io_archive: add bounds limit for uname and gname tar header fields
Modify apk_resolve_[ug]id to take the user/groupname as a blob, so proper length checking is done and honored. ==31584== Conditional jump or move depends on uninitialised value(s) ==31584== at 0x5C8CA5: strlen (strlen.c:17) ==31584== by 0x432575: APK_BLOB_STR (apk_blob.h:79) ==31584== by 0x4350EB: apk_resolve_uid (io.c:1112) ==31584== by 0x43696C: apk_tar_parse (io_archive.c:152) ==31584== by 0x4271BC: apk_pkg_read (package.c:929) ==31584== by 0x402D75: add_main (app_add.c:163) ==31584== by 0x40D5FF: main (apk-static.c:516) Fixes a potential crash (DoS) on a crafted TAR file. CVE-2021-30139. Reported-by: Sören Tempel <soeren+git@soeren-tempel.net> Reviewed-by: Ariadne Conill <ariadne@dereferenced.org>cute-signatures
parent
4bcd792194
commit
f7143c1766
|
@ -180,7 +180,7 @@ const char *apk_url_local_file(const char *url);
|
||||||
void apk_id_cache_init(struct apk_id_cache *idc, int root_fd);
|
void apk_id_cache_init(struct apk_id_cache *idc, int root_fd);
|
||||||
void apk_id_cache_free(struct apk_id_cache *idc);
|
void apk_id_cache_free(struct apk_id_cache *idc);
|
||||||
void apk_id_cache_reset(struct apk_id_cache *idc);
|
void apk_id_cache_reset(struct apk_id_cache *idc);
|
||||||
uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t default_uid);
|
uid_t apk_resolve_uid(struct apk_id_cache *idc, apk_blob_t username, uid_t default_uid);
|
||||||
uid_t apk_resolve_gid(struct apk_id_cache *idc, const char *groupname, uid_t default_gid);
|
uid_t apk_resolve_gid(struct apk_id_cache *idc, apk_blob_t groupname, uid_t default_gid);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
12
src/io.c
12
src/io.c
|
@ -1114,7 +1114,7 @@ static FILE *fopenat(int dirfd, const char *pathname)
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t default_uid)
|
uid_t apk_resolve_uid(struct apk_id_cache *idc, apk_blob_t username, uid_t default_uid)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_FGETPWENT_R
|
#ifdef HAVE_FGETPWENT_R
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
@ -1124,7 +1124,7 @@ uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t defa
|
||||||
struct passwd *pwd;
|
struct passwd *pwd;
|
||||||
FILE *in;
|
FILE *in;
|
||||||
|
|
||||||
ci = resolve_cache_item(&idc->uid_cache, APK_BLOB_STR(username));
|
ci = resolve_cache_item(&idc->uid_cache, username);
|
||||||
if (ci == NULL) return default_uid;
|
if (ci == NULL) return default_uid;
|
||||||
|
|
||||||
if (ci->genid != idc->genid) {
|
if (ci->genid != idc->genid) {
|
||||||
|
@ -1141,7 +1141,7 @@ uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t defa
|
||||||
#endif
|
#endif
|
||||||
if (pwd == NULL)
|
if (pwd == NULL)
|
||||||
break;
|
break;
|
||||||
if (strcmp(pwd->pw_name, username) == 0) {
|
if (apk_blob_compare(APK_BLOB_STR(pwd->pw_name), username) == 0) {
|
||||||
ci->uid = pwd->pw_uid;
|
ci->uid = pwd->pw_uid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1156,7 +1156,7 @@ uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t defa
|
||||||
return default_uid;
|
return default_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
uid_t apk_resolve_gid(struct apk_id_cache *idc, const char *groupname, uid_t default_gid)
|
uid_t apk_resolve_gid(struct apk_id_cache *idc, apk_blob_t groupname, uid_t default_gid)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_FGETGRENT_R
|
#ifdef HAVE_FGETGRENT_R
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
@ -1166,7 +1166,7 @@ uid_t apk_resolve_gid(struct apk_id_cache *idc, const char *groupname, uid_t def
|
||||||
struct group *grp;
|
struct group *grp;
|
||||||
FILE *in;
|
FILE *in;
|
||||||
|
|
||||||
ci = resolve_cache_item(&idc->gid_cache, APK_BLOB_STR(groupname));
|
ci = resolve_cache_item(&idc->gid_cache, groupname);
|
||||||
if (ci == NULL) return default_gid;
|
if (ci == NULL) return default_gid;
|
||||||
|
|
||||||
if (ci->genid != idc->genid) {
|
if (ci->genid != idc->genid) {
|
||||||
|
@ -1183,7 +1183,7 @@ uid_t apk_resolve_gid(struct apk_id_cache *idc, const char *groupname, uid_t def
|
||||||
#endif
|
#endif
|
||||||
if (grp == NULL)
|
if (grp == NULL)
|
||||||
break;
|
break;
|
||||||
if (strcmp(grp->gr_name, groupname) == 0) {
|
if (apk_blob_compare(APK_BLOB_STR(grp->gr_name), groupname) == 0) {
|
||||||
ci->gid = grp->gr_gid;
|
ci->gid = grp->gr_gid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ struct tar_header {
|
||||||
char padding[12]; /* 500-511 */
|
char padding[12]; /* 500-511 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TAR_BLOB(s) APK_BLOB_PTR_LEN(s, strnlen(s, sizeof(s)))
|
||||||
#define GET_OCTAL(s) get_octal(s, sizeof(s))
|
#define GET_OCTAL(s) get_octal(s, sizeof(s))
|
||||||
#define PUT_OCTAL(s,v) put_octal(s, sizeof(s), v)
|
#define PUT_OCTAL(s,v) put_octal(s, sizeof(s), v)
|
||||||
|
|
||||||
|
@ -149,8 +150,8 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
|
||||||
|
|
||||||
entry = (struct apk_file_info){
|
entry = (struct apk_file_info){
|
||||||
.size = GET_OCTAL(buf.size),
|
.size = GET_OCTAL(buf.size),
|
||||||
.uid = apk_resolve_uid(idc, buf.uname, GET_OCTAL(buf.uid)),
|
.uid = apk_resolve_uid(idc, TAR_BLOB(buf.uname), GET_OCTAL(buf.uid)),
|
||||||
.gid = apk_resolve_gid(idc, buf.gname, GET_OCTAL(buf.gid)),
|
.gid = apk_resolve_gid(idc, TAR_BLOB(buf.gname), GET_OCTAL(buf.gid)),
|
||||||
.mode = GET_OCTAL(buf.mode) & 07777,
|
.mode = GET_OCTAL(buf.mode) & 07777,
|
||||||
.mtime = GET_OCTAL(buf.mtime),
|
.mtime = GET_OCTAL(buf.mtime),
|
||||||
.name = entry.name,
|
.name = entry.name,
|
||||||
|
|
Loading…
Reference in New Issue