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.cute-signatures
parent
1b954e4120
commit
4bcd792194
25
src/io.c
25
src/io.c
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue