Index: lib/libc/gen/getutxent.c =================================================================== --- lib/libc/gen/getutxent.c +++ lib/libc/gen/getutxent.c @@ -28,10 +28,12 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" +#include #include #include #include #include +#include #include #include #include @@ -41,15 +43,48 @@ #ifdef __NO_TLS static FILE *uf = NULL; static int udb; +static int varlog_fd = -1; +static int varrun_fd = -1; #else static _Thread_local FILE *uf = NULL; static _Thread_local int udb; +static _Thread_local int varlog_fd = -1; +static _Thread_local int varrun_fd = -1; #endif +static int +cache_directory_fds(void) +{ + cap_rights_t rights; + + if (varlog_fd < 0) { + varlog_fd = _open("/var/log", O_RDONLY); + if (varlog_fd < 0) + return (-1); + cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, + CAP_LOOKUP, CAP_READ); + if (cap_rights_limit(varlog_fd, &rights) < 0 && + errno != ENOSYS) + return (-1); + } + if (varrun_fd < 0) { + varrun_fd = _open("/var/run", O_RDONLY); + if (varrun_fd < 0) + return (-1); + cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, + CAP_LOOKUP, CAP_READ); + if (cap_rights_limit(varrun_fd, &rights) < 0 && + errno != ENOSYS) + return (-1); + } + return (0); +} + int setutxdb(int db, const char *file) { struct stat sb; + int fd, dirfd; switch (db) { case UTXDB_ACTIVE: @@ -69,9 +104,22 @@ return (-1); } + if (cache_directory_fds() < 0) + return (-1); + if (uf != NULL) fclose(uf); - uf = fopen(file, "re"); + + if (strncmp(file, "/var/log/", 9) == 0) + dirfd = varlog_fd; + else + dirfd = varrun_fd; + + fd = _openat(dirfd, &file[9], O_RDONLY | O_CLOEXEC); + if (fd < 0) + return (-1); + + uf = fdopen(fd, "re"); if (uf == NULL) return (-1);