From: hallyn Date: Mon, 25 Nov 2013 21:55:30 +0000 (-0800) Subject: Merge pull request #92 from majek/share-namespaces X-Git-Tag: lxc-1.0.0.beta1~93 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7faa7f52004943f339199bcbad1848cdf50d5f4c;p=thirdparty%2Flxc.git Merge pull request #92 from majek/share-namespaces Add options to `lxc-start` to inherit network, ipc and uts namespaces --- 7faa7f52004943f339199bcbad1848cdf50d5f4c diff --cc src/lxc/conf.c index 860fc5b63,dfc49e435..534e6e6fb --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@@ -3377,93 -3139,13 +3380,95 @@@ int ttys_shift_ids(struct lxc_conf *c return 0; } -int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath, struct cgroup_process_info *cgroup_info) +/* + * This routine is called when the configuration does not already specify a value + * for autodev (mounting a file system on /dev and populating it in a container). + * If a hard override value has not be specified, then we try to apply some + * heuristics to determine if we should switch to autodev mode. + * + * For instance, if the container has an /etc/systemd/system directory then it + * is probably running systemd as the init process and it needs the autodev + * mount to prevent it from mounting devtmpfs on /dev on it's own causing conflicts + * in the host. + * + * We may also want to enable autodev if the host has devtmpfs mounted on its + * /dev as this then enable us to use subdirectories under /dev for the container + * /dev directories and we can fake udev devices. + */ +struct start_args { + char *const *argv; +}; + +#define MAX_SYMLINK_DEPTH 32 + +int check_autodev( const char *rootfs, void *data ) +{ + struct start_args *arg = data; + int ret; + int loop_count = 0; + struct stat s; + char absrootfs[MAXPATHLEN]; + char path[MAXPATHLEN]; + char abs_path[MAXPATHLEN]; + char *command = "/sbin/init"; + + if (rootfs == NULL || strlen(rootfs) == 0) + return -2; + + if (!realpath(rootfs, absrootfs)) + return -2; + + if( arg && arg->argv[0] ) { + command = arg->argv[0]; + DEBUG("Set exec command to %s\n", command ); + } + + strncpy( path, command, MAXPATHLEN-1 ); + + if ( 0 != access(path, F_OK) || 0 != stat(path, &s) ) + return -2; + + /* Dereference down the symlink merry path testing as we go. */ + /* If anything references systemd in the path - set autodev! */ + /* Renormalize to the rootfs before each dereference */ + /* Relative symlinks should fall out in the wash even with .. */ + while( 1 ) { + if ( strstr( path, "systemd" ) ) { + INFO("Container with systemd init detected - enabling autodev!"); + return 1; + } + + ret = snprintf(abs_path, MAXPATHLEN-1, "%s/%s", absrootfs, path); + if (ret < 0 || ret > MAXPATHLEN) + return -2; + + ret = readlink( abs_path, path, MAXPATHLEN-1 ); + + if ( ( ret <= 0 ) || ( ++loop_count > MAX_SYMLINK_DEPTH ) ) { + break; /* Break out for other tests */ + } + path[ret] = '\0'; + } + + /* + * Add future checks here. + * Return positive if we should go autodev + * Return 0 if we should NOT go autodev + * Return negative if we encounter an error or can not determine... + */ + + /* All else fails, we don't need autodev */ + INFO("Autodev not required."); + return 0; +} + +int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath, struct cgroup_process_info *cgroup_info, void *data) { - if (setup_utsname(lxc_conf->utsname)) { - ERROR("failed to setup the utsname for '%s'", name); - return -1; + if (lxc_conf->inherit_ns_fd[LXC_NS_UTS] == -1) { + if (setup_utsname(lxc_conf->utsname)) { + ERROR("failed to setup the utsname for '%s'", name); + return -1; + } } if (setup_network(&lxc_conf->network)) {