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;
|
return -1;
|
||||||
|
|
||||||
dir = fdopendir(dirfd);
|
dir = fdopendir(dirfd);
|
||||||
if (dir == NULL)
|
if (!dir) {
|
||||||
|
close(dirfd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* We get called here with dup():ed fd. Since they all refer to
|
/* We get called here with dup():ed fd. Since they all refer to
|
||||||
* same object, we need to rewind so subsequent calls work. */
|
* 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;
|
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)
|
uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t default_uid)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_FGETPWENT_R
|
#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->genid = idc->genid;
|
||||||
ci->uid = -1;
|
ci->uid = -1;
|
||||||
|
|
||||||
in = fdopen(openat(idc->root_fd, "etc/passwd", O_RDONLY|O_CLOEXEC), "r");
|
in = fopenat(idc->root_fd, "etc/passwd");
|
||||||
if (in != NULL) {
|
if (in) {
|
||||||
do {
|
do {
|
||||||
#ifdef HAVE_FGETPWENT_R
|
#ifdef HAVE_FGETPWENT_R
|
||||||
fgetpwent_r(in, &pwent, buf, sizeof(buf), &pwd);
|
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->genid = idc->genid;
|
||||||
ci->gid = -1;
|
ci->gid = -1;
|
||||||
|
|
||||||
in = fdopen(openat(idc->root_fd, "etc/group", O_RDONLY|O_CLOEXEC), "r");
|
in = fopenat(idc->root_fd, "etc/group");
|
||||||
if (in != NULL) {
|
if (in) {
|
||||||
do {
|
do {
|
||||||
#ifdef HAVE_FGETGRENT_R
|
#ifdef HAVE_FGETGRENT_R
|
||||||
fgetgrent_r(in, &grent, buf, sizeof(buf), &grp);
|
fgetgrent_r(in, &grent, buf, sizeof(buf), &grp);
|
||||||
|
|
Loading…
Reference in New Issue