From 8838c4a6f8e712fcd54b6d0ab110e9962cbf8d02 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Mon, 20 Mar 2023 12:11:39 +0800 Subject: [PATCH] - add changes for bug 2177998. --- ...ix-incorrect-print-format-specifiers.patch | 40 ++ ...-add-command-pipe-handling-functions.patch | 310 ++++++++++ ...function-master_find_mapent_by_devid.patch | 125 ++++ ...fs-5.1.8-dont-close-lookup-at-umount.patch | 47 ++ autofs-5.1.8-dont-delay-expire.patch | 94 +++ ...nate-last-remaining-state_pipe-usage.patch | 292 +++++++++ autofs-5.1.8-fix-deadlock-in-lookups.patch | 141 +++++ ...1.8-fix-mount-tree-startup-reconnect.patch | 54 ++ ....8-fix-return-status-of-mount_autofs.patch | 43 ++ ...read-in-handle_cmd_pipe_fifo_message.patch | 46 ++ ...get-rid-of-unused-field-submnt_count.patch | 69 +++ ...md-mapent-search-function-name-clear.patch | 81 +++ ....1.8-make-signal-handling-consistent.patch | 75 +++ ...ename-statemachine-to-signal_handler.patch | 63 ++ ...tch-to-application-wide-command-pipe.patch | 568 ++++++++++++++++++ ...tofs_point-when-setting-log-priotity.patch | 155 +++++ autofs.spec | 56 +- 17 files changed, 2258 insertions(+), 1 deletion(-) create mode 100644 autofs-5.1.7-fix-incorrect-print-format-specifiers.patch create mode 100644 autofs-5.1.8-add-command-pipe-handling-functions.patch create mode 100644 autofs-5.1.8-add-function-master_find_mapent_by_devid.patch create mode 100644 autofs-5.1.8-dont-close-lookup-at-umount.patch create mode 100644 autofs-5.1.8-dont-delay-expire.patch create mode 100644 autofs-5.1.8-eliminate-last-remaining-state_pipe-usage.patch create mode 100644 autofs-5.1.8-fix-deadlock-in-lookups.patch create mode 100644 autofs-5.1.8-fix-mount-tree-startup-reconnect.patch create mode 100644 autofs-5.1.8-fix-return-status-of-mount_autofs.patch create mode 100644 autofs-5.1.8-fix-unterminated-read-in-handle_cmd_pipe_fifo_message.patch create mode 100644 autofs-5.1.8-get-rid-of-unused-field-submnt_count.patch create mode 100644 autofs-5.1.8-make-amd-mapent-search-function-name-clear.patch create mode 100644 autofs-5.1.8-make-signal-handling-consistent.patch create mode 100644 autofs-5.1.8-rename-statemachine-to-signal_handler.patch create mode 100644 autofs-5.1.8-switch-to-application-wide-command-pipe.patch create mode 100644 autofs-5.1.8-use-device-id-to-locate-autofs_point-when-setting-log-priotity.patch diff --git a/autofs-5.1.7-fix-incorrect-print-format-specifiers.patch b/autofs-5.1.7-fix-incorrect-print-format-specifiers.patch new file mode 100644 index 0000000..cc9feee --- /dev/null +++ b/autofs-5.1.7-fix-incorrect-print-format-specifiers.patch @@ -0,0 +1,40 @@ +autofs-5.1.7 - fix incorrect print format specifiers in get_pkt() + +From: Ian Kent + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 4 ++-- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -115,6 +115,7 @@ + - make amd mapent search function name clear. + - rename statemachine() to signal_handler(). + - make signal handling consistent. ++- fix incorrect print format specifiers in get_pkt(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -1105,7 +1105,7 @@ static int get_pkt(struct autofs_point * + estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, + "read error on state pipe, " +- "read %u, error %s", ++ "read %lu, error %s", + read, estr); + st_mutex_unlock(); + continue; +@@ -1123,7 +1123,7 @@ static int get_pkt(struct autofs_point * + estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, + "read error on request pipe, " +- "read %u, expected %u error %s", ++ "read %lu, expected %lu error %s", + read, kpkt_len, estr); + } + return read; diff --git a/autofs-5.1.8-add-command-pipe-handling-functions.patch b/autofs-5.1.8-add-command-pipe-handling-functions.patch new file mode 100644 index 0000000..3dad060 --- /dev/null +++ b/autofs-5.1.8-add-command-pipe-handling-functions.patch @@ -0,0 +1,310 @@ +autofs-5.1.8 - add command pipe handling functions + +From: Ian Kent + +In order to use a single file handle for a command pipe the pipe needs +to be independent of the kernel message packet handling function. + +Add most of the functions needed for this as preperation. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + daemon/automount.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 270 insertions(+) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -119,6 +119,7 @@ + - eliminate last remaining state_pipe usage. + - add function master_find_mapent_by_devid(). + - use device id to locate autofs_point when setting log priotity. ++- add command pipe handling functions. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -60,6 +60,14 @@ unsigned int nfs_mount_uses_string_optio + static struct nfs_mount_vers vers, check = {1, 1, 1}; + + #define FIFO_BUF_SIZE 25 ++static int cmd_pipe_fifo = -1; ++ ++/* autofs cmd fifo name */ ++#define FIFO_NAME "autofs.cmd.fifo" ++const char *cmd_pipe_name = AUTOFS_FIFO_DIR "/" FIFO_NAME; ++ ++int start_cmd_pipe_handler(void); ++void finish_cmd_pipe_handler(void); + + /* autofs fifo name prefix */ + #define FIFO_NAME_PREFIX "autofs.fifo" +@@ -1650,6 +1658,267 @@ static void *signal_handler(void *arg) + } + } + ++static pthread_mutex_t cmd_pipe_mutex = PTHREAD_MUTEX_INITIALIZER; ++static unsigned int done = 0; ++static pthread_t cmd_pipe_thid; ++ ++void cmd_pipe_mutex_lock(void) ++{ ++ int status = pthread_mutex_lock(&cmd_pipe_mutex); ++ if (status) ++ fatal(status); ++} ++ ++void cmd_pipe_mutex_unlock(void) ++{ ++ int status = pthread_mutex_unlock(&cmd_pipe_mutex); ++ if (status) ++ fatal(status); ++} ++ ++static int create_cmd_pipe_fifo(void) ++{ ++ char buf[MAX_ERR_BUF]; ++ int ret = -1; ++ int fd; ++ ++ if (cmd_pipe_fifo != -1) ++ return 0; ++ ++ ret = unlink(cmd_pipe_name); ++ if (ret != 0 && errno != ENOENT) { ++ fprintf(stderr, ++ "%s: failed to unlink command pipe. Is the " ++ "automount daemon already running?", program); ++ return ret; ++ } ++ ++ ret = mkfifo(cmd_pipe_name, S_IRUSR|S_IWUSR); ++ if (ret != 0 && errno != EEXIST) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ fprintf(stderr, "%s: mkfifo for %s failed: %s", ++ program, cmd_pipe_name, estr); ++ return ret; ++ } ++ ++ fd = open_fd(cmd_pipe_name, O_RDWR|O_NONBLOCK); ++ if (fd < 0) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ unlink(cmd_pipe_name); ++ fprintf(stderr, "%s: failed to open cwcommand pipe %s: %s", ++ program, cmd_pipe_name, estr); ++ return -1; ++ } ++ ++ cmd_pipe_fifo = fd; ++ ++ return 0; ++} ++ ++static int destroy_cmd_pipe_fifo(void) ++{ ++ char buf[MAX_ERR_BUF]; ++ int ret = -1; ++ ++ if (cmd_pipe_fifo == -1) ++ return 0; ++ ++ ret = close(cmd_pipe_fifo); ++ if (ret != 0) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ warn(LOGOPT_ANY, ++ "close for command pipe %s: %s", cmd_pipe_name, estr); ++ } ++ ++ cmd_pipe_fifo = -1; ++ ++ ret = unlink(cmd_pipe_name); ++ if (ret != 0) { ++ warn(LOGOPT_ANY, ++ "failed to unlink FIFO. Was the fifo created OK?"); ++ } ++ ++ return 0; ++} ++ ++static void handle_cmd_pipe_fifo_message(int fd) ++{ ++ struct autofs_point *ap; ++ char buffer[PIPE_BUF]; ++ char *end, *sep; ++ char buf[MAX_ERR_BUF]; ++ dev_t devid; ++ int ret; ++ long pri; ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = read(fd, &buffer, sizeof(buffer)); ++ if (ret < 0) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ warn(LOGOPT_ANY, ++ "read on command pipe returned error: %s", estr); ++ return; ++ } ++ ++ sep = strrchr(buffer, ' '); ++ if (!sep) { ++ error(LOGOPT_ANY, ++ "incorrect command pipe message format %s.", buffer); ++ return; ++ } ++ sep++; ++ ++ errno = 0; ++ devid = strtol(buffer, &end, 10); ++ if ((devid == LONG_MIN || devid == LONG_MAX) && errno == ERANGE) { ++ debug(LOGOPT_ANY, "strtol reported a range error."); ++ error(LOGOPT_ANY, "invalid command pipe message format %s.", buffer); ++ return; ++ } ++ ++ if ((devid == 0 && errno == EINVAL) || end == buffer) { ++ debug(LOGOPT_ANY, "devid id is expected to be a integer."); ++ return; ++ } ++ ++ ap = master_find_mapent_by_devid(master_list, devid); ++ if (!ap) { ++ error(LOGOPT_ANY, "can't locate autofs_point for device id %ld.", devid); ++ return; ++ } ++ ++ errno = 0; ++ pri = strtol(sep, &end, 10); ++ if ((pri == LONG_MIN || pri == LONG_MAX) && errno == ERANGE) { ++ error(ap->logopt, "failed to set log priority."); ++ error(ap->logopt, "strtol reported an %s.", ++ pri == LONG_MIN ? "underflow" : "overflow"); ++ return; ++ } ++ ++ if ((pri == 0 && errno == EINVAL) || end == sep) { ++ debug(ap->logopt, "priority is expected to be an integer " ++ "in the range 0-7 inclusive."); ++ return; ++ } ++ ++ if (pri > LOG_DEBUG || pri < LOG_EMERG) { ++ debug(ap->logopt, ++ "invalid log priority (%ld) received on fifo", pri); ++ return; ++ } ++ ++ /* ++ * OK, the message passed all of the sanity checks. The ++ * automounter actually only supports three log priorities. ++ * Everything is logged at log level debug, deamon messages ++ * and everything except debug messages are logged with the ++ * verbose setting and only error and critical messages are ++ * logged when debugging isn't enabled. ++ */ ++ if (pri >= LOG_WARNING) { ++ if (pri == LOG_DEBUG) { ++ set_log_debug_ap(ap); ++ info(ap->logopt, "debug logging set for %s", ap->path); ++ } else { ++ set_log_verbose_ap(ap); ++ info(ap->logopt, "verbose logging set for %s", ap->path); ++ } ++ } else { ++ if (ap->logopt & LOGOPT_ANY) ++ info(ap->logopt, "basic logging set for %s", ap->path); ++ set_log_norm_ap(ap); ++ } ++} ++ ++static void cmd_pipe_dummy(int sig) ++{ ++} ++ ++static void *cmd_pipe_handler(void *arg) ++{ ++ struct sigaction sa; ++ sigset_t signalset; ++ struct pollfd fds[1]; ++ int pollfds = 1; ++ char buf[MAX_ERR_BUF]; ++ char *estr; ++ ++ if (create_cmd_pipe_fifo()) ++ return NULL; ++ ++ fds[0].fd = cmd_pipe_fifo; ++ fds[0].events = POLLIN; ++ ++ sa.sa_handler = cmd_pipe_dummy; ++ sigemptyset(&sa.sa_mask); ++ sa.sa_flags = 0; ++ if (sigaction(SIGPIPE, &sa, NULL) == -1) { ++ error(LOGOPT_ANY, "failed to set signal handler %d", errno); ++ return NULL; ++ } ++ ++ sigfillset(&signalset); ++ sigdelset(&signalset, SIGPIPE); ++ ++ while (1) { ++ cmd_pipe_mutex_lock(); ++ if (done) { ++ cmd_pipe_mutex_unlock(); ++ break; ++ } ++ cmd_pipe_mutex_unlock(); ++ ++ errno = 0; ++ if (ppoll(fds, pollfds, NULL, &signalset) == -1) { ++ if (errno == EINTR) ++ continue; ++ estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ logerr("poll failed: %s", estr); ++ return NULL; ++ } ++ ++ if (fds[0].revents & POLLIN) { ++ debug(LOGOPT_ANY, "message pending on control fifo."); ++ handle_cmd_pipe_fifo_message(fds[0].fd); ++ } ++ } ++ destroy_cmd_pipe_fifo(); ++ return NULL; ++} ++ ++int start_cmd_pipe_handler(void) ++{ ++ pthread_t thid; ++ pthread_attr_t attrs; ++ pthread_attr_t *pattrs = &attrs; ++ int status; ++ ++ status = pthread_attr_init(pattrs); ++ if (status) ++ pattrs = NULL; ++ else ++ pthread_attr_setdetachstate(pattrs, PTHREAD_CREATE_DETACHED); ++ ++ status = pthread_create(&thid, pattrs, cmd_pipe_handler, NULL); ++ ++ if (pattrs) ++ pthread_attr_destroy(pattrs); ++ ++ if (!status) ++ cmd_pipe_thid = thid; ++ ++ return !status; ++} ++ ++void finish_cmd_pipe_handler(void) ++{ ++ cmd_pipe_mutex_lock(); ++ done = 1; ++ pthread_kill(cmd_pipe_thid, SIGPIPE); ++ cmd_pipe_mutex_unlock(); ++} ++ + static void return_start_status(void *arg) + { + struct startup_cond *sc; diff --git a/autofs-5.1.8-add-function-master_find_mapent_by_devid.patch b/autofs-5.1.8-add-function-master_find_mapent_by_devid.patch new file mode 100644 index 0000000..1b15f87 --- /dev/null +++ b/autofs-5.1.8-add-function-master_find_mapent_by_devid.patch @@ -0,0 +1,125 @@ +autofs-5.1.8 - add function master_find_mapent_by_devid() + +From: Ian Kent + +Add a helper function that can locate an automount given its device id. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/master.c | 28 ++++++++++++++++++++++++++++ + include/master.h | 1 + + include/mounts.h | 1 + + lib/mounts.c | 34 ++++++++++++++++++++++++++++++++++ + 5 files changed, 65 insertions(+) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -117,6 +117,7 @@ + - make signal handling consistent. + - fix incorrect print format specifiers in get_pkt(). + - eliminate last remaining state_pipe usage. ++- add function master_find_mapent_by_devid(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/master.c ++++ autofs-5.1.4/daemon/master.c +@@ -739,6 +739,34 @@ struct master_mapent *master_find_mapent + return NULL; + } + ++struct autofs_point *master_find_mapent_by_devid(struct master *master, dev_t devid) ++{ ++ struct autofs_point *ap = NULL; ++ struct list_head *head, *p; ++ ++ master_mutex_lock(); ++ ++ head = &master->mounts; ++ list_for_each(p, head) { ++ struct master_mapent *entry; ++ ++ entry = list_entry(p, struct master_mapent, list); ++ ++ if (entry->ap->dev == devid) { ++ ap = entry->ap; ++ break; ++ } ++ ++ ap = mnt_find_submount_by_devid(&entry->ap->submounts, devid); ++ if (ap) ++ break; ++ } ++ ++ master_mutex_unlock(); ++ ++ return ap; ++} ++ + static unsigned int master_partial_match_amd_mapent(struct master *master, const char *path) + { + struct list_head *head, *p; +--- autofs-5.1.4.orig/include/master.h ++++ autofs-5.1.4/include/master.h +@@ -110,6 +110,7 @@ void master_source_lock_cleanup(void *); + void master_source_current_wait(struct master_mapent *); + void master_source_current_signal(struct master_mapent *); + struct master_mapent *master_find_mapent(struct master *, const char *); ++struct autofs_point *master_find_mapent_by_devid(struct master *master, dev_t devid); + struct master_mapent *master_new_mapent(struct master *, const char *, time_t); + void master_add_mapent(struct master *, struct master_mapent *); + void master_remove_mapent(struct master_mapent *); +--- autofs-5.1.4.orig/include/mounts.h ++++ autofs-5.1.4/include/mounts.h +@@ -160,6 +160,7 @@ int ext_mount_inuse(const char *); + struct mnt_list *mnts_lookup_mount(const char *mp); + void mnts_put_mount(struct mnt_list *mnt); + struct mnt_list *mnts_find_submount(const char *path); ++struct autofs_point *mnt_find_submount_by_devid(struct list_head *submounts, dev_t devid); + struct mnt_list *mnts_add_submount(struct autofs_point *ap); + void mnts_remove_submount(const char *mp); + struct mnt_list *mnts_find_amdmount(const char *path); +--- autofs-5.1.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -1059,6 +1059,40 @@ struct mnt_list *mnts_find_submount(cons + return NULL; + } + ++static struct autofs_point *__mnt_find_submount_by_devid(struct list_head *submounts, dev_t devid) ++{ ++ struct autofs_point *ap = NULL; ++ struct list_head *p; ++ ++ list_for_each(p, submounts) { ++ struct mnt_list *this; ++ ++ this = list_entry(p, struct mnt_list, submount); ++ ++ if (this->ap->dev == devid) { ++ ap = this->ap; ++ break; ++ } ++ ++ ap = mnt_find_submount_by_devid(&this->ap->submounts, devid); ++ if (ap) ++ break; ++ } ++ ++ return ap; ++} ++ ++struct autofs_point *mnt_find_submount_by_devid(struct list_head *submounts, dev_t devid) ++{ ++ struct autofs_point *ap = NULL; ++ ++ mnts_hash_mutex_lock(); ++ ap = __mnt_find_submount_by_devid(submounts, devid); ++ mnts_hash_mutex_unlock(); ++ ++ return ap; ++} ++ + struct mnt_list *mnts_add_submount(struct autofs_point *ap) + { + struct mnt_list *this; diff --git a/autofs-5.1.8-dont-close-lookup-at-umount.patch b/autofs-5.1.8-dont-close-lookup-at-umount.patch new file mode 100644 index 0000000..0cbcde5 --- /dev/null +++ b/autofs-5.1.8-dont-close-lookup-at-umount.patch @@ -0,0 +1,47 @@ +autofs-5.1.8 - don't close lookup at umount + +From: Ian Kent + +Since map sources are reference counted they persist beyond autofs +submounts. + +Now the map source moudule lookup gets closed at submount umount and +if we are unlucky enough to be using the same map in other submounts +and a lookup is underway at the time of the umount a crash can occur. + +To resolve this it's much better to just not close the lookup at +submount umount and rely on the map source free to close the module +lookup and instances when the map source is no longer referenced. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 7 ------- + 2 files changed, 1 insertion(+), 7 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -109,6 +109,7 @@ + - improve handling of ENOENT in sss setautomntent(). + - don't immediately call function when waiting. + - fix return status of mount_autofs(). ++- don't close lookup at umount. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -737,13 +737,6 @@ static int umount_autofs(struct autofs_p + if (ap->state == ST_INIT) + return -1; + +- /* +- * Since lookup.c is lazy about closing lookup modules +- * to prevent unneeded opens, we need to clean them up +- * before umount. +- */ +- lookup_close_lookup(ap); +- + if (ap->type == LKP_INDIRECT) { + umount_all(ap); + ret = umount_autofs_indirect(ap, root); diff --git a/autofs-5.1.8-dont-delay-expire.patch b/autofs-5.1.8-dont-delay-expire.patch new file mode 100644 index 0000000..aba361b --- /dev/null +++ b/autofs-5.1.8-dont-delay-expire.patch @@ -0,0 +1,94 @@ +autofs-5.1.8 - dont delay expire + +From: Ian Kent + +There's a delay on expire of submounts that can be as much as the +expire timeout. This was originally an attempt to reduce re-reading +the map but it can cause very long delays on expire. + +So get rid of the delay and allow submounts to expire normally. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/master.c | 9 ++++----- + daemon/state.c | 30 ++++-------------------------- + 3 files changed, 9 insertions(+), 31 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -111,6 +111,7 @@ + - fix return status of mount_autofs(). + - don't close lookup at umount. + - fix deadlock in lookups. ++- dont delay expire. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/master.c ++++ autofs-5.1.4/daemon/master.c +@@ -1250,17 +1250,16 @@ int master_notify_submount(struct autofs + st_wait_task(this->ap, state, 0); + + /* +- * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or +- * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes +- * to ST_READY. ++ * If our submount gets to state ST_SHUTDOWN_PENDING or ++ * ST_SHUTDOWN_FORCE we need to wait until it goes away ++ * or changes to state ST_SHUTDOWN or ST_READY. + */ + st_mutex_lock(); + while ((sbmnt = mnts_find_submount(path))) { + struct timespec t = { 0, 300000000 }; + struct timespec r; + +- if (sbmnt->ap->state != ST_SHUTDOWN && +- sbmnt->ap->state != ST_SHUTDOWN_PENDING && ++ if (sbmnt->ap->state != ST_SHUTDOWN_PENDING && + sbmnt->ap->state != ST_SHUTDOWN_FORCE) { + ret = 0; + mnts_put_mount(sbmnt); +--- autofs-5.1.4.orig/daemon/state.c ++++ autofs-5.1.4/daemon/state.c +@@ -123,36 +123,14 @@ void expire_cleanup(void *arg) + /* + * If we're a submount and we've just pruned or + * expired everything away, try to shut down. +- * +- * Since we use the the fact that a mount will not +- * expire for at least ap->exp_timeout to avoid a +- * mount <-> expire race we need to wait before +- * letting a submount expire away. We also need +- * them to go away fairly quickly so the owner +- * mount expires in a reasonable time. Just skip +- * one expire check after it's no longer busy before +- * allowing it to shutdown. +- * +- * But if this mount point is an amd format map it +- * is better to keep the mount around longer. This +- * is because of the common heavy reuse of maps in +- * amd maps and we want to try and avoid constantly +- * re-reading large maps. + */ + if (ap->submount && !success) { + rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle); +- if (!rv && idle && ap->submount > 1) { +- struct map_source *map = ap->entry->maps; +- +- if (ap->submount > 4 || +- !(map->flags & MAP_FLAG_FORMAT_AMD)) { +- next = ST_SHUTDOWN_PENDING; +- break; +- } ++ if (!rv && idle) { ++ next = ST_SHUTDOWN_PENDING; ++ break; + } +- ap->submount++; +- } else if (ap->submount > 1) +- ap->submount = 1; ++ } + + if (ap->state == ST_EXPIRE) + conditional_alarm_add(ap, ap->exp_runfreq); diff --git a/autofs-5.1.8-eliminate-last-remaining-state_pipe-usage.patch b/autofs-5.1.8-eliminate-last-remaining-state_pipe-usage.patch new file mode 100644 index 0000000..c4fb4c0 --- /dev/null +++ b/autofs-5.1.8-eliminate-last-remaining-state_pipe-usage.patch @@ -0,0 +1,292 @@ +autofs-5.1.8 - eliminate last remaining state_pipe usage + +From: Ian Kent + +Eliminate the last remaining usage autofs mount struct state_pipe that +is used when changing state to ST_SHUTDOWN at submount exit. Ths single +usage consumes a pipe file handle pair for every autofs file system +mount. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + daemon/automount.c | 78 ++++++++++++++++++++-------------------------------- + daemon/direct.c | 2 - + daemon/indirect.c | 7 ---- + daemon/master.c | 21 ++------------ + daemon/state.c | 16 +++------- + include/automount.h | 1 + include/state.h | 1 + 8 files changed, 40 insertions(+), 87 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -116,6 +116,7 @@ + - rename statemachine() to signal_handler(). + - make signal handling consistent. + - fix incorrect print format specifiers in get_pkt(). ++- eliminate last remaining state_pipe usage. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -1063,58 +1063,51 @@ static int set_log_priority(const char * + return 0; + } + ++static void dummy(int sig) ++{ ++} ++ + static int get_pkt(struct autofs_point *ap, union autofs_v5_packet_union *pkt) + { +- struct pollfd fds[3]; +- int pollfds = 3; ++ struct sigaction sa; ++ sigset_t signalset; ++ struct pollfd fds[2]; ++ int pollfds = 2; + char buf[MAX_ERR_BUF]; + size_t read; + char *estr; + + fds[0].fd = ap->pipefd; + fds[0].events = POLLIN; +- fds[1].fd = ap->state_pipe[0]; ++ fds[1].fd = ap->logpri_fifo; + fds[1].events = POLLIN; +- fds[2].fd = ap->logpri_fifo; +- fds[2].events = POLLIN; +- if (fds[2].fd == -1) ++ if (fds[1].fd == -1) + pollfds--; + +- for (;;) { +- if (poll(fds, pollfds, -1) == -1) { +- if (errno == EINTR) +- continue; +- estr = strerror_r(errno, buf, MAX_ERR_BUF); +- logerr("poll failed: %s", estr); +- return -1; +- } +- +- if (fds[1].revents & POLLIN) { +- enum states next_state; +- size_t read_size = sizeof(next_state); +- int state_pipe; ++ sa.sa_handler = dummy; ++ sigemptyset(&sa.sa_mask); ++ sa.sa_flags = 0; ++ if (sigaction(SIGCONT, &sa, NULL) == -1) ++ error(LOGOPT_ANY, "failed to set signal handler %d", errno); + +- next_state = ST_INVAL; ++ sigfillset(&signalset); ++ sigdelset(&signalset, SIGCONT); + +- st_mutex_lock(); +- +- state_pipe = ap->state_pipe[0]; +- +- read = fullread(state_pipe, &next_state, read_size); +- if (read) { +- estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, +- "read error on state pipe, " +- "read %lu, error %s", +- read, estr); ++ for (;;) { ++ errno = 0; ++ if (ppoll(fds, pollfds, NULL, &signalset) == -1) { ++ if (errno == EINTR) { ++ st_mutex_lock(); ++ if (ap->state == ST_SHUTDOWN) { ++ st_mutex_unlock(); ++ return -1; ++ } + st_mutex_unlock(); + continue; + } +- +- st_mutex_unlock(); +- +- if (next_state == ST_SHUTDOWN) +- return -1; ++ estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ logerr("poll failed: %s", estr); ++ return -1; + } + + if (fds[0].revents & POLLIN) { +@@ -1129,9 +1122,9 @@ static int get_pkt(struct autofs_point * + return read; + } + +- if (fds[2].fd != -1 && fds[2].revents & POLLIN) { ++ if (fds[1].fd != -1 && fds[1].revents & POLLIN) { + debug(ap->logopt, "message pending on control fifo."); +- handle_fifo_message(ap, fds[2].fd); ++ handle_fifo_message(ap, fds[1].fd); + } + } + } +@@ -1191,15 +1184,6 @@ static int autofs_init_ap(struct autofs_ + ap->pipefd = pipefd[0]; + ap->kpipefd = pipefd[1]; + +- /* Pipe state changes from signal handler to main loop */ +- if (open_pipe(ap->state_pipe) < 0) { +- crit(ap->logopt, +- "failed create state pipe for autofs path %s", ap->path); +- close(ap->pipefd); +- close(ap->kpipefd); /* Close kernel pipe end */ +- return -1; +- } +- + if (create_logpri_fifo(ap) < 0) { + logmsg("could not create FIFO for path %s\n", ap->path); + logmsg("dynamic log level changes not available for %s", ap->path); +--- autofs-5.1.4.orig/daemon/direct.c ++++ autofs-5.1.4/daemon/direct.c +@@ -263,8 +263,6 @@ done: + } + pthread_cleanup_pop(1); + +- close(ap->state_pipe[0]); +- close(ap->state_pipe[1]); + if (ap->pipefd >= 0) + close(ap->pipefd); + if (ap->kpipefd >= 0) { +--- autofs-5.1.4.orig/daemon/indirect.c ++++ autofs-5.1.4/daemon/indirect.c +@@ -152,8 +152,6 @@ out_rmdir: + out_err: + if (options) + free(options); +- close(ap->state_pipe[0]); +- close(ap->state_pipe[1]); + close(ap->pipefd); + close(ap->kpipefd); + +@@ -216,11 +214,6 @@ void close_mount_fds(struct autofs_point + if (ap->submount) + lookup_source_close_ioctlfd(ap->parent, ap->path); + +- close(ap->state_pipe[0]); +- close(ap->state_pipe[1]); +- ap->state_pipe[0] = -1; +- ap->state_pipe[1] = -1; +- + if (ap->pipefd >= 0) + close(ap->pipefd); + +--- autofs-5.1.4.orig/daemon/master.c ++++ autofs-5.1.4/daemon/master.c +@@ -112,8 +112,6 @@ int master_add_autofs_point(struct maste + + ap->state = ST_INIT; + +- ap->state_pipe[0] = -1; +- ap->state_pipe[1] = -1; + ap->logpri_fifo = -1; + + ap->path = strdup(entry->path); +@@ -1390,7 +1388,7 @@ static int master_do_mount(struct master + handle_mounts_startup_cond_destroy(&suc); + return 0; + } +- entry->thid = thid; ++ entry->thid = ap->thid = thid; + + handle_mounts_startup_cond_destroy(&suc); + +@@ -1474,9 +1472,6 @@ int master_mount_mounts(struct master *m + struct master_mapent *this; + struct autofs_point *ap; + struct mapent *ne, *nested; +- struct stat st; +- int state_pipe, save_errno; +- int ret; + + this = list_entry(p, struct master_mapent, list); + p = p->next; +@@ -1533,19 +1528,9 @@ int master_mount_mounts(struct master *m + } + cache_unlock(nc); + cont: +- st_mutex_lock(); +- +- state_pipe = this->ap->state_pipe[1]; +- +- /* No pipe so mount is needed */ +- ret = fstat(state_pipe, &st); +- save_errno = errno; +- +- st_mutex_unlock(); +- +- if (!ret) ++ if (ap->thid && is_mounted(this->path, MNTS_AUTOFS)) + check_update_map_sources(this, master->readall); +- else if (ret == -1 && save_errno == EBADF) { ++ else { + if (!master_do_mount(this)) { + list_del_init(&this->list); + master_free_mapent_sources(ap->entry, 1); +--- autofs-5.1.4.orig/daemon/state.c ++++ autofs-5.1.4/daemon/state.c +@@ -76,16 +76,6 @@ void dump_state_queue(void) + } + } + +-void nextstate(int statefd, enum states next) +-{ +- char buf[MAX_ERR_BUF]; +- +- if (write(statefd, &next, sizeof(next)) != sizeof(next)) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- logerr("write failed %s", estr); +- } +-} +- + /* + * Handle expire thread cleanup and return the next state the system + * should enter as a result. +@@ -655,12 +645,16 @@ static unsigned int st_force_shutdown(st + + static unsigned int st_shutdown(struct autofs_point *ap) + { ++ int ret; ++ + debug(ap->logopt, "state %d path %s", ap->state, ap->path); + + assert(ap->state == ST_SHUTDOWN_PENDING || ap->state == ST_SHUTDOWN_FORCE); + + ap->state = ST_SHUTDOWN; +- nextstate(ap->state_pipe[1], ST_SHUTDOWN); ++ ret = pthread_kill(ap->thid, SIGCONT); ++ if (ret) ++ error(LOGOPT_ANY, "error %d sending shutdown signal", ret); + + return 0; + } +--- autofs-5.1.4.orig/include/automount.h ++++ autofs-5.1.4/include/automount.h +@@ -563,7 +563,6 @@ struct autofs_point { + pthread_t exp_thread; /* Thread that is expiring */ + pthread_t readmap_thread; /* Thread that is reading maps */ + enum states state; /* Current state */ +- int state_pipe[2]; /* State change router pipe */ + struct autofs_point *parent; /* Owner of mounts list for submount */ + struct list_head mounts; /* List of autofs mounts at current level */ + unsigned int submount; /* Is this a submount */ +--- autofs-5.1.4.orig/include/state.h ++++ autofs-5.1.4/include/state.h +@@ -86,7 +86,6 @@ void st_mutex_unlock(void); + + void expire_cleanup(void *); + void expire_proc_cleanup(void *); +-void nextstate(int, enum states); + + int st_add_task(struct autofs_point *, enum states); + int __st_add_task(struct autofs_point *, enum states); diff --git a/autofs-5.1.8-fix-deadlock-in-lookups.patch b/autofs-5.1.8-fix-deadlock-in-lookups.patch new file mode 100644 index 0000000..b69a152 --- /dev/null +++ b/autofs-5.1.8-fix-deadlock-in-lookups.patch @@ -0,0 +1,141 @@ +autofs-5.1.8 - fix deadlock in lookups + +From: Ian Kent + +After adding locking to fix a crash during lookups we're seeing a +deadlock becuase of recursive calls. + +But once the lookup is open we shouldn't need to open it again during +the recursive call, fix it based on that. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + daemon/lookup.c | 62 +++++++++++++++++++++++++++++++++------------------- + daemon/master.c | 8 ++++++ + include/master.h | 1 + modules/parse_amd.c | 2 - + 5 files changed, 51 insertions(+), 23 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -110,6 +110,7 @@ + - don't immediately call function when waiting. + - fix return status of mount_autofs(). + - don't close lookup at umount. ++- fix deadlock in lookups. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/lookup.c ++++ autofs-5.1.4/daemon/lookup.c +@@ -318,31 +318,49 @@ static int do_read_map(struct autofs_poi + struct lookup_mod *lookup; + int status; + +- pthread_cleanup_push(map_module_lock_cleanup, map); +- map_module_writelock(map); +- if (!map->lookup) { +- status = open_lookup(map->type, "", map->format, +- map->argc, map->argv, &lookup); +- if (status == NSS_STATUS_SUCCESS) +- map->lookup = lookup; +- else +- debug(ap->logopt, +- "lookup module %s open failed", map->type); +- } else { +- status = map->lookup->lookup_reinit(map->format, +- map->argc, map->argv, +- &map->lookup->context); +- if (status) +- warn(ap->logopt, +- "lookup module %s reinit failed", map->type); +- } +- pthread_cleanup_pop(1); +- if (status != NSS_STATUS_SUCCESS) +- return status; +- + if (!map->stale) + return NSS_STATUS_SUCCESS; + ++ /* If this readmap is the result of trying to mount a submount ++ * the readlock may already be held if the map is the same as ++ * that of the caller. In that case the map has already been ++ * read so just skip the map open/reinit. ++ */ ++ status = map_module_try_writelock(map); ++ if (status) { ++ if (!map->lookup) { ++ error(ap->logopt, "map module lock not held as expected"); ++ return NSS_STATUS_UNAVAIL; ++ } ++ } else { ++ if (!map->lookup) { ++ pthread_cleanup_push(map_module_lock_cleanup, map); ++ status = open_lookup(map->type, "", map->format, ++ map->argc, map->argv, &lookup); ++ pthread_cleanup_pop(0); ++ if (status != NSS_STATUS_SUCCESS) { ++ map_module_unlock(map); ++ debug(ap->logopt, ++ "lookup module %s open failed", map->type); ++ return status; ++ } ++ map->lookup = lookup; ++ } else { ++ pthread_cleanup_push(map_module_lock_cleanup, map); ++ status = map->lookup->lookup_reinit(map->format, ++ map->argc, map->argv, ++ &map->lookup->context); ++ pthread_cleanup_pop(0); ++ if (status) { ++ map_module_unlock(map); ++ warn(ap->logopt, ++ "lookup module %s reinit failed", map->type); ++ return status; ++ } ++ } ++ map_module_unlock(map); ++ } ++ + master_source_current_wait(ap->entry); + ap->entry->current = map; + +--- autofs-5.1.4.orig/daemon/master.c ++++ autofs-5.1.4/daemon/master.c +@@ -72,6 +72,14 @@ void map_module_writelock(struct map_sou + fatal(status); + } + ++int map_module_try_writelock(struct map_source *map) ++{ ++ int status = pthread_rwlock_trywrlock(&map->module_lock); ++ if (status && status != EBUSY && status != EDEADLK) ++ fatal(status); ++ return status; ++} ++ + void map_module_readlock(struct map_source *map) + { + int status = pthread_rwlock_rdlock(&map->module_lock); +--- autofs-5.1.4.orig/include/master.h ++++ autofs-5.1.4/include/master.h +@@ -128,6 +128,7 @@ int master_list_empty(struct master *); + int master_done(struct master *); + int master_kill(struct master *); + void map_module_writelock(struct map_source *map); ++int map_module_try_writelock(struct map_source *map); + void map_module_readlock(struct map_source *map); + void map_module_unlock(struct map_source *map); + void map_module_lock_cleanup(void *arg); +--- autofs-5.1.4.orig/modules/parse_amd.c ++++ autofs-5.1.4/modules/parse_amd.c +@@ -1391,7 +1391,7 @@ static int do_host_mount(struct autofs_p + cache_unlock(source->mc); + + master_source_current_wait(ap->entry); +- ap->entry->current = source; ++ ap->entry->current = instance; + + map_module_readlock(instance); + lookup = instance->lookup; diff --git a/autofs-5.1.8-fix-mount-tree-startup-reconnect.patch b/autofs-5.1.8-fix-mount-tree-startup-reconnect.patch new file mode 100644 index 0000000..d2438e7 --- /dev/null +++ b/autofs-5.1.8-fix-mount-tree-startup-reconnect.patch @@ -0,0 +1,54 @@ +autofs-5.1.8 - fix mount tree startup reconnect + +From: Ian Kent + +When reconnecting to an existing mount tree at startup trying to work +out if we created the mountpoint directory uses the parent path of the +current map entry. + +But if the current map entry has no parent we should use the map entry +path. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + lib/mounts.c | 8 +++++--- + 2 files changed, 6 insertions(+), 3 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -122,6 +122,7 @@ + - add command pipe handling functions. + - switch to application wide command pipe. + - get rid of unused field submnt_count. ++- fix mount tree startup reconnect. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -2807,6 +2807,7 @@ static int remount_active_mount(struct a + int try_remount(struct autofs_point *ap, struct mapent *me, unsigned int type) + { + struct ioctl_ops *ops = get_ioctl_ops(); ++ struct mapent *mapent; + const char *path; + int ret, fd; + dev_t devid; +@@ -2841,12 +2842,13 @@ int try_remount(struct autofs_point *ap, + } + + me->flags &= ~MOUNT_FLAG_DIR_CREATED; ++ mapent = IS_MM(me) ? MM_PARENT(me) : me; + /* Direct or offset mount, key is full path */ +- if (MM_PARENT(me)->key[0] == '/') { +- if (!is_mounted(MM_PARENT(me)->key, MNTS_REAL)) ++ if (mapent->key[0] == '/') { ++ if (!is_mounted(mapent->key, MNTS_REAL)) + me->flags |= MOUNT_FLAG_DIR_CREATED; + } else { +- char *p_key = MM_PARENT(me)->key; ++ char *p_key = mapent->key; + char mp[PATH_MAX + 1]; + int len; + diff --git a/autofs-5.1.8-fix-return-status-of-mount_autofs.patch b/autofs-5.1.8-fix-return-status-of-mount_autofs.patch new file mode 100644 index 0000000..efcb834 --- /dev/null +++ b/autofs-5.1.8-fix-return-status-of-mount_autofs.patch @@ -0,0 +1,43 @@ +autofs-5.1.8 - fix return status of mount_autofs() + +From: Ian Kent + +The function mount_autofs() collects the status of mounting an autofs +file system but doesn't actually return it. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 4 ++-- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -108,6 +108,7 @@ + - fail on empty replicated host name. + - improve handling of ENOENT in sss setautomntent(). + - don't immediately call function when waiting. ++- fix return status of mount_autofs(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -1217,7 +1217,7 @@ static int autofs_init_ap(struct autofs_ + + static int mount_autofs(struct autofs_point *ap, const char *root) + { +- int status = 0; ++ int status; + + /* No need to create comms fds and command fifo if + * unlinking mounts and exiting. +@@ -1239,7 +1239,7 @@ static int mount_autofs(struct autofs_po + + st_add_task(ap, ST_READY); + +- return 0; ++ return status; + } + + static int handle_packet(struct autofs_point *ap) diff --git a/autofs-5.1.8-fix-unterminated-read-in-handle_cmd_pipe_fifo_message.patch b/autofs-5.1.8-fix-unterminated-read-in-handle_cmd_pipe_fifo_message.patch new file mode 100644 index 0000000..919cafd --- /dev/null +++ b/autofs-5.1.8-fix-unterminated-read-in-handle_cmd_pipe_fifo_message.patch @@ -0,0 +1,46 @@ +autofs-5.1.8 - fix unterminated read in handle_cmd_pipe_fifo_message() + +From: Ian Kent + +As Coverity points out the buffer in handle_cmd_pipe_fifo_message() +could be overflowed and end up not terminated so fix it. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 7 ++++++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -123,6 +123,7 @@ + - switch to application wide command pipe. + - get rid of unused field submnt_count. + - fix mount tree startup reconnect. ++- fix unterminated read in handle_cmd_pipe_fifo_message(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -1415,7 +1415,6 @@ static void handle_cmd_pipe_fifo_message + int ret; + long pri; + +- memset(buffer, 0, sizeof(buffer)); + ret = read(fd, &buffer, sizeof(buffer)); + if (ret < 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +@@ -1423,6 +1422,12 @@ static void handle_cmd_pipe_fifo_message + "read on command pipe returned error: %s", estr); + return; + } ++ if (ret >= sizeof(buffer)) { ++ error(LOGOPT_ANY, ++ "read overrun on command pipe message"); ++ return; ++ } ++ buffer[ret] = 0; + + sep = strrchr(buffer, ' '); + if (!sep) { diff --git a/autofs-5.1.8-get-rid-of-unused-field-submnt_count.patch b/autofs-5.1.8-get-rid-of-unused-field-submnt_count.patch new file mode 100644 index 0000000..01dd977 --- /dev/null +++ b/autofs-5.1.8-get-rid-of-unused-field-submnt_count.patch @@ -0,0 +1,69 @@ +autofs-5.1.8 - get rid of unused field submnt_count + +From: Ian Kent + +The autofs mount point struct field submnt_count is present but not +used, remove it. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 3 --- + daemon/master.c | 1 - + include/automount.h | 1 - + modules/mount_autofs.c | 2 -- + 5 files changed, 1 insertion(+), 7 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -121,6 +121,7 @@ + - use device id to locate autofs_point when setting log priotity. + - add command pipe handling functions. + - switch to application wide command pipe. ++- get rid of unused field submnt_count. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -1737,9 +1737,6 @@ static void handle_mounts_cleanup(void * + if (submount) { + struct mnt_list *mnt; + +- /* We are finishing up */ +- ap->parent->submnt_count--; +- + /* Submount at ap->path belongs to parent submount list. */ + mnts_remove_submount(ap->path); + /* Also remove from parent mounted list */ +--- autofs-5.1.4.orig/daemon/master.c ++++ autofs-5.1.4/daemon/master.c +@@ -152,7 +152,6 @@ int master_add_autofs_point(struct maste + + ap->parent = NULL; + ap->thid = 0; +- ap->submnt_count = 0; + ap->submount = submount; + INIT_LIST_HEAD(&ap->mounts); + INIT_LIST_HEAD(&ap->submounts); +--- autofs-5.1.4.orig/include/automount.h ++++ autofs-5.1.4/include/automount.h +@@ -565,7 +565,6 @@ struct autofs_point { + struct autofs_point *parent; /* Owner of mounts list for submount */ + struct list_head mounts; /* List of autofs mounts at current level */ + unsigned int submount; /* Is this a submount */ +- unsigned int submnt_count; /* Number of submounts */ + struct list_head submounts; /* List of child submounts */ + struct list_head amdmounts; /* List of non submount amd mounts */ + unsigned int shutdown; /* Shutdown notification */ +--- autofs-5.1.4.orig/modules/mount_autofs.c ++++ autofs-5.1.4/modules/mount_autofs.c +@@ -358,8 +358,6 @@ int mount_mount(struct autofs_point *ap, + } + nap->thid = thid; + +- ap->submnt_count++; +- + handle_mounts_startup_cond_destroy(&suc); + + return 0; diff --git a/autofs-5.1.8-make-amd-mapent-search-function-name-clear.patch b/autofs-5.1.8-make-amd-mapent-search-function-name-clear.patch new file mode 100644 index 0000000..e2e443b --- /dev/null +++ b/autofs-5.1.8-make-amd-mapent-search-function-name-clear.patch @@ -0,0 +1,81 @@ +autofs-5.1.8 - make amd mapent search function name clear + +From: Ian Kent + +When looking for amd sections in the configuration the function to +find mount entries is not named so it is clear what it's trying to +do so change its name. Also make it static since it is called only +once in the same source file. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/master.c | 7 ++++--- + include/master.h | 2 +- + 3 files changed, 6 insertions(+), 4 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -112,6 +112,7 @@ + - don't close lookup at umount. + - fix deadlock in lookups. + - dont delay expire. ++- make amd mapent search function name clear. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/master.c ++++ autofs-5.1.4/daemon/master.c +@@ -741,7 +741,7 @@ struct master_mapent *master_find_mapent + return NULL; + } + +-unsigned int master_partial_match_mapent(struct master *master, const char *path) ++static unsigned int master_partial_match_amd_mapent(struct master *master, const char *path) + { + struct list_head *head, *p; + size_t path_len = strlen(path); +@@ -755,7 +755,7 @@ unsigned int master_partial_match_mapent + + entry = list_entry(p, struct master_mapent, list); + +- entry_len = strlen(entry->path); ++ entry_len = entry->len; + cmp_len = min(entry_len, path_len); + + if (!strncmp(entry->path, path, cmp_len)) { +@@ -806,6 +806,7 @@ struct master_mapent *master_new_mapent( + return NULL; + } + entry->path = tmp; ++ entry->len = strlen(tmp); + + entry->thid = 0; + entry->age = age; +@@ -1038,7 +1039,7 @@ static void master_add_amd_mount_section + char *map = NULL; + char *opts; + +- ret = master_partial_match_mapent(master, path); ++ ret = master_partial_match_amd_mapent(master, path); + if (ret) { + /* If this amd entry is already present in the + * master map it's not a duplicate, don't issue +--- autofs-5.1.4.orig/include/master.h ++++ autofs-5.1.4/include/master.h +@@ -45,6 +45,7 @@ struct map_source { + + struct master_mapent { + char *path; ++ size_t len; + pthread_t thid; + time_t age; + struct master *master; +@@ -109,7 +110,6 @@ void master_source_lock_cleanup(void *); + void master_source_current_wait(struct master_mapent *); + void master_source_current_signal(struct master_mapent *); + struct master_mapent *master_find_mapent(struct master *, const char *); +-unsigned int master_partial_match_mapent(struct master *, const char *); + struct master_mapent *master_new_mapent(struct master *, const char *, time_t); + void master_add_mapent(struct master *, struct master_mapent *); + void master_remove_mapent(struct master_mapent *); diff --git a/autofs-5.1.8-make-signal-handling-consistent.patch b/autofs-5.1.8-make-signal-handling-consistent.patch new file mode 100644 index 0000000..512c75a --- /dev/null +++ b/autofs-5.1.8-make-signal-handling-consistent.patch @@ -0,0 +1,75 @@ +autofs-5.1.8 - make signal handling consistent + +From: Ian Kent + +There's a mixture of usage of sigprocmask() and pthread_sigmask(), change +to use the pthread versions of this for correctness. + +The only exception to this is reset_signals() which is done in a forked +process that is single threaded so it's valid to keep them as they are. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 8 ++++---- + daemon/spawn.c | 1 - + 3 files changed, 5 insertions(+), 5 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -114,6 +114,7 @@ + - dont delay expire. + - make amd mapent search function name clear. + - rename statemachine() to signal_handler(). ++- make signal handling consistent. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -2210,7 +2210,7 @@ static void do_master_list_reset(struct + + static int do_master_read_master(struct master *master, time_t *age, int wait) + { +- sigset_t signalset; ++ sigset_t signalset, savesigset; + /* Wait must be at least 1 second */ + unsigned int retry_wait = 2; + unsigned int elapsed = 0; +@@ -2221,7 +2221,7 @@ static int do_master_read_master(struct + sigaddset(&signalset, SIGTERM); + sigaddset(&signalset, SIGINT); + sigaddset(&signalset, SIGHUP); +- sigprocmask(SIG_UNBLOCK, &signalset, NULL); ++ pthread_sigmask(SIG_UNBLOCK, &signalset, &savesigset); + + while (1) { + struct timespec t = { retry_wait, 0 }; +@@ -2247,7 +2247,7 @@ static int do_master_read_master(struct + } + } + +- sigprocmask(SIG_BLOCK, &signalset, NULL); ++ pthread_sigmask(SIG_SETMASK, &savesigset, NULL); + + return ret; + } +@@ -2294,7 +2294,7 @@ int main(int argc, char *argv[]) + sigdelset(&block_sigs, SIGILL); + sigdelset(&block_sigs, SIGFPE); + sigdelset(&block_sigs, SIGTRAP); +- sigprocmask(SIG_BLOCK, &block_sigs, NULL); ++ pthread_sigmask(SIG_BLOCK, &block_sigs, NULL); + + program = argv[0]; + +--- autofs-5.1.4.orig/daemon/spawn.c ++++ autofs-5.1.4/daemon/spawn.c +@@ -46,7 +46,6 @@ void dump_core(void) + sigemptyset(&segv); + sigaddset(&segv, SIGSEGV); + pthread_sigmask(SIG_UNBLOCK, &segv, NULL); +- sigprocmask(SIG_UNBLOCK, &segv, NULL); + + raise(SIGSEGV); + } diff --git a/autofs-5.1.8-rename-statemachine-to-signal_handler.patch b/autofs-5.1.8-rename-statemachine-to-signal_handler.patch new file mode 100644 index 0000000..f09afd6 --- /dev/null +++ b/autofs-5.1.8-rename-statemachine-to-signal_handler.patch @@ -0,0 +1,63 @@ +autofs-5.1.8 - rename statemachine() to signal_handler() + +From: Ian Kent + +Rename function statemachine() to signal_handler() to align with what +the function actually does. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 10 +++++----- + 2 files changed, 6 insertions(+), 5 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -113,6 +113,7 @@ + - fix deadlock in lookups. + - dont delay expire. + - make amd mapent search function name clear. ++- rename statemachine() to signal_handler(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -74,7 +74,7 @@ int do_force_unlink = 0; /* Forceably u + static int start_pipefd[2] = {-1, -1}; + static int st_stat = 1; + static int *pst_stat = &st_stat; +-static pthread_t state_mach_thid; ++static pthread_t signal_handler_thid; + + static sigset_t block_sigs; + +@@ -1576,7 +1576,7 @@ static int do_hup_signal(struct master * + } + + /* Deal with all the signal-driven events in the state machine */ +-static void *statemachine(void *arg) ++static void *signal_handler(void *arg) + { + sigset_t signalset; + int sig; +@@ -1764,7 +1764,7 @@ static void handle_mounts_cleanup(void * + * perform final cleanup. + */ + if (!submount && !pending) +- pthread_kill(state_mach_thid, SIGTERM); ++ pthread_kill(signal_handler_thid, SIGTERM); + + master_mutex_unlock(); + +@@ -2763,8 +2763,8 @@ int main(int argc, char *argv[]) + sd_notify(1, "READY=1"); + #endif + +- state_mach_thid = pthread_self(); +- statemachine(NULL); ++ signal_handler_thid = pthread_self(); ++ signal_handler(NULL); + } + + master_kill(master_list); diff --git a/autofs-5.1.8-switch-to-application-wide-command-pipe.patch b/autofs-5.1.8-switch-to-application-wide-command-pipe.patch new file mode 100644 index 0000000..0298602 --- /dev/null +++ b/autofs-5.1.8-switch-to-application-wide-command-pipe.patch @@ -0,0 +1,568 @@ +autofs-5.1.8 - switch to application wide command pipe + +From: Ian Kent + +Switch to use the functions previously added to allow a single +application wide command pipe to be used. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + daemon/automount.c | 426 +++++++++------------------------------------------- + daemon/master.c | 2 + include/automount.h | 1 + modules/parse_sun.c | 1 + 5 files changed, 80 insertions(+), 351 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -120,6 +120,7 @@ + - add function master_find_mapent_by_devid(). + - use device id to locate autofs_point when setting log priotity. + - add command pipe handling functions. ++- switch to application wide command pipe. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -69,10 +69,6 @@ const char *cmd_pipe_name = AUTOFS_FIFO_ + int start_cmd_pipe_handler(void); + void finish_cmd_pipe_handler(void); + +-/* autofs fifo name prefix */ +-#define FIFO_NAME_PREFIX "autofs.fifo" +-const char *fifodir = AUTOFS_FIFO_DIR "/" FIFO_NAME_PREFIX; +- + const char *global_options; /* Global option, from command line */ + + static char *pid_file = NULL; /* File in which to keep pid */ +@@ -801,319 +797,6 @@ static int fullread(int fd, void *ptr, s + return len; + } + +-static char *automount_path_to_fifo(unsigned logopt, const char *path) +-{ +- char *fifo_name, *p; +- int name_len = strlen(path) + strlen(fifodir) + 1; +- int ret; +- +- fifo_name = malloc(name_len); +- if (!fifo_name) +- return NULL; +- ret = snprintf(fifo_name, name_len, "%s%s", fifodir, path); +- if (ret >= name_len) { +- info(logopt, +- "fifo path for \"%s\" truncated to \"%s\". This may " +- "lead to --set-log-priority commands being sent to the " +- "wrong automount daemon.", path, fifo_name); +- } +- +- /* +- * An automount path can be made up of subdirectories. So, to +- * create the fifo name, we will just replace instances of '/' with +- * '-'. +- */ +- p = fifo_name + strlen(fifodir); +- while (*p != '\0') { +- if (*p == '/') +- *p = '-'; +- p++; +- } +- +- debug(logopt, "fifo name %s",fifo_name); +- +- return fifo_name; +-} +- +-static int create_logpri_fifo(struct autofs_point *ap) +-{ +- int ret = -1; +- int fd; +- char *fifo_name; +- char buf[MAX_ERR_BUF]; +- +- fifo_name = automount_path_to_fifo(ap->logopt, ap->path); +- if (!fifo_name) { +- crit(ap->logopt, "Failed to allocate memory!"); +- goto out_free; /* free(NULL) is okay */ +- } +- +- ret = unlink(fifo_name); +- if (ret != 0 && errno != ENOENT) { +- crit(ap->logopt, +- "Failed to unlink FIFO. Is the automount daemon " +- "already running?"); +- goto out_free; +- } +- +- ret = mkfifo(fifo_name, S_IRUSR|S_IWUSR); +- if (ret != 0) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(ap->logopt, +- "mkfifo for %s failed: %s", fifo_name, estr); +- goto out_free; +- } +- +- fd = open_fd(fifo_name, O_RDWR|O_NONBLOCK); +- if (fd < 0) { +- unlink(fifo_name); +- ret = -1; +- goto out_free; +- } +- +- ap->logpri_fifo = fd; +- +-out_free: +- free(fifo_name); +- return ret; +-} +- +-int destroy_logpri_fifo(struct autofs_point *ap) +-{ +- int ret = -1; +- int fd = ap->logpri_fifo; +- char *fifo_name; +- char buf[MAX_ERR_BUF]; +- +- if (fd == -1) +- return 0; +- +- fifo_name = automount_path_to_fifo(ap->logopt, ap->path); +- if (!fifo_name) { +- crit(ap->logopt, "Failed to allocate memory!"); +- goto out_free; /* free(NULL) is okay */ +- } +- +- ap->logpri_fifo = -1; +- +- ret = close(fd); +- if (ret != 0) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(ap->logopt, +- "close for fifo %s: %s", fifo_name, estr); +- } +- +- ret = unlink(fifo_name); +- if (ret != 0) { +- warn(ap->logopt, +- "Failed to unlink FIFO. Was the fifo created OK?"); +- } +- +-out_free: +- free(fifo_name); +- return ret; +-} +- +-static void cleanup_stale_logpri_fifo_pipes(void) +-{ +- size_t prefix_len = strlen(FIFO_NAME_PREFIX); +- char *dir = AUTOFS_FIFO_DIR; +- size_t dir_len = strlen(dir); +- struct dirent *dent; +- DIR *dfd; +- int ret; +- +- dfd = opendir(dir); +- if (!dfd) { +- warn(LOGOPT_ANY, "failed to open fifo dir %s", dir); +- return; +- } +- +- while ((dent = readdir(dfd))) { +- char fifo_path[PATH_MAX]; +- +- if (!(dent->d_type & DT_FIFO)) +- continue; +- if (strncmp(FIFO_NAME_PREFIX, dent->d_name, prefix_len)) +- continue; +- if ((dir_len + 1 + strlen(dent->d_name)) >= PATH_MAX) { +- warn(LOGOPT_ANY, "fifo path too long for buffer"); +- continue; +- } +- +- strcpy(fifo_path, dir); +- strcat(fifo_path, "/"); +- strcat(fifo_path, dent->d_name); +- +- ret = unlink(fifo_path); +- if (ret == -1) { +- char buf[MAX_ERR_BUF]; +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(LOGOPT_ANY, "unlink of fifo failed: %s", estr); +- } +- } +- +- closedir(dfd); +-} +- +-static void handle_fifo_message(int fd) +-{ +- struct autofs_point *ap; +- int ret; +- char buffer[PIPE_BUF]; +- char *end, *sep; +- long pri; +- char buf[MAX_ERR_BUF]; +- dev_t devid; +- +- memset(buffer, 0, sizeof(buffer)); +- ret = read(fd, &buffer, sizeof(buffer)); +- if (ret < 0) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(LOGOPT_ANY, "read on fifo returned error: %s", estr); +- return; +- } +- +- sep = strrchr(buffer, ' '); +- if (!sep) { +- error(LOGOPT_ANY, "Incorrect cmd message format %s.", buffer); +- return; +- } +- sep++; +- +- errno = 0; +- devid = strtol(buffer, &end, 10); +- if ((devid == LONG_MIN || devid == LONG_MAX) && errno == ERANGE) { +- debug(LOGOPT_ANY, "strtol reported a range error."); +- error(LOGOPT_ANY, "Invalid cmd message format %s.", buffer); +- return; +- } +- if ((devid == 0 && errno == EINVAL) || end == buffer) { +- debug(LOGOPT_ANY, "devid id is expected to be a integer."); +- return; +- } +- +- ap = master_find_mapent_by_devid(master_list, devid); +- if (!ap) { +- error(LOGOPT_ANY, "Can't locate autofs_point for device id %ld.", devid); +- return; +- } +- +- errno = 0; +- pri = strtol(sep, &end, 10); +- if ((pri == LONG_MIN || pri == LONG_MAX) && errno == ERANGE) { +- debug(ap->logopt, "strtol reported an %s. Failed to set " +- "log priority.", pri == LONG_MIN ? "underflow" : "overflow"); +- return; +- } +- if ((pri == 0 && errno == EINVAL) || end == sep) { +- debug(ap->logopt, "priority is expected to be an integer " +- "in the range 0-7 inclusive."); +- return; +- } +- +- if (pri > LOG_DEBUG || pri < LOG_EMERG) { +- debug(ap->logopt, "invalid log priority (%ld) received " +- "on fifo", pri); +- return; +- } +- +- /* +- * OK, the message passed all of the sanity checks. The +- * automounter actually only supports three log priorities. +- * Everything is logged at log level debug, deamon messages +- * and everything except debug messages are logged with the +- * verbose setting and only error and critical messages are +- * logged when debugging isn't enabled. +- */ +- if (pri >= LOG_WARNING) { +- if (pri == LOG_DEBUG) { +- set_log_debug_ap(ap); +- info(ap->logopt, "Debug logging set for %s", ap->path); +- } else { +- set_log_verbose_ap(ap); +- info(ap->logopt, "Verbose logging set for %s", ap->path); +- } +- } else { +- if (ap->logopt & LOGOPT_ANY) +- info(ap->logopt, "Basic logging set for %s", ap->path); +- set_log_norm_ap(ap); +- } +-} +- +-static int set_log_priority(const char *path, int priority) +-{ +- struct ioctl_ops *ops = get_ioctl_ops(); +- int fd; +- char *fifo_name; +- char buf[FIFO_BUF_SIZE]; +- int ret; +- dev_t devid; +- +- if (!ops) { +- fprintf(stderr, "Could not get ioctl ops\n"); +- return -1; +- } else { +- ret = ops->mount_device(LOGOPT_ANY, path, 0, &devid); +- if (ret == -1 || ret == 0) { +- fprintf(stderr, +- "Could not find device id for mount %s\n", path); +- return -1; +- } +- } +- +- if (priority > LOG_DEBUG || priority < LOG_EMERG) { +- fprintf(stderr, "Log priority %d is invalid.\n", priority); +- fprintf(stderr, "Please specify a number in the range 0-7.\n"); +- return -1; +- } +- +- /* +- * This is an ascii based protocol, so we want the string +- * representation of the integer log priority. +- */ +- ret = snprintf(buf, sizeof(buf), "%ld %d", devid, priority); +- if (ret >= FIFO_BUF_SIZE) { +- fprintf(stderr, "Invalid device id or log priotity\n"); +- return -1; +- } +- +- fifo_name = automount_path_to_fifo(LOGOPT_NONE, path); +- if (!fifo_name) { +- fprintf(stderr, "%s: Failed to allocate memory!\n", +- __FUNCTION__); +- return -1; +- } +- +- /* +- * Specify O_NONBLOCK so that the open will fail if there is no +- * daemon reading from the other side of the FIFO. +- */ +- fd = open_fd(fifo_name, O_WRONLY|O_NONBLOCK); +- if (fd < 0) { +- fprintf(stderr, "%s: open of %s failed with %s\n", +- __FUNCTION__, fifo_name, strerror(errno)); +- fprintf(stderr, "%s: perhaps the fifo wasn't setup," +- " please check your log for more information\n", __FUNCTION__); +- free(fifo_name); +- return -1; +- } +- +- if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { +- fprintf(stderr, "Failed to change logging priority. "); +- fprintf(stderr, "write to fifo failed: %s.\n", +- strerror(errno)); +- close(fd); +- free(fifo_name); +- return -1; +- } +- close(fd); +- free(fifo_name); +- fprintf(stdout, "Successfully set log priority for %s.\n", path); +- +- return 0; +-} +- + static void dummy(int sig) + { + } +@@ -1122,18 +805,14 @@ static int get_pkt(struct autofs_point * + { + struct sigaction sa; + sigset_t signalset; +- struct pollfd fds[2]; +- int pollfds = 2; ++ struct pollfd fds[1]; ++ int pollfds = 1; + char buf[MAX_ERR_BUF]; + size_t read; + char *estr; + + fds[0].fd = ap->pipefd; + fds[0].events = POLLIN; +- fds[1].fd = ap->logpri_fifo; +- fds[1].events = POLLIN; +- if (fds[1].fd == -1) +- pollfds--; + + sa.sa_handler = dummy; + sigemptyset(&sa.sa_mask); +@@ -1172,11 +851,6 @@ static int get_pkt(struct autofs_point * + } + return read; + } +- +- if (fds[1].fd != -1 && fds[1].revents & POLLIN) { +- debug(ap->logopt, "message pending on control fifo."); +- handle_fifo_message(fds[1].fd); +- } + } + } + +@@ -1235,11 +909,6 @@ static int autofs_init_ap(struct autofs_ + ap->pipefd = pipefd[0]; + ap->kpipefd = pipefd[1]; + +- if (create_logpri_fifo(ap) < 0) { +- logmsg("could not create FIFO for path %s\n", ap->path); +- logmsg("dynamic log level changes not available for %s", ap->path); +- } +- + return 0; + } + +@@ -1260,11 +929,6 @@ static int mount_autofs(struct autofs_po + else + status = mount_autofs_indirect(ap, root); + +- if (status < 0) { +- destroy_logpri_fifo(ap); +- return -1; +- } +- + st_add_task(ap, ST_READY); + + return status; +@@ -1831,6 +1495,68 @@ static void handle_cmd_pipe_fifo_message + } + } + ++static int set_log_priority(const char *path, int priority) ++{ ++ struct ioctl_ops *ops = get_ioctl_ops(); ++ char buf[FIFO_BUF_SIZE]; ++ dev_t devid; ++ int fd; ++ int ret; ++ ++ if (!ops) { ++ fprintf(stderr, "Could not get ioctl ops\n"); ++ return -1; ++ } else { ++ ret = ops->mount_device(LOGOPT_ANY, path, 0, &devid); ++ if (ret == -1 || ret == 0) { ++ fprintf(stderr, ++ "Could not find device id for mount %s\n", path); ++ return -1; ++ } ++ } ++ ++ if (priority > LOG_DEBUG || priority < LOG_EMERG) { ++ fprintf(stderr, "Log priority %d is invalid.\n", priority); ++ fprintf(stderr, "Please specify a number in the range 0-7.\n"); ++ return -1; ++ } ++ ++ /* ++ * This is an ascii based protocol, so we want the string ++ * representation of the integer log priority. ++ */ ++ ret = snprintf(buf, sizeof(buf), "%ld %d", devid, priority); ++ if (ret >= FIFO_BUF_SIZE) { ++ fprintf(stderr, "Invalid device id or log priotity\n"); ++ return -1; ++ } ++ ++ /* ++ * Specify O_NONBLOCK so that the open will fail if there is no ++ * daemon reading from the other side of the FIFO. ++ */ ++ fd = open_fd(cmd_pipe_name, O_WRONLY|O_NONBLOCK); ++ if (fd < 0) { ++ fprintf(stderr, "%s: open of %s failed with %s\n", ++ __FUNCTION__, cmd_pipe_name, strerror(errno)); ++ fprintf(stderr, "%s: perhaps the fifo wasn't setup," ++ " please check your log for more information\n", __FUNCTION__); ++ return -1; ++ } ++ ++ if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { ++ fprintf(stderr, "Failed to change logging priority. "); ++ fprintf(stderr, "write to fifo failed: %s.\n", ++ strerror(errno)); ++ close(fd); ++ return -1; ++ } ++ close(fd); ++ fprintf(stdout, "Successfully set log priority for %s.\n", path); ++ ++ return 0; ++} ++ + static void cmd_pipe_dummy(int sig) + { + } +@@ -2031,8 +1757,6 @@ static void handle_mounts_cleanup(void * + master_remove_mapent(ap->entry); + master_source_unlock(ap->entry); + +- destroy_logpri_fifo(ap); +- + /* + * Submounts are detached threads and don't belong to the + * master map entry list so we need to free their resources +@@ -2970,6 +2694,18 @@ int main(int argc, char *argv[]) + + init_ioctl_ctl(); + ++ if (!start_cmd_pipe_handler()) { ++ logerr("%s: failed to create command pipe handler thread!", program); ++ master_kill(master_list); ++ if (start_pipefd[1] != -1) { ++ res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); ++ close(start_pipefd[1]); ++ } ++ release_flag_file(); ++ macro_free_global_table(); ++ exit(1); ++ } ++ + if (!alarm_start_handler()) { + logerr("%s: failed to create alarm handler thread!", program); + master_kill(master_list); +@@ -3035,13 +2771,7 @@ int main(int argc, char *argv[]) + } + } + +- /* If the option to unlink all autofs mounts and exit has +- * been given remove logpri fifo files as all the mounts +- * will be detached leaving them stale. +- */ +- if (do_force_unlink & UNLINK_AND_EXIT) +- cleanup_stale_logpri_fifo_pipes(); +- else { ++ if (!(do_force_unlink & UNLINK_AND_EXIT)) { + /* + * Mmm ... reset force unlink umount so we don't also do + * this in future when we receive a HUP signal. +@@ -3065,6 +2795,8 @@ int main(int argc, char *argv[]) + + master_kill(master_list); + ++ finish_cmd_pipe_handler(); ++ + if (pid_file) { + unlink(pid_file); + pid_file = NULL; +--- autofs-5.1.4.orig/daemon/master.c ++++ autofs-5.1.4/daemon/master.c +@@ -112,8 +112,6 @@ int master_add_autofs_point(struct maste + + ap->state = ST_INIT; + +- ap->logpri_fifo = -1; +- + ap->path = strdup(entry->path); + if (!ap->path) { + free(ap); +--- autofs-5.1.4.orig/include/automount.h ++++ autofs-5.1.4/include/automount.h +@@ -551,7 +551,6 @@ struct autofs_point { + int pipefd; /* File descriptor for pipe */ + int kpipefd; /* Kernel end descriptor for pipe */ + int ioctlfd; /* File descriptor for ioctls */ +- int logpri_fifo; /* FIFO used for changing log levels */ + dev_t dev; /* "Device" number assigned by kernel */ + struct master_mapent *entry; /* Master map entry for this mount */ + unsigned int type; /* Type of map direct or indirect */ +--- autofs-5.1.4.orig/modules/parse_sun.c ++++ autofs-5.1.4/modules/parse_sun.c +@@ -82,7 +82,6 @@ static struct parse_context default_cont + 1 /* Do slashify_colons */ + }; + +-int destroy_logpri_fifo(struct autofs_point *ap); + static char *concat_options(char *left, char *right); + + /* Free all storage associated with this context */ diff --git a/autofs-5.1.8-use-device-id-to-locate-autofs_point-when-setting-log-priotity.patch b/autofs-5.1.8-use-device-id-to-locate-autofs_point-when-setting-log-priotity.patch new file mode 100644 index 0000000..8d6fb26 --- /dev/null +++ b/autofs-5.1.8-use-device-id-to-locate-autofs_point-when-setting-log-priotity.patch @@ -0,0 +1,155 @@ +autofs-5.1.8 - use device id to locate autofs_point when setting log priotity + +From: Ian Kent + +Using a fifo pipe for every autofs mount to dynamically set the log +priority is expensive in terms of the number of file handles used. + +It would be better to use a single file handle and locate the autofs +mount point by it's id to set the log priority. + +Start by making the communication pipe send the device id as well as +the log priority to be set and use the newly added helper function +master_find_mapent_by_devid() to locate the autofs mount to change the +log priority. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + daemon/automount.c | 63 ++++++++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 54 insertions(+), 10 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -118,6 +118,7 @@ + - fix incorrect print format specifiers in get_pkt(). + - eliminate last remaining state_pipe usage. + - add function master_find_mapent_by_devid(). ++- use device id to locate autofs_point when setting log priotity. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -59,6 +59,8 @@ unsigned int mp_mode = 0755; + unsigned int nfs_mount_uses_string_options = 0; + static struct nfs_mount_vers vers, check = {1, 1, 1}; + ++#define FIFO_BUF_SIZE 25 ++ + /* autofs fifo name prefix */ + #define FIFO_NAME_PREFIX "autofs.fifo" + const char *fifodir = AUTOFS_FIFO_DIR "/" FIFO_NAME_PREFIX; +@@ -946,35 +948,57 @@ static void cleanup_stale_logpri_fifo_pi + closedir(dfd); + } + +-static void handle_fifo_message(struct autofs_point *ap, int fd) ++static void handle_fifo_message(int fd) + { ++ struct autofs_point *ap; + int ret; + char buffer[PIPE_BUF]; +- char *end; ++ char *end, *sep; + long pri; + char buf[MAX_ERR_BUF]; ++ dev_t devid; + + memset(buffer, 0, sizeof(buffer)); + ret = read(fd, &buffer, sizeof(buffer)); + if (ret < 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(ap->logopt, "read on fifo returned error: %s", estr); ++ warn(LOGOPT_ANY, "read on fifo returned error: %s", estr); ++ return; ++ } ++ ++ sep = strrchr(buffer, ' '); ++ if (!sep) { ++ error(LOGOPT_ANY, "Incorrect cmd message format %s.", buffer); ++ return; ++ } ++ sep++; ++ ++ errno = 0; ++ devid = strtol(buffer, &end, 10); ++ if ((devid == LONG_MIN || devid == LONG_MAX) && errno == ERANGE) { ++ debug(LOGOPT_ANY, "strtol reported a range error."); ++ error(LOGOPT_ANY, "Invalid cmd message format %s.", buffer); ++ return; ++ } ++ if ((devid == 0 && errno == EINVAL) || end == buffer) { ++ debug(LOGOPT_ANY, "devid id is expected to be a integer."); + return; + } + +- if (ret != 2) { +- debug(ap->logopt, "expected 2 bytes, received %d.", ret); ++ ap = master_find_mapent_by_devid(master_list, devid); ++ if (!ap) { ++ error(LOGOPT_ANY, "Can't locate autofs_point for device id %ld.", devid); + return; + } + + errno = 0; +- pri = strtol(buffer, &end, 10); ++ pri = strtol(sep, &end, 10); + if ((pri == LONG_MIN || pri == LONG_MAX) && errno == ERANGE) { + debug(ap->logopt, "strtol reported an %s. Failed to set " + "log priority.", pri == LONG_MIN ? "underflow" : "overflow"); + return; + } +- if ((pri == 0 && errno == EINVAL) || end == buffer) { ++ if ((pri == 0 && errno == EINVAL) || end == sep) { + debug(ap->logopt, "priority is expected to be an integer " + "in the range 0-7 inclusive."); + return; +@@ -1011,9 +1035,24 @@ static void handle_fifo_message(struct a + + static int set_log_priority(const char *path, int priority) + { ++ struct ioctl_ops *ops = get_ioctl_ops(); + int fd; + char *fifo_name; +- char buf[2]; ++ char buf[FIFO_BUF_SIZE]; ++ int ret; ++ dev_t devid; ++ ++ if (!ops) { ++ fprintf(stderr, "Could not get ioctl ops\n"); ++ return -1; ++ } else { ++ ret = ops->mount_device(LOGOPT_ANY, path, 0, &devid); ++ if (ret == -1 || ret == 0) { ++ fprintf(stderr, ++ "Could not find device id for mount %s\n", path); ++ return -1; ++ } ++ } + + if (priority > LOG_DEBUG || priority < LOG_EMERG) { + fprintf(stderr, "Log priority %d is invalid.\n", priority); +@@ -1025,7 +1064,11 @@ static int set_log_priority(const char * + * This is an ascii based protocol, so we want the string + * representation of the integer log priority. + */ +- snprintf(buf, sizeof(buf), "%d", priority); ++ ret = snprintf(buf, sizeof(buf), "%ld %d", devid, priority); ++ if (ret >= FIFO_BUF_SIZE) { ++ fprintf(stderr, "Invalid device id or log priotity\n"); ++ return -1; ++ } + + fifo_name = automount_path_to_fifo(LOGOPT_NONE, path); + if (!fifo_name) { +@@ -1124,7 +1167,7 @@ static int get_pkt(struct autofs_point * + + if (fds[1].fd != -1 && fds[1].revents & POLLIN) { + debug(ap->logopt, "message pending on control fifo."); +- handle_fifo_message(ap, fds[1].fd); ++ handle_fifo_message(fds[1].fd); + } + } + } diff --git a/autofs.spec b/autofs.spec index 9332590..86f7d23 100644 --- a/autofs.spec +++ b/autofs.spec @@ -8,7 +8,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.1.4 -Release: 93%{?dist} +Release: 102%{?dist} Epoch: 1 License: GPLv2+ Group: System Environment/Daemons @@ -281,6 +281,23 @@ Patch252: autofs-5.1.8-fail-on-empty-replicated-host-name.patch Patch253: autofs-5.1.8-improve-handling-of-ENOENT-in-sss-setautomntent.patch Patch254: autofs-5.1.8-dont-immediately-call-function-when-waiting.patch +Patch260: autofs-5.1.8-fix-return-status-of-mount_autofs.patch +Patch261: autofs-5.1.8-dont-close-lookup-at-umount.patch +Patch262: autofs-5.1.8-fix-deadlock-in-lookups.patch +Patch263: autofs-5.1.8-dont-delay-expire.patch +Patch264: autofs-5.1.8-make-amd-mapent-search-function-name-clear.patch +Patch265: autofs-5.1.8-rename-statemachine-to-signal_handler.patch +Patch266: autofs-5.1.8-make-signal-handling-consistent.patch +Patch267: autofs-5.1.7-fix-incorrect-print-format-specifiers.patch +Patch268: autofs-5.1.8-eliminate-last-remaining-state_pipe-usage.patch +Patch269: autofs-5.1.8-add-function-master_find_mapent_by_devid.patch +Patch270: autofs-5.1.8-use-device-id-to-locate-autofs_point-when-setting-log-priotity.patch +Patch271: autofs-5.1.8-add-command-pipe-handling-functions.patch +Patch272: autofs-5.1.8-switch-to-application-wide-command-pipe.patch +Patch273: autofs-5.1.8-get-rid-of-unused-field-submnt_count.patch +Patch274: autofs-5.1.8-fix-mount-tree-startup-reconnect.patch +Patch275: autofs-5.1.8-fix-unterminated-read-in-handle_cmd_pipe_fifo_message.patch + %if %{with_systemd} BuildRequires: systemd-units BuildRequires: systemd-devel @@ -602,6 +619,23 @@ echo %{version}-%{release} > .version %patch253 -p1 %patch254 -p1 +%patch260 -p1 +%patch261 -p1 +%patch262 -p1 +%patch263 -p1 +%patch264 -p1 +%patch265 -p1 +%patch266 -p1 +%patch267 -p1 +%patch268 -p1 +%patch269 -p1 +%patch270 -p1 +%patch271 -p1 +%patch272 -p1 +%patch273 -p1 +%patch274 -p1 +%patch275 -p1 + %build LDFLAGS=-Wl,-z,now %configure --disable-mount-locking --enable-ignore-busy --with-libtirpc --without-hesiod %{?systemd_configure_arg:} @@ -696,6 +730,26 @@ fi %dir /etc/auto.master.d %changelog +* Mon Mar 20 2023 Ian Kent - 5.1.4-102 +- bz2177998 - deadlock while reading amd maps + - fix return status of mount_autofs(). + - don't close lookup at umount. + - fix deadlock in lookups. + - dont delay expire. + - make amd mapent search function name clear. + - rename statemachine() to signal_handler(). + - make signal handling consistent. + - fix incorrect print format specifiers in get_pkt(). + - eliminate last remaining state_pipe usage. + - add function master_find_mapent_by_devid(). + - use device id to locate autofs_point when setting log priotity. + - add command pipe handling functions. + - switch to application wide command pipe. + - get rid of unused field submnt_count. + - fix mount tree startup reconnect. + - fix unterminated read in handle_cmd_pipe_fifo_message() (Coverity). +- Resolves: rhbz#2177998 + * Wed Feb 08 2023 Ian Kent - 5.1.4-93 - bz2165143 - Autofs reports can't connect to sssd, retry for 10 seconds when real problem is empty LDAP object