autofs-5.1.9 - move open close on exec functions to autofs library From: Ian Kent Move the open close on exec functions to the autofs library. Signed-off-by: Ian Kent --- CHANGELOG | 1 daemon/spawn.c | 208 ------------------------------------------- include/automount.h | 2 include/misc.h | 32 +++++++ lib/Makefile | 4 - lib/misc.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 280 insertions(+), 211 deletions(-) create mode 100644 include/misc.h create mode 100644 lib/misc.c diff --git a/CHANGELOG b/CHANGELOG index 883e51390..aa9fa182a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -59,6 +59,7 @@ - fix sublink option check length in update_with_defaults(). - dont assume non null tree node in tree_free(). - add missing cache_unlock() in umount_subtree_mounts(). +- move open close on exec functions to autofs library. 02/11/2023 autofs-5.1.9 - fix kernel mount status notification. diff --git a/daemon/spawn.c b/daemon/spawn.c index 452a18d0c..3d185e9d3 100644 --- a/daemon/spawn.c +++ b/daemon/spawn.c @@ -31,7 +31,6 @@ #include "automount.h" static pthread_mutex_t spawn_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER; #define SPAWN_OPT_NONE 0x0000 #define SPAWN_OPT_LOCK 0x0001 @@ -39,213 +38,6 @@ static pthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER; #define MTAB_LOCK_RETRIES 3 -void dump_core(void) -{ - sigset_t segv; - - sigemptyset(&segv); - sigaddset(&segv, SIGSEGV); - pthread_sigmask(SIG_UNBLOCK, &segv, NULL); - - raise(SIGSEGV); -} - -void open_mutex_lock(void) -{ - int _o_lock = pthread_mutex_lock(&open_mutex); - if (_o_lock) - fatal(_o_lock); -} - -void open_mutex_unlock(void) -{ - int _o_unlock = pthread_mutex_unlock(&open_mutex); - if (_o_unlock) - fatal(_o_unlock); -} - -/* - * Use CLOEXEC flag for open(), pipe(), fopen() (read-only case) and - * socket() if possible. - */ -static int cloexec_works = 0; - -static void check_cloexec(int fd) -{ - if (cloexec_works == 0) { - int fl = fcntl(fd, F_GETFD); - if (fl != -1) - cloexec_works = (fl & FD_CLOEXEC) ? 1 : -1; - } - if (cloexec_works > 0) - return; - fcntl(fd, F_SETFD, FD_CLOEXEC); - return; -} - -int open_fd(const char *path, int flags) -{ - int fd; - - open_mutex_lock(); -#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) - if (cloexec_works != -1) - flags |= O_CLOEXEC; -#endif - fd = open(path, flags); - if (fd == -1) { - char buf[MAX_ERR_BUF]; - char *estr; - - open_mutex_unlock(); - estr = strerror_r(errno, buf, sizeof(buf)); - logerr("failed to open file: %s", estr); - return -1; - } - check_cloexec(fd); - open_mutex_unlock(); - return fd; -} - -int open_fd_mode(const char *path, int flags, int mode) -{ - int fd; - - open_mutex_lock(); -#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) - if (cloexec_works != -1) - flags |= O_CLOEXEC; -#endif - fd = open(path, flags, mode); - if (fd == -1) { - char buf[MAX_ERR_BUF]; - char *estr; - - open_mutex_unlock(); - estr = strerror_r(errno, buf, sizeof(buf)); - logerr("failed to open file: %s", estr); - return -1; - } - check_cloexec(fd); - open_mutex_unlock(); - return fd; -} - -int open_pipe(int pipefd[2]) -{ - char buf[MAX_ERR_BUF]; - char *estr; - int ret; - - open_mutex_lock(); -#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) && defined(HAVE_PIPE2) - if (cloexec_works != -1) { - ret = pipe2(pipefd, O_CLOEXEC); - if (ret != -1) - goto done; - if (errno != EINVAL) - goto err; - } -#endif - ret = pipe(pipefd); - if (ret == -1) - goto err; - check_cloexec(pipefd[0]); - check_cloexec(pipefd[1]); -done: - open_mutex_unlock(); - return 0; -err: - open_mutex_unlock(); - estr = strerror_r(errno, buf, sizeof(buf)); - logerr("failed to open pipe: %s", estr); - return -1; -} - -int open_sock(int domain, int type, int protocol) -{ - int fd; - - open_mutex_lock(); -#ifdef SOCK_CLOEXEC - if (cloexec_works != -1) - type |= SOCK_CLOEXEC; -#endif - fd = socket(domain, type, protocol); - if (fd == -1) { - char buf[MAX_ERR_BUF]; - char *estr; - - open_mutex_unlock(); - estr = strerror_r(errno, buf, sizeof(buf)); - logerr("failed to open socket: %s", estr); - return -1; - } - check_cloexec(fd); - open_mutex_unlock(); - return fd; -} - -FILE *open_fopen_r(const char *path) -{ - FILE *f; - - open_mutex_lock(); -#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) - if (cloexec_works != -1) { - f = fopen(path, "re"); - if (f != NULL) { - check_cloexec(fileno(f)); - open_mutex_unlock(); - return f; - } - } -#endif - f = fopen(path, "r"); - if (f == NULL) { - char buf[MAX_ERR_BUF]; - char *estr; - - open_mutex_unlock(); - estr = strerror_r(errno, buf, sizeof(buf)); - logerr("failed to open file: %s", estr); - return NULL; - } - check_cloexec(fileno(f)); - open_mutex_unlock(); - return f; -} - -FILE *open_setmntent_r(const char *table) -{ - FILE *tab; - - open_mutex_lock(); -#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) - if (cloexec_works != -1) { - tab = setmntent(table, "re"); - if (tab != NULL) { - check_cloexec(fileno(tab)); - open_mutex_unlock(); - return tab; - } - } -#endif - tab = fopen(table, "r"); - if (tab == NULL) { - char buf[MAX_ERR_BUF]; - char *estr; - - open_mutex_unlock(); - estr = strerror_r(errno, buf, sizeof(buf)); - logerr("failed to open mount table: %s", estr); - return NULL; - } - check_cloexec(fileno(tab)); - open_mutex_unlock(); - return tab; -} - /* * Used by subprocesses which exec to avoid carrying over the main * daemon's signalling environment diff --git a/include/automount.h b/include/automount.h index fd7219d52..7b7ee41b3 100644 --- a/include/automount.h +++ b/include/automount.h @@ -37,6 +37,7 @@ #include "parse_subs.h" #include "dev-ioctl-lib.h" #include "parse_amd.h" +#include "misc.h" #ifdef WITH_DMALLOC #include @@ -237,7 +238,6 @@ int free_argv(int argc, const char **argv); struct pending_args; void set_thread_mount_request_log_id(struct pending_args *mt); -void dump_core(void); int aquire_lock(void); void release_lock(void); int spawnl(unsigned logopt, const char *prog, ...); diff --git a/include/misc.h b/include/misc.h new file mode 100644 index 000000000..d02058f00 --- /dev/null +++ b/include/misc.h @@ -0,0 +1,32 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2023 Ian Kent + * Copyright 2023 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, + * USA; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ----------------------------------------------------------------------- */ +#ifndef MISC_H +#define MISC_H +#include + +void dump_core(void); +void open_mutex_lock(void); +void open_mutex_unlock(void); +int open_fd(const char *path, int flags); +int open_fd_mode(const char *path, int flags, int mode); +int open_pipe(int pipefd[2]); +int open_sock(int domain, int type, int protocol); +FILE *open_fopen_r(const char *path); +FILE *open_setmntent_r(const char *table); +#endif diff --git a/lib/Makefile b/lib/Makefile index d18c67b58..8ee7c012f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -7,10 +7,10 @@ include ../Makefile.rules SRCS = cache.c cat_path.c rpc_subs.c mounts.c log.c nsswitch.c \ nss_tok.c nss_parse.tab.c args.c alarm.c macros.c defaults.c \ - parse_subs.c dev-ioctl-lib.c + parse_subs.c dev-ioctl-lib.c misc.c OBJS = cache.o cat_path.o rpc_subs.o mounts.o log.o nsswitch.o \ nss_tok.o nss_parse.tab.o args.o alarm.o macros.o defaults.o \ - parse_subs.o dev-ioctl-lib.o + parse_subs.o dev-ioctl-lib.o misc.o YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h diff --git a/lib/misc.c b/lib/misc.c new file mode 100644 index 000000000..453d713b6 --- /dev/null +++ b/lib/misc.c @@ -0,0 +1,244 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2023 Ian Kent + * Copyright 2023 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, + * USA; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ----------------------------------------------------------------------- */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "misc.h" + +#define MAX_ERR_BUF 128 + +static pthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER; + +void dump_core(void) +{ + sigset_t segv; + + sigemptyset(&segv); + sigaddset(&segv, SIGSEGV); + pthread_sigmask(SIG_UNBLOCK, &segv, NULL); + + raise(SIGSEGV); +} + +void open_mutex_lock(void) +{ + int _o_lock = pthread_mutex_lock(&open_mutex); + if (_o_lock) + fatal(_o_lock); +} + +void open_mutex_unlock(void) +{ + int _o_unlock = pthread_mutex_unlock(&open_mutex); + if (_o_unlock) + fatal(_o_unlock); +} + +/* + * Use CLOEXEC flag for open(), pipe(), fopen() (read-only case) and + * socket() if possible. + */ +static int cloexec_works = 0; + +static void check_cloexec(int fd) +{ + if (cloexec_works == 0) { + int fl = fcntl(fd, F_GETFD); + if (fl != -1) + cloexec_works = (fl & FD_CLOEXEC) ? 1 : -1; + } + if (cloexec_works > 0) + return; + fcntl(fd, F_SETFD, FD_CLOEXEC); + return; +} + +int open_fd(const char *path, int flags) +{ + int fd; + + open_mutex_lock(); +#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) + if (cloexec_works != -1) + flags |= O_CLOEXEC; +#endif + fd = open(path, flags); + if (fd == -1) { + char buf[MAX_ERR_BUF]; + char *estr; + + open_mutex_unlock(); + estr = strerror_r(errno, buf, sizeof(buf)); + logerr("failed to open file: %s", estr); + return -1; + } + check_cloexec(fd); + open_mutex_unlock(); + return fd; +} + +int open_fd_mode(const char *path, int flags, int mode) +{ + int fd; + + open_mutex_lock(); +#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) + if (cloexec_works != -1) + flags |= O_CLOEXEC; +#endif + fd = open(path, flags, mode); + if (fd == -1) { + char buf[MAX_ERR_BUF]; + char *estr; + + open_mutex_unlock(); + estr = strerror_r(errno, buf, sizeof(buf)); + logerr("failed to open file: %s", estr); + return -1; + } + check_cloexec(fd); + open_mutex_unlock(); + return fd; +} + +int open_pipe(int pipefd[2]) +{ + char buf[MAX_ERR_BUF]; + char *estr; + int ret; + + open_mutex_lock(); +#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) && defined(HAVE_PIPE2) + if (cloexec_works != -1) { + ret = pipe2(pipefd, O_CLOEXEC); + if (ret != -1) + goto done; + if (errno != EINVAL) + goto err; + } +#endif + ret = pipe(pipefd); + if (ret == -1) + goto err; + check_cloexec(pipefd[0]); + check_cloexec(pipefd[1]); +#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) && defined(HAVE_PIPE2) +done: +#endif + open_mutex_unlock(); + return 0; +err: + open_mutex_unlock(); + estr = strerror_r(errno, buf, sizeof(buf)); + logerr("failed to open pipe: %s", estr); + return -1; +} + +int open_sock(int domain, int type, int protocol) +{ + int fd; + + open_mutex_lock(); +#ifdef SOCK_CLOEXEC + if (cloexec_works != -1) + type |= SOCK_CLOEXEC; +#endif + fd = socket(domain, type, protocol); + if (fd == -1) { + char buf[MAX_ERR_BUF]; + char *estr; + + open_mutex_unlock(); + estr = strerror_r(errno, buf, sizeof(buf)); + logerr("failed to open socket: %s", estr); + return -1; + } + check_cloexec(fd); + open_mutex_unlock(); + return fd; +} + +FILE *open_fopen_r(const char *path) +{ + FILE *f; + + open_mutex_lock(); +#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) + if (cloexec_works != -1) { + f = fopen(path, "re"); + if (f != NULL) { + check_cloexec(fileno(f)); + open_mutex_unlock(); + return f; + } + } +#endif + f = fopen(path, "r"); + if (f == NULL) { + char buf[MAX_ERR_BUF]; + char *estr; + + open_mutex_unlock(); + estr = strerror_r(errno, buf, sizeof(buf)); + logerr("failed to open file: %s", estr); + return NULL; + } + check_cloexec(fileno(f)); + open_mutex_unlock(); + return f; +} + +FILE *open_setmntent_r(const char *table) +{ + FILE *tab; + + open_mutex_lock(); +#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) + if (cloexec_works != -1) { + tab = setmntent(table, "re"); + if (tab != NULL) { + check_cloexec(fileno(tab)); + open_mutex_unlock(); + return tab; + } + } +#endif + tab = fopen(table, "r"); + if (tab == NULL) { + char buf[MAX_ERR_BUF]; + char *estr; + + open_mutex_unlock(); + estr = strerror_r(errno, buf, sizeof(buf)); + logerr("failed to open mount table: %s", estr); + return NULL; + } + check_cloexec(fileno(tab)); + open_mutex_unlock(); + return tab; +}