Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow overriding RUNTIME_DIR with a cli flag #2 #645

Merged
merged 2 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ lxcmandir = join_paths(datadir, 'man')
conf.set_quoted('BINDIR', bindir)
conf.set_quoted('LIBDIR', libdir)
conf.set_quoted('LOCALSTATEDIR', localstatedir)
conf.set_quoted('RUNTIME_PATH', runtimepath)
conf.set_quoted('DEFAULT_RUNTIME_PATH', runtimepath)
conf.set_quoted('SYSCONFDIR', sysconfdir)

conf.set_quoted('LXCCONFDIR', lxcconfdir)
Expand Down
100 changes: 80 additions & 20 deletions src/bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
#include <linux/limits.h>
#include <linux/magic.h>
#include <linux/sched.h>
#include <pthread.h>
Expand Down Expand Up @@ -40,15 +41,32 @@
#include "syscall_numbers.h"
#include "utils.h"

/* directory under which we mount the controllers - /run/lxcfs/controllers */
#define BASEDIR "/lxcfs/controllers"
#define ROOTDIR "/lxcfs/root"

static bool can_use_pidfd;
static bool can_use_swap;
static bool can_use_sys_cpu;
static bool has_versioned_opts;
static bool memory_is_cgroupv2;
static __u32 host_personality;
static char runtime_path[PATH_MAX] = DEFAULT_RUNTIME_PATH;


static volatile sig_atomic_t reload_successful;


static char *get_base_dir(void)
{
return must_make_path(runtime_path, BASEDIR, NULL);
}

static char *get_root_dir(void)
{
return must_make_path(runtime_path, ROOTDIR, NULL);
}

bool liblxcfs_functional(void)
{
return reload_successful != 0;
Expand Down Expand Up @@ -580,8 +598,9 @@ pid_t lookup_initpid_in_store(pid_t pid)

static bool umount_if_mounted(void)
{
if (umount2(BASEDIR, MNT_DETACH) < 0 && errno != EINVAL) {
lxcfs_error("Failed to unmount %s: %s.\n", BASEDIR, strerror(errno));
__do_free char *base_dir = get_base_dir();
if (umount2(base_dir, MNT_DETACH) < 0 && errno != EINVAL) {
lxcfs_error("Failed to unmount %s: %s.\n", base_dir, strerror(errno));
return false;
}
return true;
Expand Down Expand Up @@ -639,13 +658,14 @@ static bool is_on_ramfs(void)
static int pivot_enter(void)
{
__do_close int oldroot = -EBADF, newroot = -EBADF;
__do_free char *root_dir = get_root_dir();

oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (oldroot < 0)
return log_error_errno(-1, errno,
"Failed to open old root for fchdir");

newroot = open(ROOTDIR, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
newroot = open(root_dir, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (newroot < 0)
return log_error_errno(-1, errno,
"Failed to open new root for fchdir");
Expand All @@ -654,7 +674,7 @@ static int pivot_enter(void)
if (fchdir(newroot) < 0)
return log_error_errno(-1,
errno, "Failed to change directory to new rootfs: %s",
ROOTDIR);
root_dir);

/* pivot_root into our new root fs */
if (pivot_root(".", ".") < 0)
Expand All @@ -681,8 +701,10 @@ static int pivot_enter(void)

static int chroot_enter(void)
{
if (mount(ROOTDIR, "/", NULL, MS_REC | MS_BIND, NULL)) {
lxcfs_error("Failed to recursively bind-mount %s into /.", ROOTDIR);
__do_free char *root_dir = get_root_dir();

if (mount(root_dir, "/", NULL, MS_REC | MS_BIND, NULL)) {
lxcfs_error("Failed to recursively bind-mount %s into /.", root_dir);
return -1;
}

Expand Down Expand Up @@ -725,23 +747,33 @@ static int permute_and_enter(void)
/* Prepare our new clean root. */
static int permute_prepare(void)
{
if (mkdir(ROOTDIR, 0700) < 0 && errno != EEXIST) {
__do_free char *base_dir = get_base_dir();
__do_free char *root_dir = get_root_dir();
__do_free char *new_runtime = must_make_path(root_dir, runtime_path, NULL);
__do_free char *new_base_dir = must_make_path(root_dir, base_dir, NULL);

if (mkdir(root_dir, 0700) < 0 && errno != EEXIST) {
lxcfs_error("%s\n", "Failed to create directory for new root.");
return -1;
}

if (mount("/", ROOTDIR, NULL, MS_BIND, 0) < 0) {
if (mount("/", root_dir, NULL, MS_BIND, 0) < 0) {
lxcfs_error("Failed to bind-mount / for new root: %s.\n", strerror(errno));
return -1;
}

if (mount(RUNTIME_PATH, ROOTDIR RUNTIME_PATH, NULL, MS_BIND, 0) < 0) {
lxcfs_error("Failed to bind-mount /run into new root: %s.\n", strerror(errno));
if (!mkdir_p(new_runtime, 0700)) {
lxcfs_error("Failed to create dir %s\n", new_runtime);
return -1;
}

if (mount(runtime_path, new_runtime, NULL, MS_BIND, 0) < 0) {
lxcfs_error("Failed to bind-mount %s into new root: %s.\n", runtime_path, strerror(errno));
return -1;
}

if (mount(BASEDIR, ROOTDIR BASEDIR, NULL, MS_REC | MS_MOVE, 0) < 0) {
printf("Failed to move " BASEDIR " into new root: %s.\n", strerror(errno));
if (mount(base_dir, new_base_dir, NULL, MS_REC | MS_MOVE, 0) < 0) {
printf("Failed to move %s into new root: %s.\n", base_dir, strerror(errno));
return -1;
}

Expand All @@ -764,7 +796,9 @@ static bool permute_root(void)

static bool cgfs_prepare_mounts(void)
{
if (!mkdir_p(BASEDIR, 0700)) {
__do_free char *base_dir = get_base_dir();

if (!mkdir_p(base_dir, 0700)) {
lxcfs_error("%s\n", "Failed to create lxcfs cgroup mountpoint.");
return false;
}
Expand All @@ -790,7 +824,7 @@ static bool cgfs_prepare_mounts(void)
return false;
}

if (mount("tmpfs", BASEDIR, "tmpfs", 0, "size=100000,mode=700") < 0) {
if (mount("tmpfs", base_dir, "tmpfs", 0, "size=100000,mode=700") < 0) {
lxcfs_error("%s\n", "Failed to mount tmpfs over lxcfs cgroup mountpoint.");
return false;
}
Expand All @@ -800,14 +834,17 @@ static bool cgfs_prepare_mounts(void)

static bool cgfs_mount_hierarchies(void)
{
if (!mkdir_p(BASEDIR DEFAULT_CGROUP_MOUNTPOINT, 0755))
__do_free char *base_dir = get_base_dir();
__do_free char *base_dir_cgroup_mount = must_make_path(base_dir, DEFAULT_CGROUP_MOUNTPOINT, NULL);

if (!mkdir_p(base_dir_cgroup_mount, 0700))
return false;

if (!cgroup_ops->mount(cgroup_ops, BASEDIR))
if (!cgroup_ops->mount(cgroup_ops, base_dir))
return false;

for (struct hierarchy **h = cgroup_ops->hierarchies; h && *h; h++) {
__do_free char *path = must_make_path(BASEDIR, (*h)->mountpoint, NULL);
__do_free char *path = must_make_path(base_dir, (*h)->mountpoint, NULL);
(*h)->fd = open(path, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
if ((*h)->fd < 0)
return false;
Expand Down Expand Up @@ -862,7 +899,19 @@ static void sigusr2_toggle_virtualization(int signo, siginfo_t *info, void *extr
return;
}

static void __attribute__((constructor)) lxcfs_init(void)
bool set_runtime_path(const char* new_path)
{
if (new_path && strlen(new_path) < PATH_MAX) {
strcpy(runtime_path, new_path);
lxcfs_info("Using runtime path %s", runtime_path);
return true;
} else {
lxcfs_error("%s\n", "Failed to overwrite the runtime path");
return false;
}
}

void lxcfslib_init(void)
{
__do_close int init_ns = -EBADF, root_fd = -EBADF,
pidfd = -EBADF;
Expand All @@ -871,7 +920,7 @@ static void __attribute__((constructor)) lxcfs_init(void)
pid_t pid;
struct hierarchy *hierarchy;

lxcfs_info("Running constructor %s to reload liblxcfs", __func__);
lxcfs_info("Running %s to reload liblxcfs", __func__);

cgroup_ops = cgroup_init();
if (!cgroup_ops) {
Expand Down Expand Up @@ -971,9 +1020,20 @@ static void __attribute__((destructor)) lxcfs_exit(void)
void *lxcfs_fuse_init(struct fuse_conn_info *conn, void *data)
{
struct fuse_context *fc = fuse_get_context();
struct lxcfs_opts *opts = fc ? fc->private_data : NULL;

#if HAVE_FUSE_RETURNS_DT_TYPE
can_use_sys_cpu = true;
#endif
has_versioned_opts = true;
return fc ? fc->private_data : NULL;

// We can read runtime_path as of opts version 2.
if (opts && opts->version >= 2) {
set_runtime_path(opts->runtime_path);
}

/* initialize the library */
lxcfslib_init();

return opts;
}
6 changes: 2 additions & 4 deletions src/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@
#include "proc_loadavg.h"
#include "sysfs_fuse.h"

/* directory under which we mount the controllers - /run/lxcfs/controllers */
#define BASEDIR RUNTIME_PATH "/lxcfs/controllers"
#define ROOTDIR RUNTIME_PATH "/lxcfs/root"

/* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */
#define LXCFS_NUMSTRLEN64 21

Expand Down Expand Up @@ -116,6 +112,8 @@ struct lxcfs_opts {
* and the use of bool instead of explicited __u32 and __u64 we can't.
*/
__u32 version;
// As of opts version 2.
char runtime_path[PATH_MAX];
};

typedef enum lxcfs_opt_t {
Expand Down
34 changes: 25 additions & 9 deletions src/lxcfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
#include "macro.h"
#include "memory_utils.h"

#define PID_FILE "/lxcfs.pid"

void *dlopen_handle;
static char runtime_path[PATH_MAX] = DEFAULT_RUNTIME_PATH;


/* Functions to keep track of number of threads using the library */

Expand Down Expand Up @@ -146,7 +150,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);
Expand Down Expand Up @@ -199,13 +203,12 @@ 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:
/* initialize the library */
if (reinit && lxcfs_init_library() < 0) {
if (reinit && do_lxcfs_fuse_init() < 0) {
log_exit("Failed to initialize liblxcfs.so");
}

Expand Down Expand Up @@ -1119,7 +1122,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
Expand Down Expand Up @@ -1187,12 +1190,14 @@ static void usage(void)
lxcfs_info(" -l, --enable-loadavg Enable loadavg virtualization");
lxcfs_info(" -o Options to pass directly through fuse");
lxcfs_info(" -p, --pidfile=FILE Path to use for storing lxcfs pid");
lxcfs_info(" Default pidfile is %s/lxcfs.pid", RUNTIME_PATH);
lxcfs_info(" Default pidfile is %s/lxcfs.pid", DEFAULT_RUNTIME_PATH);
lxcfs_info(" -u, --disable-swap Disable swap virtualization");
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(" --enable-cgroup Enable cgroup emulation code");
lxcfs_info(" --runtime-dir=DIR Path to use as the runtime directory.");
lxcfs_info(" Default is %s", DEFAULT_RUNTIME_PATH);
exit(EXIT_FAILURE);
}

Expand Down Expand Up @@ -1244,6 +1249,7 @@ static const struct option long_options[] = {
{"enable-cgroup", no_argument, 0, 0 },

{"pidfile", required_argument, 0, 'p' },
{"runtime-dir", required_argument, 0, 0 },
{ },
};

Expand Down Expand Up @@ -1286,7 +1292,7 @@ int main(int argc, char *argv[])
int pidfile_fd = -EBADF;
int ret = EXIT_FAILURE;
char *pidfile = NULL, *token = NULL;
char pidfile_buf[STRLITERALLEN(RUNTIME_PATH) + STRLITERALLEN("/lxcfs.pid") + 1] = {};
char pidfile_buf[PATH_MAX + sizeof(PID_FILE)] = {};
bool debug = false, foreground = false;
#if !HAVE_FUSE3
bool nonempty = false;
Expand All @@ -1303,6 +1309,7 @@ int main(int argc, char *argv[])
char *new_fuse_opts = NULL;
char *const *new_argv;
struct lxcfs_opts *opts;
char *runtime_path_arg = NULL;

opts = malloc(sizeof(struct lxcfs_opts));
if (opts == NULL) {
Expand All @@ -1313,7 +1320,7 @@ int main(int argc, char *argv[])
opts->swap_off = false;
opts->use_pidfd = false;
opts->use_cfs = false;
opts->version = 1;
opts->version = 2;

while ((c = getopt_long(argc, argv, "dulfhvso:p:", long_options, &idx)) != -1) {
switch (c) {
Expand All @@ -1324,6 +1331,8 @@ int main(int argc, char *argv[])
opts->use_cfs = true;
else if (strcmp(long_options[idx].name, "enable-cgroup") == 0)
cgroup_is_enabled = true;
else if (strcmp(long_options[idx].name, "runtime-dir") == 0)
runtime_path_arg = optarg;
else
usage();
break;
Expand Down Expand Up @@ -1376,6 +1385,12 @@ int main(int argc, char *argv[])
goto out;
}

if (runtime_path_arg) {
strcpy(runtime_path, runtime_path_arg);
lxcfs_info("runtime path set to %s", runtime_path);
}
strcpy(opts->runtime_path, runtime_path);

fuse_argv[fuse_argc++] = argv[0];
if (debug)
fuse_argv[fuse_argc++] = "-d";
Expand Down Expand Up @@ -1467,6 +1482,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;
Expand All @@ -1480,7 +1496,7 @@ int main(int argc, char *argv[])
#endif

if (!pidfile) {
snprintf(pidfile_buf, sizeof(pidfile_buf), "%s/lxcfs.pid", RUNTIME_PATH);
snprintf(pidfile_buf, sizeof(pidfile_buf), "%s%s", runtime_path, PID_FILE);
pidfile = pidfile_buf;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/main.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ if [ -x ${lxcfs} ]; then
LXCFSPID=$!
else
UNSHARE=0
LXCFSPID=$(cat "{{RUNTIME_PATH}}/lxcfs.pid")
LXCFSPID=$(cat "{{DEFAULT_RUNTIME_PATH}}/lxcfs.pid")
echo "=> Re-using host lxcfs"
rmdir $LXCFSDIR
export LXCFSDIR=/var/lib/lxcfs
Expand Down
Loading