diff --git a/src/bindings.c b/src/bindings.c index 310be257..6d8d713f 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -761,7 +761,7 @@ static int permute_prepare(void) } if (mount(runtime_path, new_runtime, NULL, MS_BIND, 0) < 0) { - lxcfs_error("Failed to bind-mount /run into new root: %s.\n", strerror(errno)); + lxcfs_error("Failed to bind-mount %s into new root: %s.\n", runtime_path, strerror(errno)); return -1; } @@ -892,7 +892,7 @@ static void sigusr2_toggle_virtualization(int signo, siginfo_t *info, void *extr return; } -static void __attribute__((constructor)) lxcfs_init(void) +void lxcfslib_init(void) { __do_close int init_ns = -EBADF, root_fd = -EBADF, pidfd = -EBADF; @@ -1003,5 +1003,21 @@ void *lxcfs_fuse_init(struct fuse_conn_info *conn, void *data) can_use_sys_cpu = true; #endif has_versioned_opts = true; - return fc ? fc->private_data : NULL; + return fc ? fc->private_data : NULL; +} + +bool set_runtime_path(const char* new_path) +{ + int pathlen; + + if (new_path && strlen(new_path) < PATH_MAX) { + pathlen = strlen(new_path); + memcpy(runtime_path, new_path, pathlen); + runtime_path[pathlen] = '\0'; + lxcfs_info("Using runtime path %s", runtime_path); + return true; + } else { + lxcfs_error("%s\n", "Failed to overwrite the runtime path"); + return false; + } } diff --git a/src/bindings.h b/src/bindings.h index ba55a8d4..3ac94068 100644 --- a/src/bindings.h +++ b/src/bindings.h @@ -183,4 +183,9 @@ static inline pid_t lxcfs_clone(int (*fn)(void *), void *arg, int flags) __visible extern void *lxcfs_fuse_init(struct fuse_conn_info *conn, void *data); +// Overrides the runtime path from DEFAULT_RUNTIME_PATH - /var/run +__visible extern bool set_runtime_path(const char* runtime_path); +// Needs to be called on library load/reload. +__visible extern void lxcfslib_init(void); + #endif /* __LXCFS_BINDINGS_H */ diff --git a/src/lxcfs.c b/src/lxcfs.c index c9db6221..eaf2d38f 100644 --- a/src/lxcfs.c +++ b/src/lxcfs.c @@ -33,6 +33,7 @@ #include "memory_utils.h" void *dlopen_handle; +static char runtime_path[PATH_MAX]; /* Functions to keep track of number of threads using the library */ @@ -146,7 +147,7 @@ static int stop_loadavg(void) static volatile sig_atomic_t need_reload; -static int lxcfs_init_library(void) +static int do_lxcfs_fuse_init(void) { char *error; void *(*__lxcfs_fuse_init)(struct fuse_conn_info * conn, void * cfg); @@ -162,6 +163,39 @@ static int lxcfs_init_library(void) return 0; } +static int do_lxcfslib_init(void) +{ + char *error; + void (*__lxcfslib_init)(void); + + dlerror(); + __lxcfslib_init = (void (*)(void))dlsym(dlopen_handle, "lxcfslib_init"); + error = dlerror(); + if (error) + return log_error(-1, "%s - Failed to find lxcfslib_init()", error); + + __lxcfslib_init(); + + return 0; +} + +static bool do_set_runtime_path(const char *path) +{ + char *error; + bool (*__set_runtime_path)(const char *path); + + dlerror(); + __set_runtime_path = (bool (*)(const char *path))dlsym(dlopen_handle, "set_runtime_path"); + error = dlerror(); + if (error) { + log_error(-1, "%s - Failed to find set_runtime_path()", error); + return false; + } + + lxcfs_info("set runtime path %s", path); + return __set_runtime_path(path); +} + /* do_reload - reload the dynamic library. Done under * lock and when we know the user_count was 0 */ static void do_reload(bool reinit) @@ -199,13 +233,19 @@ static void do_reload(bool reinit) dlopen_handle = dlopen(lxcfs_lib_path, RTLD_LAZY); if (!dlopen_handle) - log_exit("%s - Failed to open liblxcfs.so", dlerror()); + log_exit("%s - Failed to open liblxcfs.so at %s", dlerror(), lxcfs_lib_path); else lxcfs_debug("Opened %s", lxcfs_lib_path); good: + if (strlen(runtime_path) > 0 && !do_set_runtime_path(runtime_path)) { + dlclose(dlopen_handle); + log_exit("failed to override runtime dir with %s", runtime_path); + } + /* initialize the library */ - if (reinit && lxcfs_init_library() < 0) { + do_lxcfslib_init(); + if (reinit && do_lxcfs_fuse_init() < 0) { log_exit("Failed to initialize liblxcfs.so"); } @@ -1117,7 +1157,7 @@ static void *lxcfs_init(struct fuse_conn_info *conn, struct fuse_config *cfg) static void *lxcfs_init(struct fuse_conn_info *conn) #endif { - if (lxcfs_init_library() < 0) + if (do_lxcfs_fuse_init() < 0) return NULL; #if HAVE_FUSE3 @@ -1190,6 +1230,8 @@ static void usage(void) lxcfs_info(" -v, --version Print lxcfs version"); lxcfs_info(" --enable-cfs Enable CPU virtualization via CPU shares"); lxcfs_info(" --enable-pidfd Use pidfd for process tracking"); + lxcfs_info(" --runtime-dir=DIR Path to use as the runtime directory."); + lxcfs_info(" Default is %s", DEFAULT_RUNTIME_PATH); exit(EXIT_FAILURE); } @@ -1240,6 +1282,7 @@ static const struct option long_options[] = { {"enable-pidfd", no_argument, 0, 0 }, {"pidfile", required_argument, 0, 'p' }, + {"runtime-dir", required_argument, 0, 0 }, { }, }; @@ -1282,7 +1325,7 @@ int main(int argc, char *argv[]) int pidfile_fd = -EBADF; int ret = EXIT_FAILURE; char *pidfile = NULL, *token = NULL; - char pidfile_buf[STRLITERALLEN(DEFAULT_RUNTIME_PATH) + STRLITERALLEN("/lxcfs.pid") + 1] = {}; + char pidfile_buf[PATH_MAX] = {}; bool debug = false, foreground = false; #if !HAVE_FUSE3 bool nonempty = false; @@ -1299,6 +1342,8 @@ int main(int argc, char *argv[]) char *new_fuse_opts = NULL; char *const *new_argv; struct lxcfs_opts *opts; + char *runtime_path_arg = NULL; + int runtime_path_len; opts = malloc(sizeof(struct lxcfs_opts)); if (opts == NULL) { @@ -1318,6 +1363,8 @@ int main(int argc, char *argv[]) opts->use_pidfd = true; else if (strcmp(long_options[idx].name, "enable-cfs") == 0) opts->use_cfs = true; + else if (strcmp(long_options[idx].name, "runtime-dir") == 0) + runtime_path_arg = optarg; else usage(); break; @@ -1370,6 +1417,13 @@ int main(int argc, char *argv[]) goto out; } + if (runtime_path_arg) { + runtime_path_len = strlen(runtime_path_arg); + memcpy(runtime_path, runtime_path_arg, runtime_path_len); + runtime_path[runtime_path_len] = '\0'; + lxcfs_info("runtime path set to %s", runtime_path); + } + fuse_argv[fuse_argc++] = argv[0]; if (debug) fuse_argv[fuse_argc++] = "-d"; @@ -1461,6 +1515,7 @@ int main(int argc, char *argv[]) lxcfs_info("Starting LXCFS at %s", argv[0]); do_reload(false); + if (install_signal_handler(SIGUSR1, sigusr1_reload)) { lxcfs_error("%s - Failed to install SIGUSR1 signal handler", strerror(errno)); goto out; @@ -1474,7 +1529,10 @@ int main(int argc, char *argv[]) #endif if (!pidfile) { - snprintf(pidfile_buf, sizeof(pidfile_buf), "%s/lxcfs.pid", DEFAULT_RUNTIME_PATH); + if (runtime_path_arg) + snprintf(pidfile_buf, sizeof(pidfile_buf), "%s/lxcfs.pid", runtime_path_arg); + else + snprintf(pidfile_buf, sizeof(pidfile_buf), "%s/lxcfs.pid", DEFAULT_RUNTIME_PATH); pidfile = pidfile_buf; }