confile: final cleanups

parent 9c61a6d6
...@@ -213,77 +213,77 @@ static int set_config_limit(const char *, const char *, struct lxc_conf *); ...@@ -213,77 +213,77 @@ static int set_config_limit(const char *, const char *, struct lxc_conf *);
static int get_config_limit(const char *, char *, int, struct lxc_conf *); static int get_config_limit(const char *, char *, int, struct lxc_conf *);
static struct lxc_config_t config[] = { static struct lxc_config_t config[] = {
{ "lxc.arch", set_config_personality, get_config_personality, NULL}, { "lxc.arch", set_config_personality, get_config_personality, NULL },
{ "lxc.pts", set_config_pts, get_config_pts, NULL}, { "lxc.pts", set_config_pts, get_config_pts, NULL },
{ "lxc.tty", set_config_tty, get_config_tty, NULL}, { "lxc.tty", set_config_tty, get_config_tty, NULL },
{ "lxc.devttydir", set_config_ttydir, get_config_ttydir, NULL}, { "lxc.devttydir", set_config_ttydir, get_config_ttydir, NULL },
{ "lxc.kmsg", set_config_kmsg, get_config_kmsg, NULL}, { "lxc.kmsg", set_config_kmsg, get_config_kmsg, NULL },
{ "lxc.aa_profile", set_config_lsm_aa_profile, get_config_lsm_aa_profile, NULL}, { "lxc.aa_profile", set_config_lsm_aa_profile, get_config_lsm_aa_profile, NULL },
{ "lxc.aa_allow_incomplete", set_config_lsm_aa_incomplete, get_config_lsm_aa_incomplete, NULL}, { "lxc.aa_allow_incomplete", set_config_lsm_aa_incomplete, get_config_lsm_aa_incomplete, NULL },
{ "lxc.se_context", set_config_lsm_se_context, get_config_lsm_se_context, NULL}, { "lxc.se_context", set_config_lsm_se_context, get_config_lsm_se_context, NULL },
{ "lxc.cgroup", set_config_cgroup, get_config_cgroup, NULL}, { "lxc.cgroup", set_config_cgroup, get_config_cgroup, NULL },
{ "lxc.id_map", set_config_idmaps, get_config_idmaps, NULL}, { "lxc.id_map", set_config_idmaps, get_config_idmaps, NULL },
{ "lxc.loglevel", set_config_loglevel, get_config_loglevel, NULL}, { "lxc.loglevel", set_config_loglevel, get_config_loglevel, NULL },
{ "lxc.logfile", set_config_logfile, get_config_logfile, NULL}, { "lxc.logfile", set_config_logfile, get_config_logfile, NULL },
{ "lxc.mount.entry", set_config_mount, get_config_mount, NULL}, { "lxc.mount.entry", set_config_mount, get_config_mount, NULL },
{ "lxc.mount.auto", set_config_mount_auto, get_config_mount_auto, NULL}, { "lxc.mount.auto", set_config_mount_auto, get_config_mount_auto, NULL },
{ "lxc.mount", set_config_fstab, get_config_fstab, NULL}, { "lxc.mount", set_config_fstab, get_config_fstab, NULL },
{ "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, NULL}, { "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, NULL },
{ "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, NULL}, { "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, NULL },
{ "lxc.rootfs.backend", set_config_rootfs_backend, get_config_rootfs_backend, NULL}, { "lxc.rootfs.backend", set_config_rootfs_backend, get_config_rootfs_backend, NULL },
{ "lxc.rootfs", set_config_rootfs, get_config_rootfs, NULL}, { "lxc.rootfs", set_config_rootfs, get_config_rootfs, NULL },
{ "lxc.pivotdir", set_config_pivotdir, get_config_pivotdir, NULL}, { "lxc.pivotdir", set_config_pivotdir, get_config_pivotdir, NULL },
{ "lxc.utsname", set_config_utsname, get_config_utsname, NULL}, { "lxc.utsname", set_config_utsname, get_config_utsname, NULL },
{ "lxc.hook.pre-start", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.pre-start", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook.pre-mount", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.pre-mount", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook.mount", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.mount", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook.autodev", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.autodev", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook.start", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.start", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook.stop", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.stop", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook.post-stop", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.post-stop", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook.clone", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.clone", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook.destroy", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook.destroy", set_config_hooks, get_config_hooks, NULL },
{ "lxc.hook", set_config_hooks, get_config_hooks, NULL}, { "lxc.hook", set_config_hooks, get_config_hooks, NULL },
{ "lxc.network.type", set_config_network_type, get_config_network_item, NULL}, { "lxc.network.type", set_config_network_type, get_config_network_item, NULL },
{ "lxc.network.flags", set_config_network_flags, get_config_network_item, NULL}, { "lxc.network.flags", set_config_network_flags, get_config_network_item, NULL },
{ "lxc.network.link", set_config_network_link, get_config_network_item, NULL}, { "lxc.network.link", set_config_network_link, get_config_network_item, NULL },
{ "lxc.network.name", set_config_network_name, get_config_network_item, NULL}, { "lxc.network.name", set_config_network_name, get_config_network_item, NULL },
{ "lxc.network.macvlan.mode", set_config_network_macvlan_mode, get_config_network_item, NULL}, { "lxc.network.macvlan.mode", set_config_network_macvlan_mode, get_config_network_item, NULL },
{ "lxc.network.veth.pair", set_config_network_veth_pair, get_config_network_item, NULL}, { "lxc.network.veth.pair", set_config_network_veth_pair, get_config_network_item, NULL },
{ "lxc.network.script.up", set_config_network_script_up, get_config_network_item, NULL}, { "lxc.network.script.up", set_config_network_script_up, get_config_network_item, NULL },
{ "lxc.network.script.down", set_config_network_script_down, get_config_network_item, NULL}, { "lxc.network.script.down", set_config_network_script_down, get_config_network_item, NULL },
{ "lxc.network.hwaddr", set_config_network_hwaddr, get_config_network_item, NULL}, { "lxc.network.hwaddr", set_config_network_hwaddr, get_config_network_item, NULL },
{ "lxc.network.mtu", set_config_network_mtu, get_config_network_item, NULL}, { "lxc.network.mtu", set_config_network_mtu, get_config_network_item, NULL },
{ "lxc.network.vlan.id", set_config_network_vlan_id, get_config_network_item, NULL}, { "lxc.network.vlan.id", set_config_network_vlan_id, get_config_network_item, NULL },
{ "lxc.network.ipv4.gateway", set_config_network_ipv4_gateway, get_config_network_item, NULL}, { "lxc.network.ipv4.gateway", set_config_network_ipv4_gateway, get_config_network_item, NULL },
{ "lxc.network.ipv4", set_config_network_ipv4, get_config_network_item, NULL}, { "lxc.network.ipv4", set_config_network_ipv4, get_config_network_item, NULL },
{ "lxc.network.ipv6.gateway", set_config_network_ipv6_gateway, get_config_network_item, NULL}, { "lxc.network.ipv6.gateway", set_config_network_ipv6_gateway, get_config_network_item, NULL },
{ "lxc.network.ipv6", set_config_network_ipv6, get_config_network_item, NULL}, { "lxc.network.ipv6", set_config_network_ipv6, get_config_network_item, NULL },
{ "lxc.network.", set_config_network_nic, get_config_network_item, NULL}, { "lxc.network.", set_config_network_nic, get_config_network_item, NULL },
{ "lxc.network", set_config_network, get_config_network, NULL}, { "lxc.network", set_config_network, get_config_network, NULL },
{ "lxc.cap.drop", set_config_cap_drop, get_config_cap_drop, NULL}, { "lxc.cap.drop", set_config_cap_drop, get_config_cap_drop, NULL },
{ "lxc.cap.keep", set_config_cap_keep, get_config_cap_keep, NULL}, { "lxc.cap.keep", set_config_cap_keep, get_config_cap_keep, NULL },
{ "lxc.console.logfile", set_config_console_logfile, get_config_console_logfile, NULL}, { "lxc.console.logfile", set_config_console_logfile, get_config_console_logfile, NULL },
{ "lxc.console", set_config_console, get_config_console, NULL}, { "lxc.console", set_config_console, get_config_console, NULL },
{ "lxc.seccomp", set_config_seccomp, get_config_seccomp, NULL}, { "lxc.seccomp", set_config_seccomp, get_config_seccomp, NULL },
{ "lxc.include", set_config_includefile, NULL, NULL}, { "lxc.include", set_config_includefile, NULL, NULL },
{ "lxc.autodev", set_config_autodev, get_config_autodev, NULL}, { "lxc.autodev", set_config_autodev, get_config_autodev, NULL },
{ "lxc.haltsignal", set_config_haltsignal, get_config_haltsignal, NULL}, { "lxc.haltsignal", set_config_haltsignal, get_config_haltsignal, NULL },
{ "lxc.rebootsignal", set_config_rebootsignal, get_config_rebootsignal, NULL}, { "lxc.rebootsignal", set_config_rebootsignal, get_config_rebootsignal, NULL },
{ "lxc.stopsignal", set_config_stopsignal, get_config_stopsignal, NULL}, { "lxc.stopsignal", set_config_stopsignal, get_config_stopsignal, NULL },
{ "lxc.start.auto", set_config_start, get_config_start, NULL}, { "lxc.start.auto", set_config_start, get_config_start, NULL },
{ "lxc.start.delay", set_config_start, get_config_start, NULL}, { "lxc.start.delay", set_config_start, get_config_start, NULL },
{ "lxc.start.order", set_config_start, get_config_start, NULL}, { "lxc.start.order", set_config_start, get_config_start, NULL },
{ "lxc.monitor.unshare", set_config_monitor, get_config_monitor, NULL}, { "lxc.monitor.unshare", set_config_monitor, get_config_monitor, NULL },
{ "lxc.group", set_config_group, get_config_group, NULL}, { "lxc.group", set_config_group, get_config_group, NULL },
{ "lxc.environment", set_config_environment, get_config_environment, NULL}, { "lxc.environment", set_config_environment, get_config_environment, NULL },
{ "lxc.init_cmd", set_config_init_cmd, get_config_init_cmd, NULL}, { "lxc.init_cmd", set_config_init_cmd, get_config_init_cmd, NULL },
{ "lxc.init_uid", set_config_init_uid, get_config_init_uid, NULL}, { "lxc.init_uid", set_config_init_uid, get_config_init_uid, NULL },
{ "lxc.init_gid", set_config_init_gid, get_config_init_gid, NULL}, { "lxc.init_gid", set_config_init_gid, get_config_init_gid, NULL },
{ "lxc.ephemeral", set_config_ephemeral, get_config_ephemeral, NULL}, { "lxc.ephemeral", set_config_ephemeral, get_config_ephemeral, NULL },
{ "lxc.syslog", set_config_syslog, get_config_syslog, NULL}, { "lxc.syslog", set_config_syslog, get_config_syslog, NULL },
{ "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, NULL}, { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, NULL },
{ "lxc.limit", set_config_limit, get_config_limit, NULL}, { "lxc.limit", set_config_limit, get_config_limit, NULL },
}; };
struct signame { struct signame {
...@@ -292,124 +292,131 @@ struct signame { ...@@ -292,124 +292,131 @@ struct signame {
}; };
static const struct signame signames[] = { static const struct signame signames[] = {
{ SIGHUP, "HUP" }, { SIGHUP, "HUP" },
{ SIGINT, "INT" }, { SIGINT, "INT" },
{ SIGQUIT, "QUIT" }, { SIGQUIT, "QUIT" },
{ SIGILL, "ILL" }, { SIGILL, "ILL" },
{ SIGABRT, "ABRT" }, { SIGABRT, "ABRT" },
{ SIGFPE, "FPE" }, { SIGFPE, "FPE" },
{ SIGKILL, "KILL" }, { SIGKILL, "KILL" },
{ SIGSEGV, "SEGV" }, { SIGSEGV, "SEGV" },
{ SIGPIPE, "PIPE" }, { SIGPIPE, "PIPE" },
{ SIGALRM, "ALRM" }, { SIGALRM, "ALRM" },
{ SIGTERM, "TERM" }, { SIGTERM, "TERM" },
{ SIGUSR1, "USR1" }, { SIGUSR1, "USR1" },
{ SIGUSR2, "USR2" }, { SIGUSR2, "USR2" },
{ SIGCHLD, "CHLD" }, { SIGCHLD, "CHLD" },
{ SIGCONT, "CONT" }, { SIGCONT, "CONT" },
{ SIGSTOP, "STOP" }, { SIGSTOP, "STOP" },
{ SIGTSTP, "TSTP" }, { SIGTSTP, "TSTP" },
{ SIGTTIN, "TTIN" }, { SIGTTIN, "TTIN" },
{ SIGTTOU, "TTOU" }, { SIGTTOU, "TTOU" },
#ifdef SIGTRAP #ifdef SIGTRAP
{ SIGTRAP, "TRAP" }, { SIGTRAP, "TRAP" },
#endif #endif
#ifdef SIGIOT #ifdef SIGIOT
{ SIGIOT, "IOT" }, { SIGIOT, "IOT" },
#endif #endif
#ifdef SIGEMT #ifdef SIGEMT
{ SIGEMT, "EMT" }, { SIGEMT, "EMT" },
#endif #endif
#ifdef SIGBUS #ifdef SIGBUS
{ SIGBUS, "BUS" }, { SIGBUS, "BUS" },
#endif #endif
#ifdef SIGSTKFLT #ifdef SIGSTKFLT
{ SIGSTKFLT, "STKFLT" }, { SIGSTKFLT, "STKFLT" },
#endif #endif
#ifdef SIGCLD #ifdef SIGCLD
{ SIGCLD, "CLD" }, { SIGCLD, "CLD" },
#endif #endif
#ifdef SIGURG #ifdef SIGURG
{ SIGURG, "URG" }, { SIGURG, "URG" },
#endif #endif
#ifdef SIGXCPU #ifdef SIGXCPU
{ SIGXCPU, "XCPU" }, { SIGXCPU, "XCPU" },
#endif #endif
#ifdef SIGXFSZ #ifdef SIGXFSZ
{ SIGXFSZ, "XFSZ" }, { SIGXFSZ, "XFSZ" },
#endif #endif
#ifdef SIGVTALRM #ifdef SIGVTALRM
{ SIGVTALRM, "VTALRM" }, { SIGVTALRM, "VTALRM" },
#endif #endif
#ifdef SIGPROF #ifdef SIGPROF
{ SIGPROF, "PROF" }, { SIGPROF, "PROF" },
#endif #endif
#ifdef SIGWINCH #ifdef SIGWINCH
{ SIGWINCH, "WINCH" }, { SIGWINCH, "WINCH" },
#endif #endif
#ifdef SIGIO #ifdef SIGIO
{ SIGIO, "IO" }, { SIGIO, "IO" },
#endif #endif
#ifdef SIGPOLL #ifdef SIGPOLL
{ SIGPOLL, "POLL" }, { SIGPOLL, "POLL" },
#endif #endif
#ifdef SIGINFO #ifdef SIGINFO
{ SIGINFO, "INFO" }, { SIGINFO, "INFO" },
#endif #endif
#ifdef SIGLOST #ifdef SIGLOST
{ SIGLOST, "LOST" }, { SIGLOST, "LOST" },
#endif #endif
#ifdef SIGPWR #ifdef SIGPWR
{ SIGPWR, "PWR" }, { SIGPWR, "PWR" },
#endif #endif
#ifdef SIGUNUSED #ifdef SIGUNUSED
{ SIGUNUSED, "UNUSED" }, { SIGUNUSED, "UNUSED" },
#endif #endif
#ifdef SIGSYS #ifdef SIGSYS
{ SIGSYS, "SYS" }, { SIGSYS, "SYS" },
#endif #endif
}; };
static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t); static const size_t config_size = sizeof(config) / sizeof(struct lxc_config_t);
extern struct lxc_config_t *lxc_getconfig(const char *key) extern struct lxc_config_t *lxc_getconfig(const char *key)
{ {
size_t i; size_t i;
for (i = 0; i < config_size; i++) for (i = 0; i < config_size; i++)
if (!strncmp(config[i].name, key, if (!strncmp(config[i].name, key, strlen(config[i].name)))
strlen(config[i].name)))
return &config[i]; return &config[i];
return NULL; return NULL;
} }
#define strprint(str, inlen, ...) \ #define strprint(str, inlen, ...) \
do { \ do { \
len = snprintf(str, inlen, ##__VA_ARGS__); \ len = snprintf(str, inlen, ##__VA_ARGS__); \
if (len < 0) { SYSERROR("snprintf"); return -1; }; \ if (len < 0) { \
fulllen += len; \ SYSERROR("failed to create string"); \
if (inlen > 0) { \ return -1; \
if (str) str += len; \ }; \
inlen -= len; \ fulllen += len; \
if (inlen < 0) inlen = 0; \ if (inlen > 0) { \
} \ if (str) \
str += len; \
inlen -= len; \
if (inlen < 0) \
inlen = 0; \
} \
} while (0); } while (0);
int lxc_listconfigs(char *retv, int inlen) int lxc_listconfigs(char *retv, int inlen)
{ {
size_t i; size_t i;
int fulllen = 0, len; int len;
int fulllen = 0;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
else else
memset(retv, 0, inlen); memset(retv, 0, inlen);
for (i = 0; i < config_size; i++) { for (i = 0; i < config_size; i++) {
char *s = config[i].name; char *s = config[i].name;
if (s[strlen(s)-1] == '.') if (s[strlen(s) - 1] == '.')
continue; continue;
strprint(retv, inlen, "%s\n", s); strprint(retv, inlen, "%s\n", s);
} }
return fulllen; return fulllen;
} }
...@@ -443,7 +450,7 @@ static int set_config_string_item(char **conf_item, const char *value) ...@@ -443,7 +450,7 @@ static int set_config_string_item(char **conf_item, const char *value)
} }
static int set_config_string_item_max(char **conf_item, const char *value, static int set_config_string_item_max(char **conf_item, const char *value,
size_t max) size_t max)
{ {
if (strlen(value) >= max) { if (strlen(value) >= max) {
ERROR("%s is too long (>= %lu)", value, (unsigned long)max); ERROR("%s is too long (>= %lu)", value, (unsigned long)max);
...@@ -459,13 +466,12 @@ static int set_config_path_item(char **conf_item, const char *value) ...@@ -459,13 +466,12 @@ static int set_config_path_item(char **conf_item, const char *value)
} }
/* /*
* config entry is something like "lxc.network.0.ipv4" * Config entry is something like "lxc.network.0.ipv4" the key 'lxc.network.'
* the key 'lxc.network.' was found. So we make sure next * was found. So we make sure next comes an integer, find the right callback
* comes an integer, find the right callback (by rewriting * (by rewriting the key), and call it.
* the key), and call it.
*/ */
static int set_config_network_nic(const char *key, const char *value, static int set_config_network_nic(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
char *copy = strdup(key), *p; char *copy = strdup(key), *p;
int ret = -1; int ret = -1;
...@@ -476,17 +482,19 @@ static int set_config_network_nic(const char *key, const char *value, ...@@ -476,17 +482,19 @@ static int set_config_network_nic(const char *key, const char *value,
return -1; return -1;
} }
/* /*
* ok we know that to get here we've got "lxc.network." * Ok we know that to get here we've got "lxc.network."
* and it isn't any of the other network entries. So * and it isn't any of the other network entries. So
* after the second . should come an integer (# of defined * after the second . Should come an integer (# of defined
* nic) followed by a valid entry. * nic) followed by a valid entry.
*/ */
if (*(key+12) < '0' || *(key+12) > '9') if (*(key + 12) < '0' || *(key + 12) > '9')
goto out; goto out;
p = strchr(key+12, '.');
p = strchr(key + 12, '.');
if (!p) if (!p)
goto out; goto out;
strcpy(copy+12, p+1);
strcpy(copy + 12, p + 1);
config = lxc_getconfig(copy); config = lxc_getconfig(copy);
if (!config) { if (!config) {
ERROR("unknown key %s", key); ERROR("unknown key %s", key);
...@@ -500,7 +508,7 @@ out: ...@@ -500,7 +508,7 @@ out:
} }
static int set_config_network(const char *key, const char *value, static int set_config_network(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
if (!config_value_empty(value)) { if (!config_value_empty(value)) {
ERROR("lxc.network must not have a value"); ERROR("lxc.network must not have a value");
...@@ -513,7 +521,7 @@ static int set_config_network(const char *key, const char *value, ...@@ -513,7 +521,7 @@ static int set_config_network(const char *key, const char *value,
static int macvlan_mode(int *valuep, const char *value); static int macvlan_mode(int *valuep, const char *value);
static int set_config_network_type(const char *key, const char *value, static int set_config_network_type(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_list *network = &lxc_conf->network; struct lxc_list *network = &lxc_conf->network;
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -549,8 +557,7 @@ static int set_config_network_type(const char *key, const char *value, ...@@ -549,8 +557,7 @@ static int set_config_network_type(const char *key, const char *value,
else if (!strcmp(value, "macvlan")) { else if (!strcmp(value, "macvlan")) {
netdev->type = LXC_NET_MACVLAN; netdev->type = LXC_NET_MACVLAN;
macvlan_mode(&netdev->priv.macvlan_attr.mode, "private"); macvlan_mode(&netdev->priv.macvlan_attr.mode, "private");
} } else if (!strcmp(value, "vlan"))
else if (!strcmp(value, "vlan"))
netdev->type = LXC_NET_VLAN; netdev->type = LXC_NET_VLAN;
else if (!strcmp(value, "phys")) else if (!strcmp(value, "phys"))
netdev->type = LXC_NET_PHYS; netdev->type = LXC_NET_PHYS;
...@@ -578,8 +585,8 @@ static int config_ip_prefix(struct in_addr *addr) ...@@ -578,8 +585,8 @@ static int config_ip_prefix(struct in_addr *addr)
} }
/* /*
* if you have p="lxc.network.0.link", pass it p+12 * If you have p="lxc.network.0.link", pass it p+12
* to get back '0' (the index of the nic) * to get back '0' (the index of the nic).
*/ */
static int get_network_netdev_idx(const char *key) static int get_network_netdev_idx(const char *key)
{ {
...@@ -587,40 +594,48 @@ static int get_network_netdev_idx(const char *key) ...@@ -587,40 +594,48 @@ static int get_network_netdev_idx(const char *key)
if (*key < '0' || *key > '9') if (*key < '0' || *key > '9')
return -1; return -1;
ret = sscanf(key, "%d", &idx); ret = sscanf(key, "%d", &idx);
if (ret != 1) if (ret != 1)
return -1; return -1;
return idx; return idx;
} }
/* /*
* if you have p="lxc.network.0", pass this p+12 and it will return * If you have p="lxc.network.0", pass this p+12 and it will return
* the netdev of the first configured nic * the netdev of the first configured nic.
*/ */
static struct lxc_netdev *get_netdev_from_key(const char *key, static struct lxc_netdev *get_netdev_from_key(const char *key,
struct lxc_list *network) struct lxc_list *network)
{ {
int i = 0, idx = get_network_netdev_idx(key); int idx;
struct lxc_netdev *netdev = NULL;
struct lxc_list *it; struct lxc_list *it;
int i = 0;
struct lxc_netdev *netdev = NULL;
idx = get_network_netdev_idx(key);
if (idx == -1) if (idx == -1)
return NULL; return NULL;
lxc_list_for_each(it, network) { lxc_list_for_each(it, network) {
if (idx == i++) { if (idx == i++) {
netdev = it->elem; netdev = it->elem;
break; break;
} }
} }
return netdev; return netdev;
} }
extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, char *retv,
char *retv, int inlen) int inlen)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
int fulllen = 0, len; int len;
int fulllen = 0;
netdev = get_netdev_from_key(key+12, &c->network); netdev = get_netdev_from_key(key + 12, &c->network);
if (!netdev) if (!netdev)
return -1; return -1;
...@@ -643,7 +658,8 @@ extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, ...@@ -643,7 +658,8 @@ extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
strprint(retv, inlen, "ipv4\n"); strprint(retv, inlen, "ipv4\n");
strprint(retv, inlen, "ipv4.gateway\n"); strprint(retv, inlen, "ipv4.gateway\n");
} }
switch(netdev->type) {
switch (netdev->type) {
case LXC_NET_VETH: case LXC_NET_VETH:
strprint(retv, inlen, "veth.pair\n"); strprint(retv, inlen, "veth.pair\n");
break; break;
...@@ -656,6 +672,7 @@ extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, ...@@ -656,6 +672,7 @@ extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
case LXC_NET_PHYS: case LXC_NET_PHYS:
break; break;
} }
return fulllen; return fulllen;
} }
...@@ -665,19 +682,19 @@ static struct lxc_netdev *network_netdev(const char *key, const char *value, ...@@ -665,19 +682,19 @@ static struct lxc_netdev *network_netdev(const char *key, const char *value,
struct lxc_netdev *netdev = NULL; struct lxc_netdev *netdev = NULL;
if (lxc_list_empty(network)) { if (lxc_list_empty(network)) {
ERROR("network is not created for '%s' = '%s' option", ERROR("network is not created for '%s' = '%s' option", key,
key, value); value);
return NULL; return NULL;
} }
if (get_network_netdev_idx(key+12) == -1) if (get_network_netdev_idx(key + 12) == -1)
netdev = lxc_list_last_elem(network); netdev = lxc_list_last_elem(network);
else else
netdev = get_netdev_from_key(key+12, network); netdev = get_netdev_from_key(key + 12, network);
if (!netdev) { if (!netdev) {
ERROR("no network device defined for '%s' = '%s' option", ERROR("no network device defined for '%s' = '%s' option", key,
key, value); value);
return NULL; return NULL;
} }
...@@ -690,19 +707,19 @@ static int network_ifname(char **valuep, const char *value) ...@@ -690,19 +707,19 @@ static int network_ifname(char **valuep, const char *value)
} }
#ifndef MACVLAN_MODE_PRIVATE #ifndef MACVLAN_MODE_PRIVATE
# define MACVLAN_MODE_PRIVATE 1 #define MACVLAN_MODE_PRIVATE 1
#endif #endif
#ifndef MACVLAN_MODE_VEPA #ifndef MACVLAN_MODE_VEPA
# define MACVLAN_MODE_VEPA 2 #define MACVLAN_MODE_VEPA 2
#endif #endif
#ifndef MACVLAN_MODE_BRIDGE #ifndef MACVLAN_MODE_BRIDGE
# define MACVLAN_MODE_BRIDGE 4 #define MACVLAN_MODE_BRIDGE 4
#endif #endif
#ifndef MACVLAN_MODE_PASSTHRU #ifndef MACVLAN_MODE_PASSTHRU
# define MACVLAN_MODE_PASSTHRU 8 #define MACVLAN_MODE_PASSTHRU 8
#endif #endif
static int macvlan_mode(int *valuep, const char *value) static int macvlan_mode(int *valuep, const char *value)
...@@ -711,15 +728,15 @@ static int macvlan_mode(int *valuep, const char *value) ...@@ -711,15 +728,15 @@ static int macvlan_mode(int *valuep, const char *value)
char *name; char *name;
int mode; int mode;
} m[] = { } m[] = {
{ "private", MACVLAN_MODE_PRIVATE }, { "private", MACVLAN_MODE_PRIVATE },
{ "vepa", MACVLAN_MODE_VEPA }, { "vepa", MACVLAN_MODE_VEPA },
{ "bridge", MACVLAN_MODE_BRIDGE }, { "bridge", MACVLAN_MODE_BRIDGE },
{ "passthru", MACVLAN_MODE_PASSTHRU }, { "passthru", MACVLAN_MODE_PASSTHRU },
}; };
size_t i; size_t i;
for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) { for (i = 0; i < sizeof(m) / sizeof(m[0]); i++) {
if (strcmp(m[i].name, value)) if (strcmp(m[i].name, value))
continue; continue;
...@@ -738,13 +755,14 @@ static int rand_complete_hwaddr(char *hwaddr) ...@@ -738,13 +755,14 @@ static int rand_complete_hwaddr(char *hwaddr)
#ifndef HAVE_RAND_R #ifndef HAVE_RAND_R
randseed(true); randseed(true);
#else #else
unsigned int seed=randseed(false); unsigned int seed;
seed = randseed(false);
#endif #endif
while (*curs != '\0' && *curs != '\n') while (*curs != '\0' && *curs != '\n') {
{ if (*curs == 'x' || *curs == 'X') {
if ( *curs == 'x' || *curs == 'X' ) {
if (curs - hwaddr == 1) { if (curs - hwaddr == 1) {
//ensure address is unicast /* ensure address is unicast */
#ifdef HAVE_RAND_R #ifdef HAVE_RAND_R
*curs = hex[rand_r(&seed) & 0x0E]; *curs = hex[rand_r(&seed) & 0x0E];
} else { } else {
...@@ -762,7 +780,7 @@ static int rand_complete_hwaddr(char *hwaddr) ...@@ -762,7 +780,7 @@ static int rand_complete_hwaddr(char *hwaddr)
} }
static int set_config_network_flags(const char *key, const char *value, static int set_config_network_flags(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -775,24 +793,26 @@ static int set_config_network_flags(const char *key, const char *value, ...@@ -775,24 +793,26 @@ static int set_config_network_flags(const char *key, const char *value,
return 0; return 0;
} }
static int set_network_link(const char *key, const char *value, struct lxc_conf *lxc_conf) static int set_network_link(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
netdev = network_netdev(key, value, &lxc_conf->network); netdev = network_netdev(key, value, &lxc_conf->network);
if (!netdev) if (!netdev)
return -1; return -1;
return network_ifname(&netdev->link, value); return network_ifname(&netdev->link, value);
} }
static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf) static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf)
{ {
struct ifaddrs *ifaddr, *ifa; struct ifaddrs *ifaddr, *ifa;
int n;
int ret = 0;
const char *type_key = "lxc.network.type"; const char *type_key = "lxc.network.type";
const char *link_key = "lxc.network.link"; const char *link_key = "lxc.network.link";
const char *tmpvalue = "phys"; const char *tmpvalue = "phys";
int n, ret = 0;
if (getifaddrs(&ifaddr) == -1) { if (getifaddrs(&ifaddr) == -1) {
SYSERROR("Get network interfaces failed"); SYSERROR("Get network interfaces failed");
...@@ -805,10 +825,12 @@ static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf) ...@@ -805,10 +825,12 @@ static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf)
if (ifa->ifa_addr->sa_family != AF_PACKET) if (ifa->ifa_addr->sa_family != AF_PACKET)
continue; continue;
if (!strncmp(value, ifa->ifa_name, strlen(value)-1)) { if (!strncmp(value, ifa->ifa_name, strlen(value) - 1)) {
ret = set_config_network_type(type_key, tmpvalue, lxc_conf); ret = set_config_network_type(type_key, tmpvalue,
lxc_conf);
if (!ret) { if (!ret) {
ret = set_network_link(link_key, ifa->ifa_name, lxc_conf); ret = set_network_link(link_key, ifa->ifa_name,
lxc_conf);
if (ret) { if (ret) {
ERROR("failed to create matched ifnames"); ERROR("failed to create matched ifnames");
break; break;
...@@ -820,17 +842,17 @@ static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf) ...@@ -820,17 +842,17 @@ static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf)
} }
} }
freeifaddrs(ifaddr); /* free the dynamic memory */ freeifaddrs(ifaddr);
ifaddr = NULL; /* prevent use after free */ ifaddr = NULL;
return ret; return ret;
} }
static int set_config_network_link(const char *key, const char *value, static int set_config_network_link(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
struct lxc_list * it; struct lxc_list *it;
int ret = 0; int ret = 0;
netdev = network_netdev(key, value, &lxc_conf->network); netdev = network_netdev(key, value, &lxc_conf->network);
...@@ -838,17 +860,17 @@ static int set_config_network_link(const char *key, const char *value, ...@@ -838,17 +860,17 @@ static int set_config_network_link(const char *key, const char *value,
return -1; return -1;
if (value[strlen(value) - 1] == '+' && netdev->type == LXC_NET_PHYS) { if (value[strlen(value) - 1] == '+' && netdev->type == LXC_NET_PHYS) {
//get the last network list and remove it. /* Get the last network list and remove it. */
it = lxc_conf->network.prev; it = lxc_conf->network.prev;
if (((struct lxc_netdev *)(it->elem))->type != LXC_NET_PHYS) { if (((struct lxc_netdev *)(it->elem))->type != LXC_NET_PHYS) {
ERROR("lxc config cannot support string pattern matching for this link type"); ERROR("lxc config cannot support string pattern "
"matching for this link type");
return -1; return -1;
} }
lxc_list_del(it); lxc_list_del(it);
free(it); free(it);
ret = create_matched_ifnames(value, lxc_conf); ret = create_matched_ifnames(value, lxc_conf);
} else { } else {
ret = network_ifname(&netdev->link, value); ret = network_ifname(&netdev->link, value);
} }
...@@ -857,7 +879,7 @@ static int set_config_network_link(const char *key, const char *value, ...@@ -857,7 +879,7 @@ static int set_config_network_link(const char *key, const char *value,
} }
static int set_config_network_name(const char *key, const char *value, static int set_config_network_name(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -869,7 +891,7 @@ static int set_config_network_name(const char *key, const char *value, ...@@ -869,7 +891,7 @@ static int set_config_network_name(const char *key, const char *value,
} }
static int set_config_network_veth_pair(const char *key, const char *value, static int set_config_network_veth_pair(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -881,11 +903,12 @@ static int set_config_network_veth_pair(const char *key, const char *value, ...@@ -881,11 +903,12 @@ static int set_config_network_veth_pair(const char *key, const char *value,
ERROR("Invalid veth pair for a non-veth netdev"); ERROR("Invalid veth pair for a non-veth netdev");
return -1; return -1;
} }
return network_ifname(&netdev->priv.veth_attr.pair, value); return network_ifname(&netdev->priv.veth_attr.pair, value);
} }
static int set_config_network_macvlan_mode(const char *key, const char *value, static int set_config_network_macvlan_mode(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -897,17 +920,19 @@ static int set_config_network_macvlan_mode(const char *key, const char *value, ...@@ -897,17 +920,19 @@ static int set_config_network_macvlan_mode(const char *key, const char *value,
ERROR("Invalid macvlan.mode for a non-macvlan netdev"); ERROR("Invalid macvlan.mode for a non-macvlan netdev");
return -1; return -1;
} }
return macvlan_mode(&netdev->priv.macvlan_attr.mode, value); return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
} }
static int set_config_network_hwaddr(const char *key, const char *value, static int set_config_network_hwaddr(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
char *new_value;
char *new_value = strdup(value); new_value = strdup(value);
if (!new_value) { if (!new_value) {
SYSERROR("failed to strdup '%s': %m", value); SYSERROR("failed to strdup \"%s\"", value);
return -1; return -1;
} }
rand_complete_hwaddr(new_value); rand_complete_hwaddr(new_value);
...@@ -929,7 +954,7 @@ static int set_config_network_hwaddr(const char *key, const char *value, ...@@ -929,7 +954,7 @@ static int set_config_network_hwaddr(const char *key, const char *value,
} }
static int set_config_network_vlan_id(const char *key, const char *value, static int set_config_network_vlan_id(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -941,6 +966,7 @@ static int set_config_network_vlan_id(const char *key, const char *value, ...@@ -941,6 +966,7 @@ static int set_config_network_vlan_id(const char *key, const char *value,
ERROR("Invalid vlan.id for a non-macvlan netdev"); ERROR("Invalid vlan.id for a non-macvlan netdev");
return -1; return -1;
} }
if (get_u16(&netdev->priv.vlan_attr.vid, value, 0)) if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
return -1; return -1;
...@@ -948,7 +974,7 @@ static int set_config_network_vlan_id(const char *key, const char *value, ...@@ -948,7 +974,7 @@ static int set_config_network_vlan_id(const char *key, const char *value,
} }
static int set_config_network_mtu(const char *key, const char *value, static int set_config_network_mtu(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -960,12 +986,13 @@ static int set_config_network_mtu(const char *key, const char *value, ...@@ -960,12 +986,13 @@ static int set_config_network_mtu(const char *key, const char *value,
} }
static int set_config_network_ipv4(const char *key, const char *value, static int set_config_network_ipv4(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
struct lxc_inetdev *inetdev; struct lxc_inetdev *inetdev;
struct lxc_list *list; struct lxc_list *list;
char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL; char *cursor, *slash;
char *addr = NULL, *bcast = NULL, *prefix = NULL;
if (config_value_empty(value)) if (config_value_empty(value))
return lxc_clear_config_item(lxc_conf, key); return lxc_clear_config_item(lxc_conf, key);
...@@ -1027,7 +1054,7 @@ static int set_config_network_ipv4(const char *key, const char *value, ...@@ -1027,7 +1054,7 @@ static int set_config_network_ipv4(const char *key, const char *value,
return -1; return -1;
} }
/* no prefix specified, determine it from the network class */ /* No prefix specified, determine it from the network class. */
if (prefix) { if (prefix) {
if (lxc_safe_uint(prefix, &inetdev->prefix) < 0) if (lxc_safe_uint(prefix, &inetdev->prefix) < 0)
return -1; return -1;
...@@ -1035,13 +1062,13 @@ static int set_config_network_ipv4(const char *key, const char *value, ...@@ -1035,13 +1062,13 @@ static int set_config_network_ipv4(const char *key, const char *value,
inetdev->prefix = config_ip_prefix(&inetdev->addr); inetdev->prefix = config_ip_prefix(&inetdev->addr);
} }
/* if no broadcast address, let compute one from the /* If no broadcast address, let compute one from the
* prefix and address * prefix and address.
*/ */
if (!bcast) { if (!bcast) {
inetdev->bcast.s_addr = inetdev->addr.s_addr; inetdev->bcast.s_addr = inetdev->addr.s_addr;
inetdev->bcast.s_addr |= inetdev->bcast.s_addr |=
htonl(INADDR_BROADCAST >> inetdev->prefix); htonl(INADDR_BROADCAST >> inetdev->prefix);
} }
lxc_list_add_tail(&netdev->ipv4, list); lxc_list_add_tail(&netdev->ipv4, list);
...@@ -1051,7 +1078,7 @@ static int set_config_network_ipv4(const char *key, const char *value, ...@@ -1051,7 +1078,7 @@ static int set_config_network_ipv4(const char *key, const char *value,
} }
static int set_config_network_ipv4_gateway(const char *key, const char *value, static int set_config_network_ipv4_gateway(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -1089,13 +1116,12 @@ static int set_config_network_ipv4_gateway(const char *key, const char *value, ...@@ -1089,13 +1116,12 @@ static int set_config_network_ipv4_gateway(const char *key, const char *value,
} }
static int set_config_network_ipv6(const char *key, const char *value, static int set_config_network_ipv6(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
struct lxc_inet6dev *inet6dev; struct lxc_inet6dev *inet6dev;
struct lxc_list *list; struct lxc_list *list;
char *slash,*valdup; char *slash, *valdup, *netmask;
char *netmask;
if (config_value_empty(value)) if (config_value_empty(value))
return lxc_clear_config_item(lxc_conf, key); return lxc_clear_config_item(lxc_conf, key);
...@@ -1153,7 +1179,7 @@ static int set_config_network_ipv6(const char *key, const char *value, ...@@ -1153,7 +1179,7 @@ static int set_config_network_ipv6(const char *key, const char *value,
} }
static int set_config_network_ipv6_gateway(const char *key, const char *value, static int set_config_network_ipv6_gateway(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
...@@ -1191,25 +1217,25 @@ static int set_config_network_ipv6_gateway(const char *key, const char *value, ...@@ -1191,25 +1217,25 @@ static int set_config_network_ipv6_gateway(const char *key, const char *value,
} }
static int set_config_network_script_up(const char *key, const char *value, static int set_config_network_script_up(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
netdev = network_netdev(key, value, &lxc_conf->network); netdev = network_netdev(key, value, &lxc_conf->network);
if (!netdev) if (!netdev)
return -1; return -1;
return set_config_string_item(&netdev->upscript, value); return set_config_string_item(&netdev->upscript, value);
} }
static int set_config_network_script_down(const char *key, const char *value, static int set_config_network_script_down(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_netdev *netdev; struct lxc_netdev *netdev;
netdev = network_netdev(key, value, &lxc_conf->network); netdev = network_netdev(key, value, &lxc_conf->network);
if (!netdev) if (!netdev)
return -1; return -1;
return set_config_string_item(&netdev->downscript, value); return set_config_string_item(&netdev->downscript, value);
} }
...@@ -1223,25 +1249,26 @@ static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook) ...@@ -1223,25 +1249,26 @@ static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
free(hook); free(hook);
return -1; return -1;
} }
hooklist->elem = hook; hooklist->elem = hook;
lxc_list_add_tail(&lxc_conf->hooks[which], hooklist); lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
return 0; return 0;
} }
static int set_config_seccomp(const char *key, const char *value, static int set_config_seccomp(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_path_item(&lxc_conf->seccomp, value); return set_config_path_item(&lxc_conf->seccomp, value);
} }
static int set_config_init_cmd(const char *key, const char *value, static int set_config_init_cmd(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_path_item(&lxc_conf->init_cmd, value); return set_config_path_item(&lxc_conf->init_cmd, value);
} }
static int set_config_init_uid(const char *key, const char *value, static int set_config_init_uid(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
unsigned int init_uid; unsigned int init_uid;
...@@ -1260,7 +1287,7 @@ static int set_config_init_uid(const char *key, const char *value, ...@@ -1260,7 +1287,7 @@ static int set_config_init_uid(const char *key, const char *value,
} }
static int set_config_init_gid(const char *key, const char *value, static int set_config_init_gid(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
unsigned int init_gid; unsigned int init_gid;
...@@ -1295,6 +1322,7 @@ static int set_config_hooks(const char *key, const char *value, ...@@ -1295,6 +1322,7 @@ static int set_config_hooks(const char *key, const char *value,
SYSERROR("failed to dup string '%s'", value); SYSERROR("failed to dup string '%s'", value);
return -1; return -1;
} }
if (strcmp(key, "lxc.hook.pre-start") == 0) if (strcmp(key, "lxc.hook.pre-start") == 0)
return add_hook(lxc_conf, LXCHOOK_PRESTART, copy); return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
else if (strcmp(key, "lxc.hook.pre-mount") == 0) else if (strcmp(key, "lxc.hook.pre-mount") == 0)
...@@ -1313,13 +1341,14 @@ static int set_config_hooks(const char *key, const char *value, ...@@ -1313,13 +1341,14 @@ static int set_config_hooks(const char *key, const char *value,
return add_hook(lxc_conf, LXCHOOK_CLONE, copy); return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
else if (strcmp(key, "lxc.hook.destroy") == 0) else if (strcmp(key, "lxc.hook.destroy") == 0)
return add_hook(lxc_conf, LXCHOOK_DESTROY, copy); return add_hook(lxc_conf, LXCHOOK_DESTROY, copy);
SYSERROR("Unknown key: %s", key); SYSERROR("Unknown key: %s", key);
free(copy); free(copy);
return -1; return -1;
} }
static int set_config_personality(const char *key, const char *value, static int set_config_personality(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
signed long personality = lxc_config_parse_arch(value); signed long personality = lxc_config_parse_arch(value);
...@@ -1332,7 +1361,7 @@ static int set_config_personality(const char *key, const char *value, ...@@ -1332,7 +1361,7 @@ static int set_config_personality(const char *key, const char *value,
} }
static int set_config_pts(const char *key, const char *value, static int set_config_pts(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
/* Set config value to default. */ /* Set config value to default. */
if (config_value_empty(value)) { if (config_value_empty(value)) {
...@@ -1348,7 +1377,7 @@ static int set_config_pts(const char *key, const char *value, ...@@ -1348,7 +1377,7 @@ static int set_config_pts(const char *key, const char *value,
} }
static int set_config_start(const char *key, const char *value, static int set_config_start(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
bool is_empty; bool is_empty;
...@@ -1394,7 +1423,7 @@ static int set_config_start(const char *key, const char *value, ...@@ -1394,7 +1423,7 @@ static int set_config_start(const char *key, const char *value,
} }
static int set_config_monitor(const char *key, const char *value, static int set_config_monitor(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
/* Set config value to default. */ /* Set config value to default. */
if (config_value_empty(value)) { if (config_value_empty(value)) {
...@@ -1411,7 +1440,7 @@ static int set_config_monitor(const char *key, const char *value, ...@@ -1411,7 +1440,7 @@ static int set_config_monitor(const char *key, const char *value,
} }
static int set_config_group(const char *key, const char *value, static int set_config_group(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
char *groups, *groupptr, *sptr, *token; char *groups, *groupptr, *sptr, *token;
struct lxc_list *grouplist; struct lxc_list *grouplist;
...@@ -1426,9 +1455,10 @@ static int set_config_group(const char *key, const char *value, ...@@ -1426,9 +1455,10 @@ static int set_config_group(const char *key, const char *value,
return -1; return -1;
} }
/* in case several groups are specified in a single line /* In case several groups are specified in a single line
* split these groups in a single element for the list */ * split these groups in a single element for the list.
for (groupptr = groups;;groupptr = NULL) { */
for (groupptr = groups;; groupptr = NULL) {
token = strtok_r(groupptr, " \t", &sptr); token = strtok_r(groupptr, " \t", &sptr);
if (!token) { if (!token) {
ret = 0; ret = 0;
...@@ -1452,12 +1482,11 @@ static int set_config_group(const char *key, const char *value, ...@@ -1452,12 +1482,11 @@ static int set_config_group(const char *key, const char *value,
} }
free(groups); free(groups);
return ret; return ret;
} }
static int set_config_environment(const char *key, const char *value, static int set_config_environment(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_list *list_item = NULL; struct lxc_list *list_item = NULL;
...@@ -1466,25 +1495,24 @@ static int set_config_environment(const char *key, const char *value, ...@@ -1466,25 +1495,24 @@ static int set_config_environment(const char *key, const char *value,
list_item = malloc(sizeof(*list_item)); list_item = malloc(sizeof(*list_item));
if (!list_item) if (!list_item)
goto freak_out; goto on_error;
list_item->elem = strdup(value); list_item->elem = strdup(value);
if (!list_item->elem) if (!list_item->elem)
goto freak_out; goto on_error;
lxc_list_add_tail(&lxc_conf->environment, list_item); lxc_list_add_tail(&lxc_conf->environment, list_item);
return 0; return 0;
freak_out: on_error:
free(list_item); free(list_item);
return -1; return -1;
} }
static int set_config_tty(const char *key, const char *value, static int set_config_tty(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
/* Set config value to default. */ /* Set config value to default. */
if (config_value_empty(value)) { if (config_value_empty(value)) {
...@@ -1497,13 +1525,14 @@ static int set_config_tty(const char *key, const char *value, ...@@ -1497,13 +1525,14 @@ static int set_config_tty(const char *key, const char *value,
} }
static int set_config_ttydir(const char *key, const char *value, static int set_config_ttydir(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_string_item_max(&lxc_conf->ttydir, value, NAME_MAX+1); return set_config_string_item_max(&lxc_conf->ttydir, value,
NAME_MAX + 1);
} }
static int set_config_kmsg(const char *key, const char *value, static int set_config_kmsg(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
/* Set config value to default. */ /* Set config value to default. */
if (config_value_empty(value)) { if (config_value_empty(value)) {
...@@ -1522,13 +1551,13 @@ static int set_config_kmsg(const char *key, const char *value, ...@@ -1522,13 +1551,13 @@ static int set_config_kmsg(const char *key, const char *value,
} }
static int set_config_lsm_aa_profile(const char *key, const char *value, static int set_config_lsm_aa_profile(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_string_item(&lxc_conf->lsm_aa_profile, value); return set_config_string_item(&lxc_conf->lsm_aa_profile, value);
} }
static int set_config_lsm_aa_incomplete(const char *key, const char *value, static int set_config_lsm_aa_incomplete(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
/* Set config value to default. */ /* Set config value to default. */
if (config_value_empty(value)) { if (config_value_empty(value)) {
...@@ -1550,7 +1579,7 @@ static int set_config_lsm_aa_incomplete(const char *key, const char *value, ...@@ -1550,7 +1579,7 @@ static int set_config_lsm_aa_incomplete(const char *key, const char *value,
} }
static int set_config_lsm_se_context(const char *key, const char *value, static int set_config_lsm_se_context(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_string_item(&lxc_conf->lsm_se_context, value); return set_config_string_item(&lxc_conf->lsm_se_context, value);
} }
...@@ -1567,7 +1596,8 @@ static int set_config_logfile(const char *key, const char *value, ...@@ -1567,7 +1596,8 @@ static int set_config_logfile(const char *key, const char *value,
} }
/* Store these values in the lxc_conf, and then try to set for actual /* Store these values in the lxc_conf, and then try to set for actual
* current logging. */ * current logging.
*/
ret = set_config_path_item(&c->logfile, value); ret = set_config_path_item(&c->logfile, value);
if (ret == 0) if (ret == 0)
ret = lxc_log_set_file(&c->logfd, c->logfile); ret = lxc_log_set_file(&c->logfd, c->logfile);
...@@ -1575,7 +1605,7 @@ static int set_config_logfile(const char *key, const char *value, ...@@ -1575,7 +1605,7 @@ static int set_config_logfile(const char *key, const char *value,
} }
static int set_config_loglevel(const char *key, const char *value, static int set_config_loglevel(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
int newlevel; int newlevel;
...@@ -1593,7 +1623,7 @@ static int set_config_loglevel(const char *key, const char *value, ...@@ -1593,7 +1623,7 @@ static int set_config_loglevel(const char *key, const char *value,
newlevel = lxc_log_priority_to_int(value); newlevel = lxc_log_priority_to_int(value);
} }
/* store these values in the lxc_conf, and then try to set for actual /* Store these values in the lxc_conf, and then try to set for actual
* current logging. * current logging.
*/ */
lxc_conf->loglevel = newlevel; lxc_conf->loglevel = newlevel;
...@@ -1601,7 +1631,7 @@ static int set_config_loglevel(const char *key, const char *value, ...@@ -1601,7 +1631,7 @@ static int set_config_loglevel(const char *key, const char *value,
} }
static int set_config_autodev(const char *key, const char *value, static int set_config_autodev(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
/* Set config value to default. */ /* Set config value to default. */
if (config_value_empty(value)) { if (config_value_empty(value)) {
...@@ -1633,23 +1663,26 @@ static int sig_num(const char *sig) ...@@ -1633,23 +1663,26 @@ static int sig_num(const char *sig)
static int rt_sig_num(const char *signame) static int rt_sig_num(const char *signame)
{ {
int sig_n = 0; int rtmax = 0, sig_n = 0;
int rtmax = 0;
if (strncasecmp(signame, "max-", 4) == 0) { if (strncasecmp(signame, "max-", 4) == 0) {
rtmax = 1; rtmax = 1;
} }
signame += 4; signame += 4;
if (!isdigit(*signame)) if (!isdigit(*signame))
return -1; return -1;
sig_n = sig_num(signame); sig_n = sig_num(signame);
sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n; sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n;
if (sig_n > SIGRTMAX || sig_n < SIGRTMIN) if (sig_n > SIGRTMAX || sig_n < SIGRTMIN)
return -1; return -1;
return sig_n; return sig_n;
} }
static int sig_parse(const char *signame) { static int sig_parse(const char *signame)
{
size_t n; size_t n;
if (isdigit(*signame)) { if (isdigit(*signame)) {
...@@ -1659,15 +1692,16 @@ static int sig_parse(const char *signame) { ...@@ -1659,15 +1692,16 @@ static int sig_parse(const char *signame) {
if (strncasecmp(signame, "rt", 2) == 0) if (strncasecmp(signame, "rt", 2) == 0)
return rt_sig_num(signame + 2); return rt_sig_num(signame + 2);
for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) { for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
if (strcasecmp (signames[n].name, signame) == 0) if (strcasecmp(signames[n].name, signame) == 0)
return signames[n].num; return signames[n].num;
} }
} }
return -1; return -1;
} }
static int set_config_haltsignal(const char *key, const char *value, static int set_config_haltsignal(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
int sig_n; int sig_n;
...@@ -1688,7 +1722,7 @@ static int set_config_haltsignal(const char *key, const char *value, ...@@ -1688,7 +1722,7 @@ static int set_config_haltsignal(const char *key, const char *value,
} }
static int set_config_rebootsignal(const char *key, const char *value, static int set_config_rebootsignal(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
int sig_n; int sig_n;
...@@ -1708,7 +1742,7 @@ static int set_config_rebootsignal(const char *key, const char *value, ...@@ -1708,7 +1742,7 @@ static int set_config_rebootsignal(const char *key, const char *value,
} }
static int set_config_stopsignal(const char *key, const char *value, static int set_config_stopsignal(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
int sig_n; int sig_n;
...@@ -1728,10 +1762,10 @@ static int set_config_stopsignal(const char *key, const char *value, ...@@ -1728,10 +1762,10 @@ static int set_config_stopsignal(const char *key, const char *value,
} }
static int set_config_cgroup(const char *key, const char *value, static int set_config_cgroup(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
char *token = "lxc.cgroup.";
char *subkey; char *subkey;
char *token = "lxc.cgroup.";
struct lxc_list *cglist = NULL; struct lxc_list *cglist = NULL;
struct lxc_cgroup *cgelem = NULL; struct lxc_cgroup *cgelem = NULL;
...@@ -1739,7 +1773,6 @@ static int set_config_cgroup(const char *key, const char *value, ...@@ -1739,7 +1773,6 @@ static int set_config_cgroup(const char *key, const char *value,
return lxc_clear_cgroups(lxc_conf, key); return lxc_clear_cgroups(lxc_conf, key);
subkey = strstr(key, token); subkey = strstr(key, token);
if (!subkey) if (!subkey)
return -1; return -1;
...@@ -1786,12 +1819,13 @@ out: ...@@ -1786,12 +1819,13 @@ out:
return -1; return -1;
} }
static bool parse_limit_value(const char **value, unsigned long *res) { static bool parse_limit_value(const char **value, unsigned long *res)
{
char *endptr = NULL; char *endptr = NULL;
if (strncmp(*value, "unlimited", sizeof("unlimited")-1) == 0) { if (strncmp(*value, "unlimited", sizeof("unlimited") - 1) == 0) {
*res = RLIM_INFINITY; *res = RLIM_INFINITY;
*value += sizeof("unlimited")-1; *value += sizeof("unlimited") - 1;
return true; return true;
} }
...@@ -1805,21 +1839,21 @@ static bool parse_limit_value(const char **value, unsigned long *res) { ...@@ -1805,21 +1839,21 @@ static bool parse_limit_value(const char **value, unsigned long *res) {
} }
static int set_config_limit(const char *key, const char *value, static int set_config_limit(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct lxc_list *limlist = NULL;
struct lxc_limit *limelem = NULL;
struct lxc_list *iter; struct lxc_list *iter;
struct rlimit limit; struct rlimit limit;
unsigned long limit_value; unsigned long limit_value;
struct lxc_list *limlist = NULL;
struct lxc_limit *limelem = NULL;
if (config_value_empty(value)) if (config_value_empty(value))
return lxc_clear_limits(lxc_conf, key); return lxc_clear_limits(lxc_conf, key);
if (strncmp(key, "lxc.limit.", sizeof("lxc.limit.")-1) != 0) if (strncmp(key, "lxc.limit.", sizeof("lxc.limit.") - 1) != 0)
return -1; return -1;
key += sizeof("lxc.limit.")-1; key += sizeof("lxc.limit.") - 1;
/* soft limit comes first in the value */ /* soft limit comes first in the value */
if (!parse_limit_value(&value, &limit_value)) if (!parse_limit_value(&value, &limit_value))
...@@ -1829,10 +1863,12 @@ static int set_config_limit(const char *key, const char *value, ...@@ -1829,10 +1863,12 @@ static int set_config_limit(const char *key, const char *value,
/* skip spaces and a colon */ /* skip spaces and a colon */
while (isspace(*value)) while (isspace(*value))
++value; ++value;
if (*value == ':') if (*value == ':')
++value; ++value;
else if (*value) /* any other character is an error here */ else if (*value) /* any other character is an error here */
return -1; return -1;
while (isspace(*value)) while (isspace(*value))
++value; ++value;
...@@ -1841,9 +1877,11 @@ static int set_config_limit(const char *key, const char *value, ...@@ -1841,9 +1877,11 @@ static int set_config_limit(const char *key, const char *value,
if (!parse_limit_value(&value, &limit_value)) if (!parse_limit_value(&value, &limit_value))
return -1; return -1;
limit.rlim_max = limit_value; limit.rlim_max = limit_value;
/* check for trailing garbage */ /* check for trailing garbage */
while (isspace(*value)) while (isspace(*value))
++value; ++value;
if (*value) if (*value)
return -1; return -1;
} else { } else {
...@@ -1852,7 +1890,8 @@ static int set_config_limit(const char *key, const char *value, ...@@ -1852,7 +1890,8 @@ static int set_config_limit(const char *key, const char *value,
} }
/* find existing list element */ /* find existing list element */
lxc_list_for_each(iter, &lxc_conf->limits) { lxc_list_for_each(iter, &lxc_conf->limits)
{
limelem = iter->elem; limelem = iter->elem;
if (!strcmp(key, limelem->resource)) { if (!strcmp(key, limelem->resource)) {
limelem->limit = limit; limelem->limit = limit;
...@@ -1917,7 +1956,7 @@ static int set_config_idmaps(const char *key, const char *value, ...@@ -1917,7 +1956,7 @@ static int set_config_idmaps(const char *key, const char *value,
if (!dup) if (!dup)
goto on_error; goto on_error;
/* A prototypical idmap entry would be: "0 1000 1000000 65536" */ /* A prototypical idmap entry would be: "u 1000 1000000 65536" */
/* align */ /* align */
slide = window = dup; slide = window = dup;
...@@ -2041,7 +2080,7 @@ on_error: ...@@ -2041,7 +2080,7 @@ on_error:
} }
static int set_config_fstab(const char *key, const char *value, static int set_config_fstab(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
if (config_value_empty(value)) { if (config_value_empty(value)) {
lxc_clear_config_item(lxc_conf, key); lxc_clear_config_item(lxc_conf, key);
...@@ -2052,33 +2091,37 @@ static int set_config_fstab(const char *key, const char *value, ...@@ -2052,33 +2091,37 @@ static int set_config_fstab(const char *key, const char *value,
} }
static int set_config_mount_auto(const char *key, const char *value, static int set_config_mount_auto(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
char *autos, *autoptr, *sptr, *token; char *autos, *autoptr, *sptr, *token;
static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = {
{ "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
{ "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
{ "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
{ "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
{ "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
{ "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
{ "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
{ "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
{ "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
{ "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
{ "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
{ "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
{ "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
{ "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
{ "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
/* NB: For adding anything that is just a single on/off, but has
* no options: keep mask and flag identical and just define the
* enum value as an unused bit so far
*/
{ NULL, 0 }
};
int i; int i;
int ret = -1; int ret = -1;
static struct {
const char *token;
int mask;
int flag;
} allowed_auto_mounts[] = {
{ "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
{ "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
{ "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
{ "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
{ "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
{ "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
{ "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
{ "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
{ "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
{ "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
{ "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
{ "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
{ "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
{ "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
{ "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
/* NB: For adding anything that is just a single on/off, but has
* no options: keep mask and flag identical and just define the
* enum value as an unused bit so far
*/
{ NULL, 0, 0 }
};
if (config_value_empty(value)) { if (config_value_empty(value)) {
lxc_conf->auto_mounts = 0; lxc_conf->auto_mounts = 0;
...@@ -2091,7 +2134,7 @@ static int set_config_mount_auto(const char *key, const char *value, ...@@ -2091,7 +2134,7 @@ static int set_config_mount_auto(const char *key, const char *value,
return -1; return -1;
} }
for (autoptr = autos; ; autoptr = NULL) { for (autoptr = autos;; autoptr = NULL) {
token = strtok_r(autoptr, " \t", &sptr); token = strtok_r(autoptr, " \t", &sptr);
if (!token) { if (!token) {
ret = 0; ret = 0;
...@@ -2113,12 +2156,11 @@ static int set_config_mount_auto(const char *key, const char *value, ...@@ -2113,12 +2156,11 @@ static int set_config_mount_auto(const char *key, const char *value,
} }
free(autos); free(autos);
return ret; return ret;
} }
static int set_config_mount(const char *key, const char *value, static int set_config_mount(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
char *mntelem; char *mntelem;
struct lxc_list *mntlist; struct lxc_list *mntlist;
...@@ -2143,7 +2185,7 @@ static int set_config_mount(const char *key, const char *value, ...@@ -2143,7 +2185,7 @@ static int set_config_mount(const char *key, const char *value,
} }
static int set_config_cap_keep(const char *key, const char *value, static int set_config_cap_keep(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
char *keepcaps, *keepptr, *sptr, *token; char *keepcaps, *keepptr, *sptr, *token;
struct lxc_list *keeplist; struct lxc_list *keeplist;
...@@ -2158,9 +2200,10 @@ static int set_config_cap_keep(const char *key, const char *value, ...@@ -2158,9 +2200,10 @@ static int set_config_cap_keep(const char *key, const char *value,
return -1; return -1;
} }
/* in case several capability keep is specified in a single line /* In case several capability keep is specified in a single line
* split these caps in a single element for the list */ * split these caps in a single element for the list.
for (keepptr = keepcaps;;keepptr = NULL) { */
for (keepptr = keepcaps;; keepptr = NULL) {
token = strtok_r(keepptr, " \t", &sptr); token = strtok_r(keepptr, " \t", &sptr);
if (!token) { if (!token) {
ret = 0; ret = 0;
...@@ -2192,7 +2235,7 @@ static int set_config_cap_keep(const char *key, const char *value, ...@@ -2192,7 +2235,7 @@ static int set_config_cap_keep(const char *key, const char *value,
} }
static int set_config_cap_drop(const char *key, const char *value, static int set_config_cap_drop(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
char *dropcaps, *dropptr, *sptr, *token; char *dropcaps, *dropptr, *sptr, *token;
struct lxc_list *droplist; struct lxc_list *droplist;
...@@ -2207,9 +2250,10 @@ static int set_config_cap_drop(const char *key, const char *value, ...@@ -2207,9 +2250,10 @@ static int set_config_cap_drop(const char *key, const char *value,
return -1; return -1;
} }
/* in case several capability drop is specified in a single line /* In case several capability drop is specified in a single line
* split these caps in a single element for the list */ * split these caps in a single element for the list.
for (dropptr = dropcaps;;dropptr = NULL) { */
for (dropptr = dropcaps;; dropptr = NULL) {
token = strtok_r(dropptr, " \t", &sptr); token = strtok_r(dropptr, " \t", &sptr);
if (!token) { if (!token) {
ret = 0; ret = 0;
...@@ -2238,23 +2282,23 @@ static int set_config_cap_drop(const char *key, const char *value, ...@@ -2238,23 +2282,23 @@ static int set_config_cap_drop(const char *key, const char *value,
} }
static int set_config_console(const char *key, const char *value, static int set_config_console(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_path_item(&lxc_conf->console.path, value); return set_config_path_item(&lxc_conf->console.path, value);
} }
static int set_config_console_logfile(const char *key, const char *value, static int set_config_console_logfile(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_path_item(&lxc_conf->console.log_path, value); return set_config_path_item(&lxc_conf->console.log_path, value);
} }
/* /*
* If we find a lxc.network.hwaddr in the original config file, * If we find a lxc.network.hwaddr in the original config file, we expand it in
* we expand it in the unexpanded_config, so that after a save_config * the unexpanded_config, so that after a save_config we store the hwaddr for
* we store the hwaddr for re-use. * re-use.
* This is only called when reading the config file, not when executing * This is only called when reading the config file, not when executing a
* a lxc.include. * lxc.include.
* 'x' and 'X' are substituted in-place. * 'x' and 'X' are substituted in-place.
*/ */
static void update_hwaddr(const char *line) static void update_hwaddr(const char *line)
...@@ -2264,14 +2308,19 @@ static void update_hwaddr(const char *line) ...@@ -2264,14 +2308,19 @@ static void update_hwaddr(const char *line)
line += lxc_char_left_gc(line, strlen(line)); line += lxc_char_left_gc(line, strlen(line));
if (line[0] == '#') if (line[0] == '#')
return; return;
if (strncmp(line, "lxc.network.hwaddr", 18) != 0) if (strncmp(line, "lxc.network.hwaddr", 18) != 0)
return; return;
/* Let config_network_hwaddr raise the error. */
p = strchr(line, '='); p = strchr(line, '=');
if (!p) if (!p)
return; // let config_network_hwaddr raise the error return;
p++; p++;
while (isblank(*p)) while (isblank(*p))
p++; p++;
if (!*p) if (!*p)
return; return;
...@@ -2285,9 +2334,11 @@ int append_unexp_config_line(const char *line, struct lxc_conf *conf) ...@@ -2285,9 +2334,11 @@ int append_unexp_config_line(const char *line, struct lxc_conf *conf)
update_hwaddr(line); update_hwaddr(line);
while (conf->unexpanded_alloced <= len + linelen + 2) { while (conf->unexpanded_alloced <= len + linelen + 2) {
char *tmp = realloc(conf->unexpanded_config, conf->unexpanded_alloced + 1024); char *tmp = realloc(conf->unexpanded_config,
conf->unexpanded_alloced + 1024);
if (!tmp) if (!tmp)
return -1; return -1;
if (!conf->unexpanded_config) if (!conf->unexpanded_config)
*tmp = '\0'; *tmp = '\0';
conf->unexpanded_config = tmp; conf->unexpanded_config = tmp;
...@@ -2295,7 +2346,7 @@ int append_unexp_config_line(const char *line, struct lxc_conf *conf) ...@@ -2295,7 +2346,7 @@ int append_unexp_config_line(const char *line, struct lxc_conf *conf)
} }
strcat(conf->unexpanded_config, line); strcat(conf->unexpanded_config, line);
conf->unexpanded_len += linelen; conf->unexpanded_len += linelen;
if (line[linelen-1] != '\n') { if (line[linelen - 1] != '\n') {
strcat(conf->unexpanded_config, "\n"); strcat(conf->unexpanded_config, "\n");
conf->unexpanded_len++; conf->unexpanded_len++;
} }
...@@ -2307,7 +2358,8 @@ static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf) ...@@ -2307,7 +2358,8 @@ static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
struct dirent *direntp; struct dirent *direntp;
DIR *dir; DIR *dir;
char path[MAXPATHLEN]; char path[MAXPATHLEN];
int ret = -1, len; int len;
int ret = -1;
dir = opendir(dirp); dir = opendir(dirp);
if (!dir) { if (!dir) {
...@@ -2328,7 +2380,7 @@ static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf) ...@@ -2328,7 +2380,7 @@ static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
continue; continue;
len = strlen(fnam); len = strlen(fnam);
if (len < 6 || strncmp(fnam+len-5, ".conf", 5) != 0) if (len < 6 || strncmp(fnam + len - 5, ".conf", 5) != 0)
continue; continue;
len = snprintf(path, MAXPATHLEN, "%s/%s", dirp, fnam); len = snprintf(path, MAXPATHLEN, "%s/%s", dirp, fnam);
if (len < 0 || len >= MAXPATHLEN) { if (len < 0 || len >= MAXPATHLEN) {
...@@ -2351,7 +2403,7 @@ out: ...@@ -2351,7 +2403,7 @@ out:
} }
static int set_config_includefile(const char *key, const char *value, static int set_config_includefile(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
/* Set config value to default. */ /* Set config value to default. */
if (config_value_empty(value)) { if (config_value_empty(value)) {
...@@ -2367,25 +2419,25 @@ static int set_config_includefile(const char *key, const char *value, ...@@ -2367,25 +2419,25 @@ static int set_config_includefile(const char *key, const char *value,
} }
static int set_config_rootfs(const char *key, const char *value, static int set_config_rootfs(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_path_item(&lxc_conf->rootfs.path, value); return set_config_path_item(&lxc_conf->rootfs.path, value);
} }
static int set_config_rootfs_mount(const char *key, const char *value, static int set_config_rootfs_mount(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_path_item(&lxc_conf->rootfs.mount, value); return set_config_path_item(&lxc_conf->rootfs.mount, value);
} }
static int set_config_rootfs_options(const char *key, const char *value, static int set_config_rootfs_options(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
return set_config_string_item(&lxc_conf->rootfs.options, value); return set_config_string_item(&lxc_conf->rootfs.options, value);
} }
static int set_config_rootfs_backend(const char *key, const char *value, static int set_config_rootfs_backend(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
if (config_value_empty(value)) { if (config_value_empty(value)) {
free(lxc_conf->rootfs.bdev_type); free(lxc_conf->rootfs.bdev_type);
...@@ -2402,14 +2454,14 @@ static int set_config_rootfs_backend(const char *key, const char *value, ...@@ -2402,14 +2454,14 @@ static int set_config_rootfs_backend(const char *key, const char *value,
} }
static int set_config_pivotdir(const char *key, const char *value, static int set_config_pivotdir(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
WARN("lxc.pivotdir is ignored. It will soon become an error."); WARN("lxc.pivotdir is ignored. It will soon become an error.");
return 0; return 0;
} }
static int set_config_utsname(const char *key, const char *value, static int set_config_utsname(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
struct utsname *utsname; struct utsname *utsname;
...@@ -2445,12 +2497,9 @@ struct parse_line_conf { ...@@ -2445,12 +2497,9 @@ struct parse_line_conf {
static int parse_line(char *buffer, void *data) static int parse_line(char *buffer, void *data)
{ {
struct lxc_config_t *config; struct lxc_config_t *config;
char *line, *linep; char *dot, *key, *line, *linep, *value;
char *dot;
char *key;
char *value;
int ret = 0;
struct parse_line_conf *plc = data; struct parse_line_conf *plc = data;
int ret = 0;
if (lxc_is_line_empty(buffer)) if (lxc_is_line_empty(buffer))
return 0; return 0;
...@@ -2498,8 +2547,8 @@ static int parse_line(char *buffer, void *data) ...@@ -2498,8 +2547,8 @@ static int parse_line(char *buffer, void *data)
if (*value == '\'' || *value == '\"') { if (*value == '\'' || *value == '\"') {
size_t len = strlen(value); size_t len = strlen(value);
if (len > 1 && value[len-1] == *value) { if (len > 1 && value[len - 1] == *value) {
value[len-1] = '\0'; value[len - 1] = '\0';
value++; value++;
} }
} }
...@@ -2534,18 +2583,18 @@ int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include) ...@@ -2534,18 +2583,18 @@ int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
c.conf = conf; c.conf = conf;
c.from_include = from_include; c.from_include = from_include;
if( access(file, R_OK) == -1 ) { if (access(file, R_OK) == -1) {
return -1; return -1;
} }
/* Catch only the top level config file name in the structure */ /* Catch only the top level config file name in the structure */
if(!conf->rcfile) if (!conf->rcfile)
conf->rcfile = strdup(file); conf->rcfile = strdup(file);
return lxc_file_for_each_line(file, parse_line, &c); return lxc_file_for_each_line(file, parse_line, &c);
} }
int lxc_config_define_add(struct lxc_list *defines, char* arg) int lxc_config_define_add(struct lxc_list *defines, char *arg)
{ {
struct lxc_list *dent; struct lxc_list *dent;
...@@ -2560,7 +2609,7 @@ int lxc_config_define_add(struct lxc_list *defines, char* arg) ...@@ -2560,7 +2609,7 @@ int lxc_config_define_add(struct lxc_list *defines, char* arg)
int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf) int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
{ {
struct lxc_list *it,*next; struct lxc_list *it, *next;
int ret = 0; int ret = 0;
lxc_list_for_each(it, defines) { lxc_list_for_each(it, defines) {
...@@ -2579,48 +2628,47 @@ int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf) ...@@ -2579,48 +2628,47 @@ int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
signed long lxc_config_parse_arch(const char *arch) signed long lxc_config_parse_arch(const char *arch)
{ {
#if HAVE_SYS_PERSONALITY_H #if HAVE_SYS_PERSONALITY_H
size_t i;
struct per_name { struct per_name {
char *name; char *name;
unsigned long per; unsigned long per;
} pername[] = { } pername[] = {
{ "x86", PER_LINUX32 }, { "x86", PER_LINUX32 },
{ "linux32", PER_LINUX32 }, { "linux32", PER_LINUX32 },
{ "i386", PER_LINUX32 }, { "i386", PER_LINUX32 },
{ "i486", PER_LINUX32 }, { "i486", PER_LINUX32 },
{ "i586", PER_LINUX32 }, { "i586", PER_LINUX32 },
{ "i686", PER_LINUX32 }, { "i686", PER_LINUX32 },
{ "athlon", PER_LINUX32 }, { "athlon", PER_LINUX32 },
{ "mips", PER_LINUX32 }, { "mips", PER_LINUX32 },
{ "mipsel", PER_LINUX32 }, { "mipsel", PER_LINUX32 },
{ "ppc", PER_LINUX32 }, { "ppc", PER_LINUX32 },
{ "arm", PER_LINUX32 }, { "arm", PER_LINUX32 },
{ "armv7l", PER_LINUX32 }, { "armv7l", PER_LINUX32 },
{ "armhf", PER_LINUX32 }, { "armhf", PER_LINUX32 },
{ "armel", PER_LINUX32 }, { "armel", PER_LINUX32 },
{ "powerpc", PER_LINUX32 }, { "powerpc", PER_LINUX32 },
{ "linux64", PER_LINUX }, { "linux64", PER_LINUX },
{ "x86_64", PER_LINUX }, { "x86_64", PER_LINUX },
{ "amd64", PER_LINUX }, { "amd64", PER_LINUX },
{ "mips64", PER_LINUX }, { "mips64", PER_LINUX },
{ "mips64el", PER_LINUX }, { "mips64el", PER_LINUX },
{ "ppc64", PER_LINUX }, { "ppc64", PER_LINUX },
{ "ppc64le", PER_LINUX }, { "ppc64le", PER_LINUX },
{ "ppc64el", PER_LINUX }, { "ppc64el", PER_LINUX },
{ "powerpc64", PER_LINUX }, { "powerpc64", PER_LINUX },
{ "s390x", PER_LINUX }, { "s390x", PER_LINUX },
{ "aarch64", PER_LINUX }, { "aarch64", PER_LINUX },
{ "arm64", PER_LINUX }, { "arm64", PER_LINUX },
}; };
size_t len = sizeof(pername) / sizeof(pername[0]); size_t len = sizeof(pername) / sizeof(pername[0]);
size_t i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (!strcmp(pername[i].name, arch)) if (!strcmp(pername[i].name, arch))
return pername[i].per; return pername[i].per;
} }
#endif #endif
return -1; return -1;
} }
...@@ -2629,16 +2677,20 @@ int lxc_fill_elevated_privileges(char *flaglist, int *flags) ...@@ -2629,16 +2677,20 @@ int lxc_fill_elevated_privileges(char *flaglist, int *flags)
{ {
char *token, *saveptr = NULL; char *token, *saveptr = NULL;
int i, aflag; int i, aflag;
struct { const char *token; int flag; } all_privs[] = { struct {
{ "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP }, const char *token;
{ "CAP", LXC_ATTACH_DROP_CAPABILITIES }, int flag;
{ "LSM", LXC_ATTACH_LSM_EXEC }, } all_privs[] = {
{ NULL, 0 } { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
{ "CAP", LXC_ATTACH_DROP_CAPABILITIES },
{ "LSM", LXC_ATTACH_LSM_EXEC },
{ NULL, 0 }
}; };
if (!flaglist) { if (!flaglist) {
/* for the sake of backward compatibility, drop all privileges /* For the sake of backward compatibility, drop all privileges
if none is specified */ * if none is specified.
*/
for (i = 0; all_privs[i].token; i++) { for (i = 0; all_privs[i].token; i++) {
*flags |= all_privs[i].flag; *flags |= all_privs[i].flag;
} }
...@@ -2659,6 +2711,7 @@ int lxc_fill_elevated_privileges(char *flaglist, int *flags) ...@@ -2659,6 +2711,7 @@ int lxc_fill_elevated_privileges(char *flaglist, int *flags)
token = strtok_r(NULL, "|", &saveptr); token = strtok_r(NULL, "|", &saveptr);
} }
return 0; return 0;
} }
...@@ -2683,19 +2736,19 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key) ...@@ -2683,19 +2736,19 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key)
} else if (strncmp(key, "lxc.network.", 12) == 0) { } else if (strncmp(key, "lxc.network.", 12) == 0) {
ret = lxc_clear_nic(c, key + 12); ret = lxc_clear_nic(c, key + 12);
} else if (strcmp(key, "lxc.cap.drop") == 0) { } else if (strcmp(key, "lxc.cap.drop") == 0) {
ret = lxc_clear_config_caps(c); ret = lxc_clear_config_caps(c);
} else if (strcmp(key, "lxc.cap.keep") == 0) { } else if (strcmp(key, "lxc.cap.keep") == 0) {
ret = lxc_clear_config_keepcaps(c); ret = lxc_clear_config_keepcaps(c);
} else if (strncmp(key, "lxc.cgroup", 10) == 0) { } else if (strncmp(key, "lxc.cgroup", 10) == 0) {
ret = lxc_clear_cgroups(c, key); ret = lxc_clear_cgroups(c, key);
} else if (strcmp(key, "lxc.mount.entry") == 0) { } else if (strcmp(key, "lxc.mount.entry") == 0) {
ret = lxc_clear_mount_entries(c); ret = lxc_clear_mount_entries(c);
} else if (strcmp(key, "lxc.mount.auto") == 0) { } else if (strcmp(key, "lxc.mount.auto") == 0) {
ret = lxc_clear_automounts(c); ret = lxc_clear_automounts(c);
} else if (strncmp(key, "lxc.hook", 8) == 0) { } else if (strncmp(key, "lxc.hook", 8) == 0) {
...@@ -2837,22 +2890,22 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key) ...@@ -2837,22 +2890,22 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key)
return ret; return ret;
} }
/* /* Write out a configuration file. */
* writing out a confile.
*/
void write_config(FILE *fout, struct lxc_conf *c) void write_config(FILE *fout, struct lxc_conf *c)
{ {
size_t len = c->unexpanded_len;
int ret; int ret;
size_t len = c->unexpanded_len;
if (!len) if (!len)
return; return;
ret = fwrite(c->unexpanded_config, 1, len, fout); ret = fwrite(c->unexpanded_config, 1, len, fout);
if (ret != len) if (ret != len)
SYSERROR("Error writing configuration file"); SYSERROR("Error writing configuration file");
} }
bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, const char *v) bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key,
const char *v)
{ {
int ret; int ret;
size_t len; size_t len;
...@@ -2875,12 +2928,15 @@ bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, const c ...@@ -2875,12 +2928,15 @@ bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, const c
return true; return true;
} }
void clear_unexp_config_line(struct lxc_conf *conf, const char *key, bool rm_subkeys) void clear_unexp_config_line(struct lxc_conf *conf, const char *key,
bool rm_subkeys)
{ {
char *lstart = conf->unexpanded_config, *lend; char *lend;
char *lstart = conf->unexpanded_config;
if (!conf->unexpanded_config) if (!conf->unexpanded_config)
return; return;
while (*lstart) { while (*lstart) {
lend = strchr(lstart, '\n'); lend = strchr(lstart, '\n');
char v; char v;
...@@ -2904,7 +2960,7 @@ void clear_unexp_config_line(struct lxc_conf *conf, const char *key, bool rm_sub ...@@ -2904,7 +2960,7 @@ void clear_unexp_config_line(struct lxc_conf *conf, const char *key, bool rm_sub
*lstart = '\0'; *lstart = '\0';
return; return;
} }
memmove(lstart, lend, strlen(lend)+1); memmove(lstart, lend, strlen(lend) + 1);
} }
} }
...@@ -2912,58 +2968,69 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, ...@@ -2912,58 +2968,69 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
const char *newpath, const char *oldname, const char *newpath, const char *oldname,
const char *newname, const char *ovldir) const char *newname, const char *ovldir)
{ {
const char *key = "lxc.mount.entry";
int ret; int ret;
char *lend, *newdir, *olddir, *p, *q;
size_t newdirlen, olddirlen;
char *lstart = conf->unexpanded_config; char *lstart = conf->unexpanded_config;
char *lend; const char *key = "lxc.mount.entry";
char *p;
char *q;
size_t newdirlen = strlen(ovldir) + strlen(newpath) + strlen(newname) + 2;
size_t olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 2;
char *olddir = alloca(olddirlen + 1);
char *newdir = alloca(newdirlen + 1);
ret = snprintf(olddir, olddirlen + 1, "%s=%s/%s", ovldir, oldpath, oldname); olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 2;
olddir = alloca(olddirlen + 1);
ret = snprintf(olddir, olddirlen + 1, "%s=%s/%s", ovldir, oldpath,
oldname);
if (ret < 0 || ret >= olddirlen + 1) { if (ret < 0 || ret >= olddirlen + 1) {
ERROR("Bug in %s", __func__); ERROR("failed to create string");
return false; return false;
} }
ret = snprintf(newdir, newdirlen + 1, "%s=%s/%s", ovldir, newpath, newname);
newdirlen = strlen(ovldir) + strlen(newpath) + strlen(newname) + 2;
newdir = alloca(newdirlen + 1);
ret = snprintf(newdir, newdirlen + 1, "%s=%s/%s", ovldir, newpath,
newname);
if (ret < 0 || ret >= newdirlen + 1) { if (ret < 0 || ret >= newdirlen + 1) {
ERROR("Bug in %s", __func__); ERROR("failed to create string");
return false; return false;
} }
if (!conf->unexpanded_config) if (!conf->unexpanded_config)
return true; return true;
while (*lstart) { while (*lstart) {
lend = strchr(lstart, '\n'); lend = strchr(lstart, '\n');
if (!lend) if (!lend)
lend = lstart + strlen(lstart); lend = lstart + strlen(lstart);
else else
lend++; lend++;
if (strncmp(lstart, key, strlen(key)) != 0) if (strncmp(lstart, key, strlen(key)) != 0)
goto next; goto next;
p = strchr(lstart + strlen(key), '='); p = strchr(lstart + strlen(key), '=');
if (!p) if (!p)
goto next; goto next;
p++; p++;
while (isblank(*p)) while (isblank(*p))
p++; p++;
if (p >= lend) if (p >= lend)
goto next; goto next;
/* Whenever an lxc.mount.entry entry is found in a line we check
* if the substring " overlay" or the substring " aufs" is /* Whenever an lxc.mount.entry entry is found in a line we check
* present before doing any further work. We check for " * if the substring " overlay" or the substring " aufs" is
* overlay" and " aufs" since both substrings need to have at * present before doing any further work. We check for "
* least one space before them in a valid overlay * overlay" and " aufs" since both substrings need to have at
* lxc.mount.entry (/A B overlay). When the space before is * least one space before them in a valid overlay
* missing it is very likely that these substrings are part of a * lxc.mount.entry (/A B overlay). When the space before is
* path or something else. (Checking q >= lend ensures that we * missing it is very likely that these substrings are part of a
* only count matches in the current line.) */ * path or something else. (Checking q >= lend ensures that we
if ((!(q = strstr(p, " overlay")) || q >= lend) && (!(q = strstr(p, " aufs")) || q >= lend)) * only count matches in the current line.) */
goto next; if ((!(q = strstr(p, " overlay")) || q >= lend) &&
(!(q = strstr(p, " aufs")) || q >= lend))
goto next;
if (!(q = strstr(p, olddir)) || (q >= lend)) if (!(q = strstr(p, olddir)) || (q >= lend))
goto next; goto next;
/* replace the olddir with newdir */ /* replace the olddir with newdir */
if (olddirlen >= newdirlen) { if (olddirlen >= newdirlen) {
...@@ -2981,6 +3048,7 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, ...@@ -2981,6 +3048,7 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
size_t oldlen = conf->unexpanded_len; size_t oldlen = conf->unexpanded_len;
size_t newlen = oldlen + diff; size_t newlen = oldlen + diff;
size_t poffset = q - conf->unexpanded_config; size_t poffset = q - conf->unexpanded_config;
new = realloc(conf->unexpanded_config, newlen + 1); new = realloc(conf->unexpanded_config, newlen + 1);
if (!new) { if (!new) {
ERROR("Out of memory"); ERROR("Out of memory");
...@@ -2990,7 +3058,8 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, ...@@ -2990,7 +3058,8 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
conf->unexpanded_alloced = newlen + 1; conf->unexpanded_alloced = newlen + 1;
new[newlen - 1] = '\0'; new[newlen - 1] = '\0';
lend = new + (lend - conf->unexpanded_config); lend = new + (lend - conf->unexpanded_config);
/* move over the remainder to make room for the newdir */ /* move over the remainder to make room for the newdir
*/
memmove(new + poffset + newdirlen, memmove(new + poffset + newdirlen,
new + poffset + olddirlen, new + poffset + olddirlen,
oldlen - poffset - olddirlen + 1); oldlen - poffset - olddirlen + 1);
...@@ -2998,9 +3067,10 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, ...@@ -2998,9 +3067,10 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
memcpy(new + poffset, newdir, newdirlen); memcpy(new + poffset, newdir, newdirlen);
lend += diff; lend += diff;
} }
next: next:
lstart = lend; lstart = lend;
} }
return true; return true;
} }
...@@ -3008,22 +3078,25 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, ...@@ -3008,22 +3078,25 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
const char *newpath, const char *oldname, const char *newpath, const char *oldname,
const char *newname) const char *newname)
{ {
const char *key = "lxc.hook";
int ret; int ret;
char *lstart = conf->unexpanded_config, *lend, *p; char *lend, *newdir, *olddir, *p;
size_t newdirlen = strlen(newpath) + strlen(newname) + 1; char *lstart = conf->unexpanded_config;
size_t olddirlen = strlen(oldpath) + strlen(oldname) + 1; size_t newdirlen, olddirlen;
char *olddir = alloca(olddirlen + 1); const char *key = "lxc.hook";
char *newdir = alloca(newdirlen + 1);
olddirlen = strlen(oldpath) + strlen(oldname) + 1;
olddir = alloca(olddirlen + 1);
ret = snprintf(olddir, olddirlen + 1, "%s/%s", oldpath, oldname); ret = snprintf(olddir, olddirlen + 1, "%s/%s", oldpath, oldname);
if (ret < 0 || ret >= olddirlen + 1) { if (ret < 0 || ret >= olddirlen + 1) {
ERROR("Bug in %s", __func__); ERROR("failed to create string");
return false; return false;
} }
newdirlen = strlen(newpath) + strlen(newname) + 1;
newdir = alloca(newdirlen + 1);
ret = snprintf(newdir, newdirlen + 1, "%s/%s", newpath, newname); ret = snprintf(newdir, newdirlen + 1, "%s/%s", newpath, newname);
if (ret < 0 || ret >= newdirlen + 1) { if (ret < 0 || ret >= newdirlen + 1) {
ERROR("Bug in %s", __func__); ERROR("failed to create string");
return false; return false;
} }
if (!conf->unexpanded_config) if (!conf->unexpanded_config)
...@@ -3034,18 +3107,24 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, ...@@ -3034,18 +3107,24 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
lend = lstart + strlen(lstart); lend = lstart + strlen(lstart);
else else
lend++; lend++;
if (strncmp(lstart, key, strlen(key)) != 0) if (strncmp(lstart, key, strlen(key)) != 0)
goto next; goto next;
p = strchr(lstart + strlen(key), '='); p = strchr(lstart + strlen(key), '=');
if (!p) if (!p)
goto next; goto next;
p++; p++;
while (isblank(*p)) while (isblank(*p))
p++; p++;
if (p >= lend)
goto next; if (p >= lend)
goto next;
if (strncmp(p, olddir, strlen(olddir)) != 0) if (strncmp(p, olddir, strlen(olddir)) != 0)
goto next; goto next;
/* replace the olddir with newdir */ /* replace the olddir with newdir */
if (olddirlen >= newdirlen) { if (olddirlen >= newdirlen) {
size_t diff = olddirlen - newdirlen; size_t diff = olddirlen - newdirlen;
...@@ -3062,16 +3141,18 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, ...@@ -3062,16 +3141,18 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
size_t oldlen = conf->unexpanded_len; size_t oldlen = conf->unexpanded_len;
size_t newlen = oldlen + diff; size_t newlen = oldlen + diff;
size_t poffset = p - conf->unexpanded_config; size_t poffset = p - conf->unexpanded_config;
new = realloc(conf->unexpanded_config, newlen + 1); new = realloc(conf->unexpanded_config, newlen + 1);
if (!new) { if (!new) {
ERROR("Out of memory"); ERROR("failed to allocate memory");
return false; return false;
} }
conf->unexpanded_len = newlen; conf->unexpanded_len = newlen;
conf->unexpanded_alloced = newlen + 1; conf->unexpanded_alloced = newlen + 1;
new[newlen - 1] = '\0'; new[newlen - 1] = '\0';
lend = new + (lend - conf->unexpanded_config); lend = new + (lend - conf->unexpanded_config);
/* move over the remainder to make room for the newdir */ /* move over the remainder to make room for the newdir
*/
memmove(new + poffset + newdirlen, memmove(new + poffset + newdirlen,
new + poffset + olddirlen, new + poffset + olddirlen,
oldlen - poffset - olddirlen + 1); oldlen - poffset - olddirlen + 1);
...@@ -3079,18 +3160,20 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, ...@@ -3079,18 +3160,20 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
memcpy(new + poffset, newdir, newdirlen); memcpy(new + poffset, newdir, newdirlen);
lend += diff; lend += diff;
} }
next: next:
lstart = lend; lstart = lend;
} }
return true; return true;
} }
#define DO(cmd) { \ #define DO(cmd) \
if (!(cmd)) { \ { \
ERROR("Error writing to new config"); \ if (!(cmd)) { \
return false; \ ERROR("Error writing to new config"); \
} \ return false; \
} } \
}
static bool new_hwaddr(char *hwaddr) static bool new_hwaddr(char *hwaddr)
{ {
...@@ -3109,21 +3192,20 @@ static bool new_hwaddr(char *hwaddr) ...@@ -3109,21 +3192,20 @@ static bool new_hwaddr(char *hwaddr)
} }
/* /*
* This is called only from clone. * This is called only from clone. We wish to update all hwaddrs in the
* We wish to update all hwaddrs in the unexpanded config file. We * unexpanded config file. We can't/don't want to update any which come from
* can't/don't want to update any which come from lxc.includes (there * lxc.includes (there shouldn't be any).
* shouldn't be any). * We can't just walk the c->lxc-conf->network list because that includes netifs
* We can't just walk the c->lxc-conf->network list because that includes * from the include files. So we update the ones which we find in the unexp
* netifs from the include files. So we update the ones which we find in * config file, then find the original macaddr in the conf->network, and update
* the unexp config file, then find the original macaddr in the * that to the same value.
* conf->network, and update that to the same value.
*/ */
bool network_new_hwaddrs(struct lxc_conf *conf) bool network_new_hwaddrs(struct lxc_conf *conf)
{ {
char *lend, *p, *p2;
struct lxc_list *it; struct lxc_list *it;
const char *key = "lxc.network.hwaddr"; const char *key = "lxc.network.hwaddr";
char *lstart = conf->unexpanded_config, *lend, *p, *p2; char *lstart = conf->unexpanded_config;
if (!conf->unexpanded_config) if (!conf->unexpanded_config)
return true; return true;
...@@ -3142,7 +3224,7 @@ bool network_new_hwaddrs(struct lxc_conf *conf) ...@@ -3142,7 +3224,7 @@ bool network_new_hwaddrs(struct lxc_conf *conf)
continue; continue;
} }
p = strchr(lstart+strlen(key), '='); p = strchr(lstart + strlen(key), '=');
if (!p) { if (!p) {
lstart = lend; lstart = lend;
continue; continue;
...@@ -3157,7 +3239,8 @@ bool network_new_hwaddrs(struct lxc_conf *conf) ...@@ -3157,7 +3239,8 @@ bool network_new_hwaddrs(struct lxc_conf *conf)
p2 = p; p2 = p;
while (*p2 && !isblank(*p2) && *p2 != '\n') while (*p2 && !isblank(*p2) && *p2 != '\n')
p2++; p2++;
if (p2-p != 17) {
if ((p2 - p) != 17) {
WARN("Bad hwaddr entry"); WARN("Bad hwaddr entry");
lstart = lend; lstart = lend;
continue; continue;
...@@ -3169,7 +3252,8 @@ bool network_new_hwaddrs(struct lxc_conf *conf) ...@@ -3169,7 +3252,8 @@ bool network_new_hwaddrs(struct lxc_conf *conf)
return false; return false;
memcpy(p, newhwaddr, 17); memcpy(p, newhwaddr, 17);
lxc_list_for_each(it, &conf->network) { lxc_list_for_each(it, &conf->network)
{
struct lxc_netdev *n = it->elem; struct lxc_netdev *n = it->elem;
if (n->hwaddr && memcmp(oldhwaddr, n->hwaddr, 17) == 0) if (n->hwaddr && memcmp(oldhwaddr, n->hwaddr, 17) == 0)
memcpy(n->hwaddr, newhwaddr, 17); memcpy(n->hwaddr, newhwaddr, 17);
...@@ -3182,7 +3266,7 @@ bool network_new_hwaddrs(struct lxc_conf *conf) ...@@ -3182,7 +3266,7 @@ bool network_new_hwaddrs(struct lxc_conf *conf)
} }
static int set_config_ephemeral(const char *key, const char *value, static int set_config_ephemeral(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
/* Set config value to default. */ /* Set config value to default. */
if (config_value_empty(value)) { if (config_value_empty(value)) {
...@@ -3195,7 +3279,8 @@ static int set_config_ephemeral(const char *key, const char *value, ...@@ -3195,7 +3279,8 @@ static int set_config_ephemeral(const char *key, const char *value,
return -1; return -1;
if (lxc_conf->ephemeral > 1) { if (lxc_conf->ephemeral > 1) {
ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1"); ERROR(
"Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
return -1; return -1;
} }
...@@ -3203,7 +3288,7 @@ static int set_config_ephemeral(const char *key, const char *value, ...@@ -3203,7 +3288,7 @@ static int set_config_ephemeral(const char *key, const char *value,
} }
static int set_config_syslog(const char *key, const char *value, static int set_config_syslog(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
int facility; int facility;
...@@ -3229,7 +3314,7 @@ static int set_config_syslog(const char *key, const char *value, ...@@ -3229,7 +3314,7 @@ static int set_config_syslog(const char *key, const char *value,
} }
static int set_config_no_new_privs(const char *key, const char *value, static int set_config_no_new_privs(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
unsigned int v; unsigned int v;
...@@ -3244,7 +3329,8 @@ static int set_config_no_new_privs(const char *key, const char *value, ...@@ -3244,7 +3329,8 @@ static int set_config_no_new_privs(const char *key, const char *value,
return -1; return -1;
if (v > 1) { if (v > 1) {
ERROR("Wrong value for lxc.no_new_privs. Can only be set to 0 or 1"); ERROR("Wrong value for lxc.no_new_privs. Can only be set to 0 "
"or 1");
return -1; return -1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment