Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
netatalk.26996
netatalk-CVE-2022-23123,23122,23124,0194.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File netatalk-CVE-2022-23123,23122,23124,0194.patch of Package netatalk.26996
From 4a8f6c964d5ca86df27c50e50dc1b60d39c9b76d Mon Sep 17 00:00:00 2001 From: Ralph Boehme <slow@samba.org> Date: Thu, 10 Mar 2022 13:24:28 +0100 Subject: [PATCH] CVE-2022-23123: libatalk: harden ad_entry() Also fixes: - CVE-2022-23122 - CVE-2022-23124 - CVE-2022-0194 Signed-off-by: Ralph Boehme <slow@samba.org> --- include/atalk/adouble.h | 3 +- libatalk/adouble/ad_open.c | 117 +++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) Index: netatalk-3.1.0/include/atalk/adouble.h =================================================================== --- netatalk-3.1.0.orig/include/atalk/adouble.h 2013-10-28 16:46:51.000000000 +0100 +++ netatalk-3.1.0/include/atalk/adouble.h 2022-03-22 13:40:03.279889725 +0100 @@ -110,6 +110,8 @@ #define ADEDLEN_MACFILEI 4 #define ADEDLEN_PRODOSFILEI 8 #define ADEDLEN_MSDOSFILEI 2 +#define ADEDLEN_ICONBW 128 +#define ADEDLEN_ICONCOL 1024 #define ADEDLEN_DID 4 #define ADEDLEN_PRIVDEV 8 #define ADEDLEN_PRIVINO 8 @@ -222,6 +224,7 @@ struct adouble { char *ad_name; /* mac name (maccharset or UTF8-MAC) */ struct adouble_fops *ad_ops; uint16_t ad_open_forks; /* open forks (by others) */ + size_t valid_data_len; /* Bytes read into ad_data */ char ad_data[AD_DATASZ_MAX]; }; @@ -362,7 +365,6 @@ struct adouble { #define ad_getentrylen(ad,eid) ((ad)->ad_eid[(eid)].ade_len) #define ad_setentrylen(ad,eid,len) ((ad)->ad_eid[(eid)].ade_len = (len)) #define ad_setentryoff(ad,eid,off) ((ad)->ad_eid[(eid)].ade_off = (off)) -#define ad_entry(ad,eid) ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off) #define ad_get_RF_flags(ad) ((ad)->ad_rfp->adf_flags) #define ad_get_MD_flags(ad) ((ad)->ad_mdp->adf_flags) @@ -389,6 +391,7 @@ extern void ad_unlock(struct adouble *, extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int fork); /* ad_open.c */ +extern void *ad_entry(const struct adouble *ad, int eid); extern off_t ad_getentryoff(const struct adouble *ad, int eid); extern const char *adflags2logstr(int adflags); extern int ad_setfuid (const uid_t ); Index: netatalk-3.1.0/libatalk/adouble/ad_open.c =================================================================== --- netatalk-3.1.0.orig/libatalk/adouble/ad_open.c 2022-03-22 13:40:03.271889679 +0100 +++ netatalk-3.1.0/libatalk/adouble/ad_open.c 2022-03-22 13:40:03.279889725 +0100 @@ -420,6 +420,7 @@ static int parse_entries(struct adouble ad->ad_eid[eid].ade_len = len; } + ad->valid_data_len = valid_data_len; return 0; } @@ -1417,6 +1418,122 @@ static int ad_open_rf(const char *path, * API functions ********************************************************************************* */ +/* + * All entries besides FinderInfo and resource fork must fit into the + * buffer. FinderInfo is special as it may be larger then the default 32 bytes + * if it contains marshalled xattrs, which we will fixup that in + * ad_convert(). The first 32 bytes however must also be part of the buffer. + * + * The resource fork is never accessed directly by the ad_data buf. + */ +static bool ad_entry_check_size(uint32_t eid, + size_t bufsize, + uint32_t off, + uint32_t got_len) +{ + struct { + off_t expected_len; + bool fixed_size; + bool minimum_size; + } ad_checks[] = { + [ADEID_DFORK] = {-1, false, false}, /* not applicable */ + [ADEID_RFORK] = {-1, false, false}, /* no limit */ + [ADEID_NAME] = {ADEDLEN_NAME, false, false}, + [ADEID_COMMENT] = {ADEDLEN_COMMENT, false, false}, + [ADEID_ICONBW] = {ADEDLEN_ICONBW, true, false}, + [ADEID_ICONCOL] = {ADEDLEN_ICONCOL, false, false}, + [ADEID_FILEI] = {ADEDLEN_FILEI, true, false}, + [ADEID_FILEDATESI] = {ADEDLEN_FILEDATESI, true, false}, + [ADEID_FINDERI] = {ADEDLEN_FINDERI, false, true}, + [ADEID_MACFILEI] = {ADEDLEN_MACFILEI, true, false}, + [ADEID_PRODOSFILEI] = {ADEDLEN_PRODOSFILEI, true, false}, + [ADEID_MSDOSFILEI] = {ADEDLEN_MSDOSFILEI, true, false}, + [ADEID_SHORTNAME] = {ADEDLEN_SHORTNAME, false, false}, + [ADEID_AFPFILEI] = {ADEDLEN_AFPFILEI, true, false}, + [ADEID_DID] = {ADEDLEN_DID, true, false}, + [ADEID_PRIVDEV] = {ADEDLEN_PRIVDEV, true, false}, + [ADEID_PRIVINO] = {ADEDLEN_PRIVINO, true, false}, + [ADEID_PRIVSYN] = {ADEDLEN_PRIVSYN, true, false}, + [ADEID_PRIVID] = {ADEDLEN_PRIVID, true, false}, + }; + uint32_t required_len; + + if (eid >= ADEID_MAX) { + return false; + } + if (got_len == 0) { + /* Entry present, but empty, allow */ + return true; + } + if (ad_checks[eid].expected_len == 0) { + /* + * Shouldn't happen: implicitly initialized to zero because + * explicit initializer missing. + */ + return false; + } + if (ad_checks[eid].expected_len == -1) { + /* Unused or no limit */ + return true; + } + if (ad_checks[eid].fixed_size) { + if (ad_checks[eid].expected_len != got_len) { + /* Wrong size fo fixed size entry. */ + return false; + } + required_len = got_len; + } else { + if (ad_checks[eid].minimum_size) { + if (got_len < ad_checks[eid].expected_len) { + /* + * Too small for variable sized entry with + * minimum size. + */ + return false; + } + required_len = got_len; + } else { + if (got_len > ad_checks[eid].expected_len) { + /* Too big for variable sized entry. */ + return false; + } + /* + * Expect the buffer to provide enough room for the maximum possible + * size. + */ + required_len = ad_checks[eid].expected_len; + } + } + if (off + required_len < off) { + /* wrap around */ + return false; + } + if (off + required_len > bufsize) { + /* overflow */ + return false; + } + return true; +} + +void *ad_entry(const struct adouble *ad, int eid) +{ + size_t bufsize = ad->valid_data_len; + off_t off = ad_getentryoff(ad, eid); + size_t len = ad_getentrylen(ad, eid); + bool valid; + + valid = ad_entry_check_size(eid, bufsize, off, len); + if (!valid) { + return NULL; + } + + if (off == 0 || len == 0) { + return NULL; + } + + return ((struct adouble *)ad)->ad_data + off; +} + off_t ad_getentryoff(const struct adouble *ad, int eid) { if (ad->ad_vers == AD_VERSION2)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor