summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2021-04-11 15:01:52 +0300
committerTimo Teräs <timo.teras@iki.fi>2021-04-11 15:08:17 +0300
commit6552a1d3f8126d858d64c75fa3c1eb049d8bf235 (patch)
tree95ab25d8881aaafff88b11c2511c57f7e0a16fa2 /src
parent1096e3ce154e0a702ca7fdec783452b96b79d78c (diff)
downloadapk-tools-6552a1d3f8126d858d64c75fa3c1eb049d8bf235.tar.gz
apk-tools-6552a1d3f8126d858d64c75fa3c1eb049d8bf235.tar.bz2
apk-tools-6552a1d3f8126d858d64c75fa3c1eb049d8bf235.tar.xz
apk-tools-6552a1d3f8126d858d64c75fa3c1eb049d8bf235.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. (cherry picked from commit 3c339a74d1b9dba23d60d6c769d99227d75cc6dc)
Diffstat (limited to 'src')
-rw-r--r--src/io.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/src/io.c b/src/io.c
index 8aac019..81050a4 100644
--- a/src/io.c
+++ b/src/io.c
@@ -725,8 +725,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. */
@@ -1012,6 +1014,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
@@ -1030,8 +1045,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);
@@ -1073,8 +1088,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);