git: b64d88424dda - stable/14 - ctld: fix several process setup/teardown bugs
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 10 Oct 2024 19:16:57 UTC
The branch stable/14 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=b64d88424dda7785eba815cefcc99709780c2953 commit b64d88424dda7785eba815cefcc99709780c2953 Author: Alan Somers <asomers@FreeBSD.org> AuthorDate: 2024-08-07 15:21:08 +0000 Commit: Alan Somers <asomers@FreeBSD.org> CommitDate: 2024-10-10 19:11:37 +0000 ctld: fix several process setup/teardown bugs All of the below bugs could result in a system where ctld is not running, but LUNs and targets still exist in the kernel; a difficult situation to recover from. * open the pidfile earlier. Open the pidfile before reading the kernel's current state, so two racing ctld processes won't step on each others' toes. * close the pidfile later. Close it after tearing down the configuration, for the same reason. * If the configured pidfile changes, then rename it on SIGHUP rather than remove and recreate it. * When running in debug mode, don't close the pidfile while handling a new connection. Only do that in non-debug mode, in the child of the fork. * Register signal handlers earlier. Otherwise a SIGTERM signal received during startup could kill ctld without tearing down the configuration. PR: 271460 Sponsored by: Axcient Reviewed by: mav Pull Request: https://github.com/freebsd/freebsd-src/pull/1370 (cherry picked from commit 5f89aea7b74aa4605b25af62e31303097a4a48cc) --- usr.sbin/ctld/ctld.c | 70 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c index fdd3a49f8a48..9be0f6975437 100644 --- a/usr.sbin/ctld/ctld.c +++ b/usr.sbin/ctld/ctld.c @@ -1916,7 +1916,6 @@ conf_apply(struct conf *oldconf, struct conf *newconf) struct portal *oldp, *newp; struct port *oldport, *newport, *tmpport; struct isns *oldns, *newns; - pid_t otherpid; int changed, cumulated_error = 0, error, sockbuf; int one = 1; @@ -1925,32 +1924,25 @@ conf_apply(struct conf *oldconf, struct conf *newconf) log_init(newconf->conf_debug); } - if (oldconf->conf_pidfh != NULL) { - assert(oldconf->conf_pidfile_path != NULL); - if (newconf->conf_pidfile_path != NULL && - strcmp(oldconf->conf_pidfile_path, - newconf->conf_pidfile_path) == 0) { - newconf->conf_pidfh = oldconf->conf_pidfh; - oldconf->conf_pidfh = NULL; - } else { - log_debugx("removing pidfile %s", - oldconf->conf_pidfile_path); - pidfile_remove(oldconf->conf_pidfh); - oldconf->conf_pidfh = NULL; - } - } - - if (newconf->conf_pidfh == NULL && newconf->conf_pidfile_path != NULL) { - log_debugx("opening pidfile %s", newconf->conf_pidfile_path); - newconf->conf_pidfh = - pidfile_open(newconf->conf_pidfile_path, 0600, &otherpid); - if (newconf->conf_pidfh == NULL) { - if (errno == EEXIST) - log_errx(1, "daemon already running, pid: %jd.", - (intmax_t)otherpid); - log_err(1, "cannot open or create pidfile \"%s\"", - newconf->conf_pidfile_path); + if (oldconf->conf_pidfile_path != NULL && + newconf->conf_pidfile_path != NULL) + { + if (strcmp(oldconf->conf_pidfile_path, + newconf->conf_pidfile_path) != 0) + { + /* pidfile has changed. rename it */ + log_debugx("moving pidfile to %s", + newconf->conf_pidfile_path); + if (rename(oldconf->conf_pidfile_path, + newconf->conf_pidfile_path)) + { + log_err(1, "renaming pidfile %s -> %s", + oldconf->conf_pidfile_path, + newconf->conf_pidfile_path); + } } + newconf->conf_pidfh = oldconf->conf_pidfh; + oldconf->conf_pidfh = NULL; } /* @@ -2472,8 +2464,8 @@ handle_connection(struct portal *portal, int fd, close(fd); return; } + pidfile_close(conf->conf_pidfh); } - pidfile_close(conf->conf_pidfh); error = getnameinfo(client_sa, client_sa->sa_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); @@ -2808,6 +2800,7 @@ main(int argc, char **argv) struct isns *newns; const char *config_path = DEFAULT_CONFIG_PATH; int debug = 0, ch, error; + pid_t otherpid; bool dont_daemonize = false; bool test_config = false; bool use_ucl = false; @@ -2847,7 +2840,6 @@ main(int argc, char **argv) kernel_init(); TAILQ_INIT(&kports.pports); - oldconf = conf_new_from_kernel(&kports); newconf = conf_new_from_file(config_path, use_ucl); if (newconf == NULL) @@ -2856,6 +2848,22 @@ main(int argc, char **argv) if (test_config) return (0); + assert(newconf->conf_pidfile_path != NULL); + log_debugx("opening pidfile %s", newconf->conf_pidfile_path); + newconf->conf_pidfh = pidfile_open(newconf->conf_pidfile_path, 0600, + &otherpid); + if (newconf->conf_pidfh == NULL) { + if (errno == EEXIST) + log_errx(1, "daemon already running, pid: %jd.", + (intmax_t)otherpid); + log_err(1, "cannot open or create pidfile \"%s\"", + newconf->conf_pidfile_path); + } + + register_signals(); + + oldconf = conf_new_from_kernel(&kports); + if (debug > 0) { oldconf->conf_debug = debug; newconf->conf_debug = debug; @@ -2871,8 +2879,6 @@ main(int argc, char **argv) conf_delete(oldconf); oldconf = NULL; - register_signals(); - if (dont_daemonize == false) { log_debugx("daemonizing"); if (daemon(0, 0) == -1) { @@ -2927,6 +2933,10 @@ main(int argc, char **argv) error = conf_apply(oldconf, newconf); if (error != 0) log_warnx("failed to apply configuration"); + if (oldconf->conf_pidfh) { + pidfile_remove(oldconf->conf_pidfh); + oldconf->conf_pidfh = NULL; + } conf_delete(newconf); conf_delete(oldconf); oldconf = NULL;