diff options
author | Timo Teräs <timo.teras@iki.fi> | 2021-04-11 15:01:52 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2021-04-11 15:06:49 +0300 |
commit | 4bcd792194c23fd73912a567101af5fda6e860da (patch) | |
tree | e45bef29dbfe031a6abb5360c72b183177858856 /src/io.c | |
parent | 1b954e4120c1565134e9d81296e4fec3ce8e7a7c (diff) | |
download | apk-tools-4bcd792194c23fd73912a567101af5fda6e860da.tar.gz apk-tools-4bcd792194c23fd73912a567101af5fda6e860da.tar.bz2 apk-tools-4bcd792194c23fd73912a567101af5fda6e860da.tar.xz apk-tools-4bcd792194c23fd73912a567101af5fda6e860da.zip |
io: fix fd leak in error handling paths
apk_dir_foreach_file and apk_resolve_[ug]id needs to free the fd in
case fdopen/fdopendir fails. Additionally this does not rely on fdopen
to fail if openat() returned -1, making sure that we don't call any
syscalls with invalid file handle.
Diffstat (limited to 'src/io.c')
-rw-r--r-- | src/io.c | 25 |
1 files changed, 20 insertions, 5 deletions
@@ -808,8 +808,10 @@ int apk_dir_foreach_file(int dirfd, apk_dir_file_cb cb, void *ctx) return -1; dir = fdopendir(dirfd); - if (dir == NULL) + if (!dir) { + close(dirfd); return -1; + } /* We get called here with dup():ed fd. Since they all refer to * same object, we need to rewind so subsequent calls work. */ @@ -1099,6 +1101,19 @@ void apk_id_cache_reset(struct apk_id_cache *idc) idc->genid = 1; } +static FILE *fopenat(int dirfd, const char *pathname) +{ + FILE *f; + int fd; + + fd = openat(dirfd, pathname, O_RDONLY|O_CLOEXEC); + if (fd < 0) return NULL; + + f = fdopen(fd, "r"); + if (!f) close(fd); + return f; +} + uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t default_uid) { #ifdef HAVE_FGETPWENT_R @@ -1116,8 +1131,8 @@ uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t defa ci->genid = idc->genid; ci->uid = -1; - in = fdopen(openat(idc->root_fd, "etc/passwd", O_RDONLY|O_CLOEXEC), "r"); - if (in != NULL) { + in = fopenat(idc->root_fd, "etc/passwd"); + if (in) { do { #ifdef HAVE_FGETPWENT_R fgetpwent_r(in, &pwent, buf, sizeof(buf), &pwd); @@ -1158,8 +1173,8 @@ uid_t apk_resolve_gid(struct apk_id_cache *idc, const char *groupname, uid_t def ci->genid = idc->genid; ci->gid = -1; - in = fdopen(openat(idc->root_fd, "etc/group", O_RDONLY|O_CLOEXEC), "r"); - if (in != NULL) { + in = fopenat(idc->root_fd, "etc/group"); + if (in) { do { #ifdef HAVE_FGETGRENT_R fgetgrent_r(in, &grent, buf, sizeof(buf), &grp); |