]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile.c
confile: add getter for lxc.rootfs.options
[mirror_lxc.git] / src / lxc / confile.c
1 /*
2 * lxc: linux Container library
3 * (C) Copyright IBM Corp. 2007, 2008
4 *
5 * Authors:
6 * Daniel Lezcano <daniel.lezcano at free.fr>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 #define _GNU_SOURCE
23 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31 #include <inttypes.h> /* Required for PRIu64 to work. */
32 #include <signal.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/utsname.h>
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
39 #include <net/if.h>
40 #include <time.h>
41 #include <dirent.h>
42 #include <syslog.h>
43
44 #include "bdev.h"
45 #include "parse.h"
46 #include "config.h"
47 #include "confile.h"
48 #include "utils.h"
49 #include "log.h"
50 #include "conf.h"
51 #include "network.h"
52 #include "lxcseccomp.h"
53
54 #if HAVE_IFADDRS_H
55 #include <ifaddrs.h>
56 #else
57 #include <../include/ifaddrs.h>
58 #endif
59
60 #if HAVE_SYS_PERSONALITY_H
61 #include <sys/personality.h>
62 #endif
63
64 lxc_log_define(lxc_confile, lxc);
65
66 static int set_config_personality(const char *, const char *, struct lxc_conf *);
67 static int get_config_personality(struct lxc_container *, const char *, char *, int);
68
69 static int set_config_pts(const char *, const char *, struct lxc_conf *);
70 static int get_config_pts(struct lxc_container *, const char *, char *, int);
71
72 static int set_config_tty(const char *, const char *, struct lxc_conf *);
73 static int get_config_tty(struct lxc_container *, const char *, char *, int);
74
75 static int set_config_ttydir(const char *, const char *, struct lxc_conf *);
76 static int get_config_ttydir(struct lxc_container *, const char *, char *, int);
77
78 static int set_config_kmsg(const char *, const char *, struct lxc_conf *);
79 static int get_config_kmsg(struct lxc_container *, const char *, char *, int);
80
81 static int set_config_lsm_aa_profile(const char *, const char *, struct lxc_conf *);
82 static int get_config_lsm_aa_profile(struct lxc_container *, const char *, char *, int);
83
84 static int set_config_lsm_aa_incomplete(const char *, const char *, struct lxc_conf *);
85 static int get_config_lsm_aa_incomplete(struct lxc_container *, const char *, char *, int);
86
87 static int set_config_lsm_se_context(const char *, const char *, struct lxc_conf *);
88 static int get_config_lsm_se_context(struct lxc_container *, const char *, char *, int);
89
90 static int set_config_cgroup(const char *, const char *, struct lxc_conf *);
91 static int get_config_cgroup(struct lxc_container *, const char *, char *, int);
92
93 static int set_config_idmaps(const char *, const char *, struct lxc_conf *);
94 static int get_config_idmaps(struct lxc_container *, const char *, char *, int);
95
96 static int set_config_loglevel(const char *, const char *, struct lxc_conf *);
97 static int get_config_loglevel(struct lxc_container *, const char *, char *, int);
98
99 static int set_config_logfile(const char *, const char *, struct lxc_conf *);
100 static int get_config_logfile(struct lxc_container *, const char *, char *, int);
101
102 static int set_config_mount(const char *, const char *, struct lxc_conf *);
103 static int get_config_mount(struct lxc_container *, const char *, char *, int);
104
105 static int set_config_mount_auto(const char *, const char *, struct lxc_conf *);
106 static int get_config_mount_auto(struct lxc_container *, const char *, char *, int);
107
108 static int set_config_fstab(const char *, const char *, struct lxc_conf *);
109 static int get_config_fstab(struct lxc_container *, const char *, char *, int);
110
111 static int set_config_rootfs(const char *, const char *, struct lxc_conf *);
112 static int get_config_rootfs(struct lxc_container *, const char *, char *, int);
113
114 static int set_config_rootfs_mount(const char *, const char *, struct lxc_conf *);
115 static int get_config_rootfs_mount(struct lxc_container *, const char *, char *, int);
116
117 static int set_config_rootfs_options(const char *, const char *, struct lxc_conf *);
118 static int get_config_rootfs_options(struct lxc_container *, const char *, char *, int);
119
120 static int set_config_rootfs_backend(const char *, const char *, struct lxc_conf *);
121 static int set_config_pivotdir(const char *, const char *, struct lxc_conf *);
122 static int set_config_utsname(const char *, const char *, struct lxc_conf *);
123 static int set_config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
124 static int set_config_network(const char *, const char *, struct lxc_conf *);
125 static int set_config_network_type(const char *, const char *, struct lxc_conf *);
126 static int set_config_network_flags(const char *, const char *, struct lxc_conf *);
127 static int set_config_network_link(const char *, const char *, struct lxc_conf *);
128 static int set_config_network_name(const char *, const char *, struct lxc_conf *);
129 static int set_config_network_veth_pair(const char *, const char *, struct lxc_conf *);
130 static int set_config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
131 static int set_config_network_hwaddr(const char *, const char *, struct lxc_conf *);
132 static int set_config_network_vlan_id(const char *, const char *, struct lxc_conf *);
133 static int set_config_network_mtu(const char *, const char *, struct lxc_conf *);
134 static int set_config_network_ipv4(const char *, const char *, struct lxc_conf *);
135 static int set_config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
136 static int set_config_network_script_up(const char *, const char *, struct lxc_conf *);
137 static int set_config_network_script_down(const char *, const char *, struct lxc_conf *);
138 static int set_config_network_ipv6(const char *, const char *, struct lxc_conf *);
139 static int set_config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
140 static int set_config_cap_drop(const char *, const char *, struct lxc_conf *);
141 static int set_config_cap_keep(const char *, const char *, struct lxc_conf *);
142 static int set_config_console(const char *, const char *, struct lxc_conf *);
143 static int set_config_console_logfile(const char *, const char *, struct lxc_conf *);
144 static int set_config_seccomp(const char *, const char *, struct lxc_conf *);
145 static int set_config_includefile(const char *, const char *, struct lxc_conf *);
146 static int set_config_network_nic(const char *, const char *, struct lxc_conf *);
147 static int set_config_autodev(const char *, const char *, struct lxc_conf *);
148 static int set_config_haltsignal(const char *, const char *, struct lxc_conf *);
149 static int set_config_rebootsignal(const char *, const char *, struct lxc_conf *);
150 static int set_config_stopsignal(const char *, const char *, struct lxc_conf *);
151 static int set_config_start(const char *, const char *, struct lxc_conf *);
152 static int set_config_syslog(const char *, const char *, struct lxc_conf *);
153 static int set_config_monitor(const char *, const char *, struct lxc_conf *);
154 static int set_config_group(const char *, const char *, struct lxc_conf *);
155 static int set_config_environment(const char *, const char *, struct lxc_conf *);
156 static int set_config_init_cmd(const char *, const char *, struct lxc_conf *);
157 static int set_config_init_uid(const char *, const char *, struct lxc_conf *);
158 static int set_config_init_gid(const char *, const char *, struct lxc_conf *);
159 static int set_config_ephemeral(const char *, const char *, struct lxc_conf *);
160 static int set_config_no_new_privs(const char *, const char *, struct lxc_conf *);
161 static int set_config_limit(const char *, const char *, struct lxc_conf *);
162
163 static struct lxc_config_t config[] = {
164 { "lxc.arch", set_config_personality, get_config_personality, NULL},
165 { "lxc.pts", set_config_pts, get_config_pts, NULL},
166 { "lxc.tty", set_config_tty, get_config_tty, NULL},
167 { "lxc.devttydir", set_config_ttydir, get_config_ttydir, NULL},
168 { "lxc.kmsg", set_config_kmsg, get_config_kmsg, NULL},
169 { "lxc.aa_profile", set_config_lsm_aa_profile, get_config_lsm_aa_profile, NULL},
170 { "lxc.aa_allow_incomplete", set_config_lsm_aa_incomplete, get_config_lsm_aa_incomplete, NULL},
171 { "lxc.se_context", set_config_lsm_se_context, get_config_lsm_se_context, NULL},
172 { "lxc.cgroup", set_config_cgroup, get_config_cgroup, NULL},
173 { "lxc.id_map", set_config_idmaps, get_config_idmaps, NULL},
174 { "lxc.loglevel", set_config_loglevel, get_config_loglevel, NULL},
175 { "lxc.logfile", set_config_logfile, get_config_logfile, NULL},
176 { "lxc.mount.entry", set_config_mount, get_config_mount, NULL},
177 { "lxc.mount.auto", set_config_mount_auto, get_config_mount_auto, NULL},
178 { "lxc.mount", set_config_fstab, get_config_fstab, NULL},
179 { "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, NULL},
180 { "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, NULL},
181 { "lxc.rootfs.backend", set_config_rootfs_backend, NULL, NULL},
182 { "lxc.rootfs", set_config_rootfs, get_config_rootfs, NULL},
183 { "lxc.pivotdir", set_config_pivotdir, NULL, NULL},
184 { "lxc.utsname", set_config_utsname, NULL, NULL},
185 { "lxc.hook.pre-start", set_config_hook, NULL, NULL},
186 { "lxc.hook.pre-mount", set_config_hook, NULL, NULL},
187 { "lxc.hook.mount", set_config_hook, NULL, NULL},
188 { "lxc.hook.autodev", set_config_hook, NULL, NULL},
189 { "lxc.hook.start", set_config_hook, NULL, NULL},
190 { "lxc.hook.stop", set_config_hook, NULL, NULL},
191 { "lxc.hook.post-stop", set_config_hook, NULL, NULL},
192 { "lxc.hook.clone", set_config_hook, NULL, NULL},
193 { "lxc.hook.destroy", set_config_hook, NULL, NULL},
194 { "lxc.hook", set_config_hook, NULL, NULL},
195 { "lxc.network.type", set_config_network_type, NULL, NULL},
196 { "lxc.network.flags", set_config_network_flags, NULL, NULL},
197 { "lxc.network.link", set_config_network_link, NULL, NULL},
198 { "lxc.network.name", set_config_network_name, NULL, NULL},
199 { "lxc.network.macvlan.mode", set_config_network_macvlan_mode, NULL, NULL},
200 { "lxc.network.veth.pair", set_config_network_veth_pair, NULL, NULL},
201 { "lxc.network.script.up", set_config_network_script_up, NULL, NULL},
202 { "lxc.network.script.down", set_config_network_script_down, NULL, NULL},
203 { "lxc.network.hwaddr", set_config_network_hwaddr, NULL, NULL},
204 { "lxc.network.mtu", set_config_network_mtu, NULL, NULL},
205 { "lxc.network.vlan.id", set_config_network_vlan_id, NULL, NULL},
206 { "lxc.network.ipv4.gateway", set_config_network_ipv4_gateway, NULL, NULL},
207 { "lxc.network.ipv4", set_config_network_ipv4, NULL, NULL},
208 { "lxc.network.ipv6.gateway", set_config_network_ipv6_gateway, NULL, NULL},
209 { "lxc.network.ipv6", set_config_network_ipv6, NULL, NULL},
210 { "lxc.network.", set_config_network_nic, NULL, NULL},
211 { "lxc.network", set_config_network, NULL, NULL},
212 { "lxc.cap.drop", set_config_cap_drop, NULL, NULL},
213 { "lxc.cap.keep", set_config_cap_keep, NULL, NULL},
214 { "lxc.console.logfile", set_config_console_logfile, NULL, NULL},
215 { "lxc.console", set_config_console, NULL, NULL},
216 { "lxc.seccomp", set_config_seccomp, NULL, NULL},
217 { "lxc.include", set_config_includefile, NULL, NULL},
218 { "lxc.autodev", set_config_autodev, NULL, NULL},
219 { "lxc.haltsignal", set_config_haltsignal, NULL, NULL},
220 { "lxc.rebootsignal", set_config_rebootsignal, NULL, NULL},
221 { "lxc.stopsignal", set_config_stopsignal, NULL, NULL},
222 { "lxc.start.auto", set_config_start, NULL, NULL},
223 { "lxc.start.delay", set_config_start, NULL, NULL},
224 { "lxc.start.order", set_config_start, NULL, NULL},
225 { "lxc.monitor.unshare", set_config_monitor, NULL, NULL},
226 { "lxc.group", set_config_group, NULL, NULL},
227 { "lxc.environment", set_config_environment, NULL, NULL},
228 { "lxc.init_cmd", set_config_init_cmd, NULL, NULL},
229 { "lxc.init_uid", set_config_init_uid, NULL, NULL},
230 { "lxc.init_gid", set_config_init_gid, NULL, NULL},
231 { "lxc.ephemeral", set_config_ephemeral, NULL, NULL},
232 { "lxc.syslog", set_config_syslog, NULL, NULL},
233 { "lxc.no_new_privs", set_config_no_new_privs, NULL, NULL},
234 { "lxc.limit", set_config_limit, NULL, NULL},
235 };
236
237 struct signame {
238 int num;
239 const char *name;
240 };
241
242 static const struct signame signames[] = {
243 { SIGHUP, "HUP" },
244 { SIGINT, "INT" },
245 { SIGQUIT, "QUIT" },
246 { SIGILL, "ILL" },
247 { SIGABRT, "ABRT" },
248 { SIGFPE, "FPE" },
249 { SIGKILL, "KILL" },
250 { SIGSEGV, "SEGV" },
251 { SIGPIPE, "PIPE" },
252 { SIGALRM, "ALRM" },
253 { SIGTERM, "TERM" },
254 { SIGUSR1, "USR1" },
255 { SIGUSR2, "USR2" },
256 { SIGCHLD, "CHLD" },
257 { SIGCONT, "CONT" },
258 { SIGSTOP, "STOP" },
259 { SIGTSTP, "TSTP" },
260 { SIGTTIN, "TTIN" },
261 { SIGTTOU, "TTOU" },
262 #ifdef SIGTRAP
263 { SIGTRAP, "TRAP" },
264 #endif
265 #ifdef SIGIOT
266 { SIGIOT, "IOT" },
267 #endif
268 #ifdef SIGEMT
269 { SIGEMT, "EMT" },
270 #endif
271 #ifdef SIGBUS
272 { SIGBUS, "BUS" },
273 #endif
274 #ifdef SIGSTKFLT
275 { SIGSTKFLT, "STKFLT" },
276 #endif
277 #ifdef SIGCLD
278 { SIGCLD, "CLD" },
279 #endif
280 #ifdef SIGURG
281 { SIGURG, "URG" },
282 #endif
283 #ifdef SIGXCPU
284 { SIGXCPU, "XCPU" },
285 #endif
286 #ifdef SIGXFSZ
287 { SIGXFSZ, "XFSZ" },
288 #endif
289 #ifdef SIGVTALRM
290 { SIGVTALRM, "VTALRM" },
291 #endif
292 #ifdef SIGPROF
293 { SIGPROF, "PROF" },
294 #endif
295 #ifdef SIGWINCH
296 { SIGWINCH, "WINCH" },
297 #endif
298 #ifdef SIGIO
299 { SIGIO, "IO" },
300 #endif
301 #ifdef SIGPOLL
302 { SIGPOLL, "POLL" },
303 #endif
304 #ifdef SIGINFO
305 { SIGINFO, "INFO" },
306 #endif
307 #ifdef SIGLOST
308 { SIGLOST, "LOST" },
309 #endif
310 #ifdef SIGPWR
311 { SIGPWR, "PWR" },
312 #endif
313 #ifdef SIGUNUSED
314 { SIGUNUSED, "UNUSED" },
315 #endif
316 #ifdef SIGSYS
317 { SIGSYS, "SYS" },
318 #endif
319 };
320
321 static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
322
323 extern struct lxc_config_t *lxc_getconfig(const char *key)
324 {
325 size_t i;
326
327 for (i = 0; i < config_size; i++)
328 if (!strncmp(config[i].name, key,
329 strlen(config[i].name)))
330 return &config[i];
331 return NULL;
332 }
333
334 #define strprint(str, inlen, ...) \
335 do { \
336 len = snprintf(str, inlen, ##__VA_ARGS__); \
337 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
338 fulllen += len; \
339 if (inlen > 0) { \
340 if (str) str += len; \
341 inlen -= len; \
342 if (inlen < 0) inlen = 0; \
343 } \
344 } while (0);
345
346 int lxc_listconfigs(char *retv, int inlen)
347 {
348 size_t i;
349 int fulllen = 0, len;
350
351 if (!retv)
352 inlen = 0;
353 else
354 memset(retv, 0, inlen);
355 for (i = 0; i < config_size; i++) {
356 char *s = config[i].name;
357 if (s[strlen(s)-1] == '.')
358 continue;
359 strprint(retv, inlen, "%s\n", s);
360 }
361 return fulllen;
362 }
363
364 static inline bool config_value_empty(const char *value)
365 {
366 if (value && strlen(value) > 0)
367 return false;
368
369 return true;
370 }
371
372 static int set_config_string_item(char **conf_item, const char *value)
373 {
374 char *new_value;
375
376 if (config_value_empty(value)) {
377 free(*conf_item);
378 *conf_item = NULL;
379 return 0;
380 }
381
382 new_value = strdup(value);
383 if (!new_value) {
384 SYSERROR("failed to duplicate string \"%s\"", value);
385 return -1;
386 }
387
388 free(*conf_item);
389 *conf_item = new_value;
390 return 0;
391 }
392
393 static int set_config_string_item_max(char **conf_item, const char *value,
394 size_t max)
395 {
396 if (strlen(value) >= max) {
397 ERROR("%s is too long (>= %lu)", value, (unsigned long)max);
398 return -1;
399 }
400
401 return set_config_string_item(conf_item, value);
402 }
403
404 static int set_config_path_item(char **conf_item, const char *value)
405 {
406 return set_config_string_item_max(conf_item, value, PATH_MAX);
407 }
408
409 /*
410 * config entry is something like "lxc.network.0.ipv4"
411 * the key 'lxc.network.' was found. So we make sure next
412 * comes an integer, find the right callback (by rewriting
413 * the key), and call it.
414 */
415 static int set_config_network_nic(const char *key, const char *value,
416 struct lxc_conf *lxc_conf)
417 {
418 char *copy = strdup(key), *p;
419 int ret = -1;
420 struct lxc_config_t *config;
421
422 if (!copy) {
423 SYSERROR("failed to allocate memory");
424 return -1;
425 }
426 /*
427 * ok we know that to get here we've got "lxc.network."
428 * and it isn't any of the other network entries. So
429 * after the second . should come an integer (# of defined
430 * nic) followed by a valid entry.
431 */
432 if (*(key+12) < '0' || *(key+12) > '9')
433 goto out;
434 p = strchr(key+12, '.');
435 if (!p)
436 goto out;
437 strcpy(copy+12, p+1);
438 config = lxc_getconfig(copy);
439 if (!config) {
440 ERROR("unknown key %s", key);
441 goto out;
442 }
443 ret = config->set(key, value, lxc_conf);
444
445 out:
446 free(copy);
447 return ret;
448 }
449
450 static int set_config_network(const char *key, const char *value,
451 struct lxc_conf *lxc_conf)
452 {
453 if (!config_value_empty(value)) {
454 ERROR("lxc.network must not have a value");
455 return -1;
456 }
457
458 return lxc_clear_config_network(lxc_conf);
459 }
460
461 static int macvlan_mode(int *valuep, const char *value);
462
463 static int set_config_network_type(const char *key, const char *value,
464 struct lxc_conf *lxc_conf)
465 {
466 struct lxc_list *network = &lxc_conf->network;
467 struct lxc_netdev *netdev;
468 struct lxc_list *list;
469
470 if (config_value_empty(value))
471 return lxc_clear_config_network(lxc_conf);
472
473 netdev = malloc(sizeof(*netdev));
474 if (!netdev) {
475 SYSERROR("failed to allocate memory");
476 return -1;
477 }
478
479 memset(netdev, 0, sizeof(*netdev));
480 lxc_list_init(&netdev->ipv4);
481 lxc_list_init(&netdev->ipv6);
482
483 list = malloc(sizeof(*list));
484 if (!list) {
485 SYSERROR("failed to allocate memory");
486 free(netdev);
487 return -1;
488 }
489
490 lxc_list_init(list);
491 list->elem = netdev;
492
493 lxc_list_add_tail(network, list);
494
495 if (!strcmp(value, "veth"))
496 netdev->type = LXC_NET_VETH;
497 else if (!strcmp(value, "macvlan")) {
498 netdev->type = LXC_NET_MACVLAN;
499 macvlan_mode(&netdev->priv.macvlan_attr.mode, "private");
500 }
501 else if (!strcmp(value, "vlan"))
502 netdev->type = LXC_NET_VLAN;
503 else if (!strcmp(value, "phys"))
504 netdev->type = LXC_NET_PHYS;
505 else if (!strcmp(value, "empty"))
506 netdev->type = LXC_NET_EMPTY;
507 else if (!strcmp(value, "none"))
508 netdev->type = LXC_NET_NONE;
509 else {
510 ERROR("invalid network type %s", value);
511 return -1;
512 }
513 return 0;
514 }
515
516 static int config_ip_prefix(struct in_addr *addr)
517 {
518 if (IN_CLASSA(addr->s_addr))
519 return 32 - IN_CLASSA_NSHIFT;
520 if (IN_CLASSB(addr->s_addr))
521 return 32 - IN_CLASSB_NSHIFT;
522 if (IN_CLASSC(addr->s_addr))
523 return 32 - IN_CLASSC_NSHIFT;
524
525 return 0;
526 }
527
528 /*
529 * if you have p="lxc.network.0.link", pass it p+12
530 * to get back '0' (the index of the nic)
531 */
532 static int get_network_netdev_idx(const char *key)
533 {
534 int ret, idx;
535
536 if (*key < '0' || *key > '9')
537 return -1;
538 ret = sscanf(key, "%d", &idx);
539 if (ret != 1)
540 return -1;
541 return idx;
542 }
543
544 /*
545 * if you have p="lxc.network.0", pass this p+12 and it will return
546 * the netdev of the first configured nic
547 */
548 static struct lxc_netdev *get_netdev_from_key(const char *key,
549 struct lxc_list *network)
550 {
551 int i = 0, idx = get_network_netdev_idx(key);
552 struct lxc_netdev *netdev = NULL;
553 struct lxc_list *it;
554 if (idx == -1)
555 return NULL;
556 lxc_list_for_each(it, network) {
557 if (idx == i++) {
558 netdev = it->elem;
559 break;
560 }
561 }
562 return netdev;
563 }
564
565 extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
566 char *retv, int inlen)
567 {
568 struct lxc_netdev *netdev;
569 int fulllen = 0, len;
570
571 netdev = get_netdev_from_key(key+12, &c->network);
572 if (!netdev)
573 return -1;
574
575 if (!retv)
576 inlen = 0;
577 else
578 memset(retv, 0, inlen);
579
580 strprint(retv, inlen, "type\n");
581 strprint(retv, inlen, "script.up\n");
582 strprint(retv, inlen, "script.down\n");
583 if (netdev->type != LXC_NET_EMPTY) {
584 strprint(retv, inlen, "flags\n");
585 strprint(retv, inlen, "link\n");
586 strprint(retv, inlen, "name\n");
587 strprint(retv, inlen, "hwaddr\n");
588 strprint(retv, inlen, "mtu\n");
589 strprint(retv, inlen, "ipv6\n");
590 strprint(retv, inlen, "ipv6.gateway\n");
591 strprint(retv, inlen, "ipv4\n");
592 strprint(retv, inlen, "ipv4.gateway\n");
593 }
594 switch(netdev->type) {
595 case LXC_NET_VETH:
596 strprint(retv, inlen, "veth.pair\n");
597 break;
598 case LXC_NET_MACVLAN:
599 strprint(retv, inlen, "macvlan.mode\n");
600 break;
601 case LXC_NET_VLAN:
602 strprint(retv, inlen, "vlan.id\n");
603 break;
604 case LXC_NET_PHYS:
605 break;
606 }
607 return fulllen;
608 }
609
610 static struct lxc_netdev *network_netdev(const char *key, const char *value,
611 struct lxc_list *network)
612 {
613 struct lxc_netdev *netdev = NULL;
614
615 if (lxc_list_empty(network)) {
616 ERROR("network is not created for '%s' = '%s' option",
617 key, value);
618 return NULL;
619 }
620
621 if (get_network_netdev_idx(key+12) == -1)
622 netdev = lxc_list_last_elem(network);
623 else
624 netdev = get_netdev_from_key(key+12, network);
625
626 if (!netdev) {
627 ERROR("no network device defined for '%s' = '%s' option",
628 key, value);
629 return NULL;
630 }
631
632 return netdev;
633 }
634
635 static int network_ifname(char **valuep, const char *value)
636 {
637 return set_config_string_item_max(valuep, value, IFNAMSIZ);
638 }
639
640 #ifndef MACVLAN_MODE_PRIVATE
641 # define MACVLAN_MODE_PRIVATE 1
642 #endif
643
644 #ifndef MACVLAN_MODE_VEPA
645 # define MACVLAN_MODE_VEPA 2
646 #endif
647
648 #ifndef MACVLAN_MODE_BRIDGE
649 # define MACVLAN_MODE_BRIDGE 4
650 #endif
651
652 #ifndef MACVLAN_MODE_PASSTHRU
653 # define MACVLAN_MODE_PASSTHRU 8
654 #endif
655
656 static int macvlan_mode(int *valuep, const char *value)
657 {
658 struct mc_mode {
659 char *name;
660 int mode;
661 } m[] = {
662 { "private", MACVLAN_MODE_PRIVATE },
663 { "vepa", MACVLAN_MODE_VEPA },
664 { "bridge", MACVLAN_MODE_BRIDGE },
665 { "passthru", MACVLAN_MODE_PASSTHRU },
666 };
667
668 size_t i;
669
670 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
671 if (strcmp(m[i].name, value))
672 continue;
673
674 *valuep = m[i].mode;
675 return 0;
676 }
677
678 return -1;
679 }
680
681 static int rand_complete_hwaddr(char *hwaddr)
682 {
683 const char hex[] = "0123456789abcdef";
684 char *curs = hwaddr;
685
686 #ifndef HAVE_RAND_R
687 randseed(true);
688 #else
689 unsigned int seed=randseed(false);
690 #endif
691 while (*curs != '\0' && *curs != '\n')
692 {
693 if ( *curs == 'x' || *curs == 'X' ) {
694 if (curs - hwaddr == 1) {
695 //ensure address is unicast
696 #ifdef HAVE_RAND_R
697 *curs = hex[rand_r(&seed) & 0x0E];
698 } else {
699 *curs = hex[rand_r(&seed) & 0x0F];
700 #else
701 *curs = hex[rand() & 0x0E];
702 } else {
703 *curs = hex[rand() & 0x0F];
704 #endif
705 }
706 }
707 curs++;
708 }
709 return 0;
710 }
711
712 static int set_config_network_flags(const char *key, const char *value,
713 struct lxc_conf *lxc_conf)
714 {
715 struct lxc_netdev *netdev;
716
717 netdev = network_netdev(key, value, &lxc_conf->network);
718 if (!netdev)
719 return -1;
720
721 netdev->flags |= IFF_UP;
722
723 return 0;
724 }
725
726 static int set_network_link(const char *key, const char *value, struct lxc_conf *lxc_conf)
727 {
728 struct lxc_netdev *netdev;
729
730 netdev = network_netdev(key, value, &lxc_conf->network);
731 if (!netdev)
732 return -1;
733
734 return network_ifname(&netdev->link, value);
735 }
736
737 static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf)
738 {
739 struct ifaddrs *ifaddr, *ifa;
740 const char *type_key = "lxc.network.type";
741 const char *link_key = "lxc.network.link";
742 const char *tmpvalue = "phys";
743 int n, ret = 0;
744
745 if (getifaddrs(&ifaddr) == -1) {
746 SYSERROR("Get network interfaces failed");
747 return -1;
748 }
749
750 for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
751 if (!ifa->ifa_addr)
752 continue;
753 if (ifa->ifa_addr->sa_family != AF_PACKET)
754 continue;
755
756 if (!strncmp(value, ifa->ifa_name, strlen(value)-1)) {
757 ret = set_config_network_type(type_key, tmpvalue, lxc_conf);
758 if (!ret) {
759 ret = set_network_link(link_key, ifa->ifa_name, lxc_conf);
760 if (ret) {
761 ERROR("failed to create matched ifnames");
762 break;
763 }
764 } else {
765 ERROR("failed to create matched ifnames");
766 break;
767 }
768 }
769 }
770
771 freeifaddrs(ifaddr); /* free the dynamic memory */
772 ifaddr = NULL; /* prevent use after free */
773
774 return ret;
775 }
776
777 static int set_config_network_link(const char *key, const char *value,
778 struct lxc_conf *lxc_conf)
779 {
780 struct lxc_netdev *netdev;
781 struct lxc_list * it;
782 int ret = 0;
783
784 netdev = network_netdev(key, value, &lxc_conf->network);
785 if (!netdev)
786 return -1;
787
788 if (value[strlen(value) - 1] == '+' && netdev->type == LXC_NET_PHYS) {
789 //get the last network list and remove it.
790 it = lxc_conf->network.prev;
791 if (((struct lxc_netdev *)(it->elem))->type != LXC_NET_PHYS) {
792 ERROR("lxc config cannot support string pattern matching for this link type");
793 return -1;
794 }
795
796 lxc_list_del(it);
797 free(it);
798 ret = create_matched_ifnames(value, lxc_conf);
799
800 } else {
801 ret = network_ifname(&netdev->link, value);
802 }
803
804 return ret;
805 }
806
807 static int set_config_network_name(const char *key, const char *value,
808 struct lxc_conf *lxc_conf)
809 {
810 struct lxc_netdev *netdev;
811
812 netdev = network_netdev(key, value, &lxc_conf->network);
813 if (!netdev)
814 return -1;
815
816 return network_ifname(&netdev->name, value);
817 }
818
819 static int set_config_network_veth_pair(const char *key, const char *value,
820 struct lxc_conf *lxc_conf)
821 {
822 struct lxc_netdev *netdev;
823
824 netdev = network_netdev(key, value, &lxc_conf->network);
825 if (!netdev)
826 return -1;
827
828 if (netdev->type != LXC_NET_VETH) {
829 ERROR("Invalid veth pair for a non-veth netdev");
830 return -1;
831 }
832 return network_ifname(&netdev->priv.veth_attr.pair, value);
833 }
834
835 static int set_config_network_macvlan_mode(const char *key, const char *value,
836 struct lxc_conf *lxc_conf)
837 {
838 struct lxc_netdev *netdev;
839
840 netdev = network_netdev(key, value, &lxc_conf->network);
841 if (!netdev)
842 return -1;
843
844 if (netdev->type != LXC_NET_MACVLAN) {
845 ERROR("Invalid macvlan.mode for a non-macvlan netdev");
846 return -1;
847 }
848 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
849 }
850
851 static int set_config_network_hwaddr(const char *key, const char *value,
852 struct lxc_conf *lxc_conf)
853 {
854 struct lxc_netdev *netdev;
855
856 char *new_value = strdup(value);
857 if (!new_value) {
858 SYSERROR("failed to strdup '%s': %m", value);
859 return -1;
860 }
861 rand_complete_hwaddr(new_value);
862
863 netdev = network_netdev(key, new_value, &lxc_conf->network);
864 if (!netdev) {
865 free(new_value);
866 return -1;
867 };
868
869 if (config_value_empty(new_value)) {
870 free(new_value);
871 netdev->hwaddr = NULL;
872 return 0;
873 }
874
875 netdev->hwaddr = new_value;
876 return 0;
877 }
878
879 static int set_config_network_vlan_id(const char *key, const char *value,
880 struct lxc_conf *lxc_conf)
881 {
882 struct lxc_netdev *netdev;
883
884 netdev = network_netdev(key, value, &lxc_conf->network);
885 if (!netdev)
886 return -1;
887
888 if (netdev->type != LXC_NET_VLAN) {
889 ERROR("Invalid vlan.id for a non-macvlan netdev");
890 return -1;
891 }
892 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
893 return -1;
894
895 return 0;
896 }
897
898 static int set_config_network_mtu(const char *key, const char *value,
899 struct lxc_conf *lxc_conf)
900 {
901 struct lxc_netdev *netdev;
902
903 netdev = network_netdev(key, value, &lxc_conf->network);
904 if (!netdev)
905 return -1;
906
907 return set_config_string_item(&netdev->mtu, value);
908 }
909
910 static int set_config_network_ipv4(const char *key, const char *value,
911 struct lxc_conf *lxc_conf)
912 {
913 struct lxc_netdev *netdev;
914 struct lxc_inetdev *inetdev;
915 struct lxc_list *list;
916 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
917
918 if (config_value_empty(value))
919 return lxc_clear_config_item(lxc_conf, key);
920
921 netdev = network_netdev(key, value, &lxc_conf->network);
922 if (!netdev)
923 return -1;
924
925 inetdev = malloc(sizeof(*inetdev));
926 if (!inetdev) {
927 SYSERROR("failed to allocate ipv4 address");
928 return -1;
929 }
930 memset(inetdev, 0, sizeof(*inetdev));
931
932 list = malloc(sizeof(*list));
933 if (!list) {
934 SYSERROR("failed to allocate memory");
935 free(inetdev);
936 return -1;
937 }
938
939 lxc_list_init(list);
940 list->elem = inetdev;
941
942 addr = strdup(value);
943 if (!addr) {
944 ERROR("no address specified");
945 free(inetdev);
946 free(list);
947 return -1;
948 }
949
950 cursor = strstr(addr, " ");
951 if (cursor) {
952 *cursor = '\0';
953 bcast = cursor + 1;
954 }
955
956 slash = strstr(addr, "/");
957 if (slash) {
958 *slash = '\0';
959 prefix = slash + 1;
960 }
961
962 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
963 SYSERROR("invalid ipv4 address: %s", value);
964 free(inetdev);
965 free(addr);
966 free(list);
967 return -1;
968 }
969
970 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
971 SYSERROR("invalid ipv4 broadcast address: %s", value);
972 free(inetdev);
973 free(list);
974 free(addr);
975 return -1;
976 }
977
978 /* no prefix specified, determine it from the network class */
979 if (prefix) {
980 if (lxc_safe_uint(prefix, &inetdev->prefix) < 0)
981 return -1;
982 } else {
983 inetdev->prefix = config_ip_prefix(&inetdev->addr);
984 }
985
986 /* if no broadcast address, let compute one from the
987 * prefix and address
988 */
989 if (!bcast) {
990 inetdev->bcast.s_addr = inetdev->addr.s_addr;
991 inetdev->bcast.s_addr |=
992 htonl(INADDR_BROADCAST >> inetdev->prefix);
993 }
994
995 lxc_list_add_tail(&netdev->ipv4, list);
996
997 free(addr);
998 return 0;
999 }
1000
1001 static int set_config_network_ipv4_gateway(const char *key, const char *value,
1002 struct lxc_conf *lxc_conf)
1003 {
1004 struct lxc_netdev *netdev;
1005
1006 netdev = network_netdev(key, value, &lxc_conf->network);
1007 if (!netdev)
1008 return -1;
1009
1010 free(netdev->ipv4_gateway);
1011
1012 if (config_value_empty(value)) {
1013 netdev->ipv4_gateway = NULL;
1014 } else if (!strcmp(value, "auto")) {
1015 netdev->ipv4_gateway = NULL;
1016 netdev->ipv4_gateway_auto = true;
1017 } else {
1018 struct in_addr *gw;
1019
1020 gw = malloc(sizeof(*gw));
1021 if (!gw) {
1022 SYSERROR("failed to allocate ipv4 gateway address");
1023 return -1;
1024 }
1025
1026 if (!inet_pton(AF_INET, value, gw)) {
1027 SYSERROR("invalid ipv4 gateway address: %s", value);
1028 free(gw);
1029 return -1;
1030 }
1031
1032 netdev->ipv4_gateway = gw;
1033 netdev->ipv4_gateway_auto = false;
1034 }
1035
1036 return 0;
1037 }
1038
1039 static int set_config_network_ipv6(const char *key, const char *value,
1040 struct lxc_conf *lxc_conf)
1041 {
1042 struct lxc_netdev *netdev;
1043 struct lxc_inet6dev *inet6dev;
1044 struct lxc_list *list;
1045 char *slash,*valdup;
1046 char *netmask;
1047
1048 if (config_value_empty(value))
1049 return lxc_clear_config_item(lxc_conf, key);
1050
1051 netdev = network_netdev(key, value, &lxc_conf->network);
1052 if (!netdev)
1053 return -1;
1054
1055 inet6dev = malloc(sizeof(*inet6dev));
1056 if (!inet6dev) {
1057 SYSERROR("failed to allocate ipv6 address");
1058 return -1;
1059 }
1060 memset(inet6dev, 0, sizeof(*inet6dev));
1061
1062 list = malloc(sizeof(*list));
1063 if (!list) {
1064 SYSERROR("failed to allocate memory");
1065 free(inet6dev);
1066 return -1;
1067 }
1068
1069 lxc_list_init(list);
1070 list->elem = inet6dev;
1071
1072 valdup = strdup(value);
1073 if (!valdup) {
1074 ERROR("no address specified");
1075 free(list);
1076 free(inet6dev);
1077 return -1;
1078 }
1079
1080 inet6dev->prefix = 64;
1081 slash = strstr(valdup, "/");
1082 if (slash) {
1083 *slash = '\0';
1084 netmask = slash + 1;
1085 if (lxc_safe_uint(netmask, &inet6dev->prefix) < 0)
1086 return -1;
1087 }
1088
1089 if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {
1090 SYSERROR("invalid ipv6 address: %s", valdup);
1091 free(list);
1092 free(inet6dev);
1093 free(valdup);
1094 return -1;
1095 }
1096
1097 lxc_list_add_tail(&netdev->ipv6, list);
1098
1099 free(valdup);
1100 return 0;
1101 }
1102
1103 static int set_config_network_ipv6_gateway(const char *key, const char *value,
1104 struct lxc_conf *lxc_conf)
1105 {
1106 struct lxc_netdev *netdev;
1107
1108 netdev = network_netdev(key, value, &lxc_conf->network);
1109 if (!netdev)
1110 return -1;
1111
1112 free(netdev->ipv6_gateway);
1113
1114 if (config_value_empty(value)) {
1115 netdev->ipv6_gateway = NULL;
1116 } else if (!strcmp(value, "auto")) {
1117 netdev->ipv6_gateway = NULL;
1118 netdev->ipv6_gateway_auto = true;
1119 } else {
1120 struct in6_addr *gw;
1121
1122 gw = malloc(sizeof(*gw));
1123 if (!gw) {
1124 SYSERROR("failed to allocate ipv6 gateway address");
1125 return -1;
1126 }
1127
1128 if (!inet_pton(AF_INET6, value, gw)) {
1129 SYSERROR("invalid ipv6 gateway address: %s", value);
1130 free(gw);
1131 return -1;
1132 }
1133
1134 netdev->ipv6_gateway = gw;
1135 netdev->ipv6_gateway_auto = false;
1136 }
1137
1138 return 0;
1139 }
1140
1141 static int set_config_network_script_up(const char *key, const char *value,
1142 struct lxc_conf *lxc_conf)
1143 {
1144 struct lxc_netdev *netdev;
1145
1146 netdev = network_netdev(key, value, &lxc_conf->network);
1147 if (!netdev)
1148 return -1;
1149
1150 return set_config_string_item(&netdev->upscript, value);
1151 }
1152
1153 static int set_config_network_script_down(const char *key, const char *value,
1154 struct lxc_conf *lxc_conf)
1155 {
1156 struct lxc_netdev *netdev;
1157
1158 netdev = network_netdev(key, value, &lxc_conf->network);
1159 if (!netdev)
1160 return -1;
1161
1162 return set_config_string_item(&netdev->downscript, value);
1163 }
1164
1165 static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
1166 {
1167 struct lxc_list *hooklist;
1168
1169 hooklist = malloc(sizeof(*hooklist));
1170 if (!hooklist) {
1171 free(hook);
1172 return -1;
1173 }
1174 hooklist->elem = hook;
1175 lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
1176 return 0;
1177 }
1178
1179 static int set_config_seccomp(const char *key, const char *value,
1180 struct lxc_conf *lxc_conf)
1181 {
1182 return set_config_path_item(&lxc_conf->seccomp, value);
1183 }
1184
1185 static int set_config_init_cmd(const char *key, const char *value,
1186 struct lxc_conf *lxc_conf)
1187 {
1188 return set_config_path_item(&lxc_conf->init_cmd, value);
1189 }
1190
1191 static int set_config_init_uid(const char *key, const char *value,
1192 struct lxc_conf *lxc_conf)
1193 {
1194 unsigned int init_uid;
1195
1196 /* Set config value to default. */
1197 if (config_value_empty(value)) {
1198 lxc_conf->init_uid = 0;
1199 return 0;
1200 }
1201
1202 /* Parse new config value. */
1203 if (lxc_safe_uint(value, &init_uid) < 0)
1204 return -1;
1205 lxc_conf->init_uid = init_uid;
1206
1207 return 0;
1208 }
1209
1210 static int set_config_init_gid(const char *key, const char *value,
1211 struct lxc_conf *lxc_conf)
1212 {
1213 unsigned int init_gid;
1214
1215 /* Set config value to default. */
1216 if (config_value_empty(value)) {
1217 lxc_conf->init_gid = 0;
1218 return 0;
1219 }
1220
1221 /* Parse new config value. */
1222 if (lxc_safe_uint(value, &init_gid) < 0)
1223 return -1;
1224 lxc_conf->init_gid = init_gid;
1225
1226 return 0;
1227 }
1228
1229 static int set_config_hook(const char *key, const char *value,
1230 struct lxc_conf *lxc_conf)
1231 {
1232 char *copy;
1233
1234 if (config_value_empty(value))
1235 return lxc_clear_hooks(lxc_conf, key);
1236
1237 if (strcmp(key, "lxc.hook") == 0) {
1238 ERROR("lxc.hook cannot take a value");
1239 return -1;
1240 }
1241 copy = strdup(value);
1242 if (!copy) {
1243 SYSERROR("failed to dup string '%s'", value);
1244 return -1;
1245 }
1246 if (strcmp(key, "lxc.hook.pre-start") == 0)
1247 return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
1248 else if (strcmp(key, "lxc.hook.pre-mount") == 0)
1249 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
1250 else if (strcmp(key, "lxc.hook.autodev") == 0)
1251 return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
1252 else if (strcmp(key, "lxc.hook.mount") == 0)
1253 return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
1254 else if (strcmp(key, "lxc.hook.start") == 0)
1255 return add_hook(lxc_conf, LXCHOOK_START, copy);
1256 else if (strcmp(key, "lxc.hook.stop") == 0)
1257 return add_hook(lxc_conf, LXCHOOK_STOP, copy);
1258 else if (strcmp(key, "lxc.hook.post-stop") == 0)
1259 return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
1260 else if (strcmp(key, "lxc.hook.clone") == 0)
1261 return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
1262 else if (strcmp(key, "lxc.hook.destroy") == 0)
1263 return add_hook(lxc_conf, LXCHOOK_DESTROY, copy);
1264 SYSERROR("Unknown key: %s", key);
1265 free(copy);
1266 return -1;
1267 }
1268
1269 static int set_config_personality(const char *key, const char *value,
1270 struct lxc_conf *lxc_conf)
1271 {
1272 signed long personality = lxc_config_parse_arch(value);
1273
1274 if (personality >= 0)
1275 lxc_conf->personality = personality;
1276 else
1277 WARN("unsupported personality '%s'", value);
1278
1279 return 0;
1280 }
1281
1282 static int set_config_pts(const char *key, const char *value,
1283 struct lxc_conf *lxc_conf)
1284 {
1285 /* Set config value to default. */
1286 if (config_value_empty(value)) {
1287 lxc_conf->pts = 0;
1288 return 0;
1289 }
1290
1291 /* Parse new config value. */
1292 if (lxc_safe_uint(value, &lxc_conf->pts) < 0)
1293 return -1;
1294
1295 return 0;
1296 }
1297
1298 static int set_config_start(const char *key, const char *value,
1299 struct lxc_conf *lxc_conf)
1300 {
1301 bool is_empty;
1302
1303 is_empty = config_value_empty(value);
1304
1305 if (strcmp(key, "lxc.start.auto") == 0) {
1306 /* Set config value to default. */
1307 if (is_empty) {
1308 lxc_conf->start_auto = 0;
1309 return 0;
1310 }
1311
1312 /* Parse new config value. */
1313 if (lxc_safe_uint(value, &lxc_conf->start_auto) < 0)
1314 return -1;
1315
1316 if (lxc_conf->start_auto > 1)
1317 return -1;
1318
1319 return 0;
1320 } else if (strcmp(key, "lxc.start.delay") == 0) {
1321 /* Set config value to default. */
1322 if (is_empty) {
1323 lxc_conf->start_delay = 0;
1324 return 0;
1325 }
1326
1327 /* Parse new config value. */
1328 return lxc_safe_uint(value, &lxc_conf->start_delay);
1329 } else if (strcmp(key, "lxc.start.order") == 0) {
1330 /* Set config value to default. */
1331 if (is_empty) {
1332 lxc_conf->start_order = 0;
1333 return 0;
1334 }
1335
1336 /* Parse new config value. */
1337 return lxc_safe_int(value, &lxc_conf->start_order);
1338 }
1339
1340 SYSERROR("Unknown key: %s", key);
1341 return -1;
1342 }
1343
1344 static int set_config_monitor(const char *key, const char *value,
1345 struct lxc_conf *lxc_conf)
1346 {
1347 /* Set config value to default. */
1348 if (config_value_empty(value)) {
1349 lxc_conf->monitor_unshare = 0;
1350 return 0;
1351 }
1352
1353 /* Parse new config value. */
1354 if (strcmp(key, "lxc.monitor.unshare") == 0)
1355 return lxc_safe_uint(value, &lxc_conf->monitor_unshare);
1356
1357 SYSERROR("Unknown key: %s", key);
1358 return -1;
1359 }
1360
1361 static int set_config_group(const char *key, const char *value,
1362 struct lxc_conf *lxc_conf)
1363 {
1364 char *groups, *groupptr, *sptr, *token;
1365 struct lxc_list *grouplist;
1366 int ret = -1;
1367
1368 if (config_value_empty(value))
1369 return lxc_clear_groups(lxc_conf);
1370
1371 groups = strdup(value);
1372 if (!groups) {
1373 SYSERROR("failed to dup '%s'", value);
1374 return -1;
1375 }
1376
1377 /* in case several groups are specified in a single line
1378 * split these groups in a single element for the list */
1379 for (groupptr = groups;;groupptr = NULL) {
1380 token = strtok_r(groupptr, " \t", &sptr);
1381 if (!token) {
1382 ret = 0;
1383 break;
1384 }
1385
1386 grouplist = malloc(sizeof(*grouplist));
1387 if (!grouplist) {
1388 SYSERROR("failed to allocate groups list");
1389 break;
1390 }
1391
1392 grouplist->elem = strdup(token);
1393 if (!grouplist->elem) {
1394 SYSERROR("failed to dup '%s'", token);
1395 free(grouplist);
1396 break;
1397 }
1398
1399 lxc_list_add_tail(&lxc_conf->groups, grouplist);
1400 }
1401
1402 free(groups);
1403
1404 return ret;
1405 }
1406
1407 static int set_config_environment(const char *key, const char *value,
1408 struct lxc_conf *lxc_conf)
1409 {
1410 struct lxc_list *list_item = NULL;
1411
1412 if (config_value_empty(value))
1413 return lxc_clear_environment(lxc_conf);
1414
1415 list_item = malloc(sizeof(*list_item));
1416 if (!list_item)
1417 goto freak_out;
1418
1419 list_item->elem = strdup(value);
1420
1421 if (!list_item->elem)
1422 goto freak_out;
1423
1424 lxc_list_add_tail(&lxc_conf->environment, list_item);
1425
1426 return 0;
1427
1428 freak_out:
1429 free(list_item);
1430
1431 return -1;
1432 }
1433
1434 static int set_config_tty(const char *key, const char *value,
1435 struct lxc_conf *lxc_conf)
1436 {
1437 /* Set config value to default. */
1438 if (config_value_empty(value)) {
1439 lxc_conf->tty = 0;
1440 return 0;
1441 }
1442
1443 /* Parse new config value. */
1444 return lxc_safe_uint(value, &lxc_conf->tty);
1445 }
1446
1447 static int set_config_ttydir(const char *key, const char *value,
1448 struct lxc_conf *lxc_conf)
1449 {
1450 return set_config_string_item_max(&lxc_conf->ttydir, value, NAME_MAX+1);
1451 }
1452
1453 static int set_config_kmsg(const char *key, const char *value,
1454 struct lxc_conf *lxc_conf)
1455 {
1456 /* Set config value to default. */
1457 if (config_value_empty(value)) {
1458 lxc_conf->kmsg = 0;
1459 return 0;
1460 }
1461
1462 /* Parse new config value. */
1463 if (lxc_safe_uint(value, &lxc_conf->kmsg) < 0)
1464 return -1;
1465
1466 if (lxc_conf->kmsg > 1)
1467 return -1;
1468
1469 return 0;
1470 }
1471
1472 static int set_config_lsm_aa_profile(const char *key, const char *value,
1473 struct lxc_conf *lxc_conf)
1474 {
1475 return set_config_string_item(&lxc_conf->lsm_aa_profile, value);
1476 }
1477
1478 static int set_config_lsm_aa_incomplete(const char *key, const char *value,
1479 struct lxc_conf *lxc_conf)
1480 {
1481 /* Set config value to default. */
1482 if (config_value_empty(value)) {
1483 lxc_conf->lsm_aa_allow_incomplete = 0;
1484 return 0;
1485 }
1486
1487 /* Parse new config value. */
1488 if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete) < 0)
1489 return -1;
1490
1491 if (lxc_conf->lsm_aa_allow_incomplete > 1) {
1492 ERROR("Wrong value for lxc.lsm_aa_allow_incomplete. Can only "
1493 "be set to 0 or 1");
1494 return -1;
1495 }
1496
1497 return 0;
1498 }
1499
1500 static int set_config_lsm_se_context(const char *key, const char *value,
1501 struct lxc_conf *lxc_conf)
1502 {
1503 return set_config_string_item(&lxc_conf->lsm_se_context, value);
1504 }
1505
1506 static int set_config_logfile(const char *key, const char *value,
1507 struct lxc_conf *c)
1508 {
1509 int ret;
1510
1511 if (config_value_empty(value)) {
1512 free(c->logfile);
1513 c->logfile = NULL;
1514 return 0;
1515 }
1516
1517 /* Store these values in the lxc_conf, and then try to set for actual
1518 * current logging. */
1519 ret = set_config_path_item(&c->logfile, value);
1520 if (ret == 0)
1521 ret = lxc_log_set_file(&c->logfd, c->logfile);
1522 return ret;
1523 }
1524
1525 static int set_config_loglevel(const char *key, const char *value,
1526 struct lxc_conf *lxc_conf)
1527 {
1528 int newlevel;
1529
1530 /* Set config value to default. */
1531 if (config_value_empty(value)) {
1532 lxc_conf->loglevel = LXC_LOG_PRIORITY_NOTSET;
1533 return 0;
1534 }
1535
1536 /* Parse new config value. */
1537 if (value[0] >= '0' && value[0] <= '9') {
1538 if (lxc_safe_int(value, &newlevel) < 0)
1539 return -1;
1540 } else {
1541 newlevel = lxc_log_priority_to_int(value);
1542 }
1543
1544 /* store these values in the lxc_conf, and then try to set for actual
1545 * current logging.
1546 */
1547 lxc_conf->loglevel = newlevel;
1548 return lxc_log_set_level(&lxc_conf->loglevel, newlevel);
1549 }
1550
1551 static int set_config_autodev(const char *key, const char *value,
1552 struct lxc_conf *lxc_conf)
1553 {
1554 /* Set config value to default. */
1555 if (config_value_empty(value)) {
1556 lxc_conf->autodev = 0;
1557 return 0;
1558 }
1559
1560 /* Parse new config value. */
1561 if (lxc_safe_uint(value, &lxc_conf->autodev) < 0)
1562 return -1;
1563
1564 if (lxc_conf->autodev > 1) {
1565 ERROR("Wrong value for lxc.autodev. Can only be set to 0 or 1");
1566 return -1;
1567 }
1568
1569 return 0;
1570 }
1571
1572 static int sig_num(const char *sig)
1573 {
1574 unsigned int signum;
1575
1576 if (lxc_safe_uint(sig, &signum) < 0)
1577 return -1;
1578
1579 return signum;
1580 }
1581
1582 static int rt_sig_num(const char *signame)
1583 {
1584 int sig_n = 0;
1585 int rtmax = 0;
1586
1587 if (strncasecmp(signame, "max-", 4) == 0) {
1588 rtmax = 1;
1589 }
1590 signame += 4;
1591 if (!isdigit(*signame))
1592 return -1;
1593 sig_n = sig_num(signame);
1594 sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n;
1595 if (sig_n > SIGRTMAX || sig_n < SIGRTMIN)
1596 return -1;
1597 return sig_n;
1598 }
1599
1600 static int sig_parse(const char *signame) {
1601 size_t n;
1602
1603 if (isdigit(*signame)) {
1604 return sig_num(signame);
1605 } else if (strncasecmp(signame, "sig", 3) == 0) {
1606 signame += 3;
1607 if (strncasecmp(signame, "rt", 2) == 0)
1608 return rt_sig_num(signame + 2);
1609 for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
1610 if (strcasecmp (signames[n].name, signame) == 0)
1611 return signames[n].num;
1612 }
1613 }
1614 return -1;
1615 }
1616
1617 static int set_config_haltsignal(const char *key, const char *value,
1618 struct lxc_conf *lxc_conf)
1619 {
1620 int sig_n;
1621
1622 /* Set config value to default. */
1623 if (config_value_empty(value)) {
1624 lxc_conf->haltsignal = 0;
1625 return 0;
1626 }
1627
1628 /* Parse new config value. */
1629 sig_n = sig_parse(value);
1630
1631 if (sig_n < 0)
1632 return -1;
1633 lxc_conf->haltsignal = sig_n;
1634
1635 return 0;
1636 }
1637
1638 static int set_config_rebootsignal(const char *key, const char *value,
1639 struct lxc_conf *lxc_conf)
1640 {
1641 int sig_n;
1642
1643 /* Set config value to default. */
1644 if (config_value_empty(value)) {
1645 lxc_conf->rebootsignal = 0;
1646 return 0;
1647 }
1648
1649 /* Parse new config value. */
1650 sig_n = sig_parse(value);
1651 if (sig_n < 0)
1652 return -1;
1653 lxc_conf->rebootsignal = sig_n;
1654
1655 return 0;
1656 }
1657
1658 static int set_config_stopsignal(const char *key, const char *value,
1659 struct lxc_conf *lxc_conf)
1660 {
1661 int sig_n;
1662
1663 /* Set config value to default. */
1664 if (config_value_empty(value)) {
1665 lxc_conf->stopsignal = 0;
1666 return 0;
1667 }
1668
1669 /* Parse new config value. */
1670 sig_n = sig_parse(value);
1671 if (sig_n < 0)
1672 return -1;
1673 lxc_conf->stopsignal = sig_n;
1674
1675 return 0;
1676 }
1677
1678 static int set_config_cgroup(const char *key, const char *value,
1679 struct lxc_conf *lxc_conf)
1680 {
1681 char *token = "lxc.cgroup.";
1682 char *subkey;
1683 struct lxc_list *cglist = NULL;
1684 struct lxc_cgroup *cgelem = NULL;
1685
1686 if (config_value_empty(value))
1687 return lxc_clear_cgroups(lxc_conf, key);
1688
1689 subkey = strstr(key, token);
1690
1691 if (!subkey)
1692 return -1;
1693
1694 if (!strlen(subkey))
1695 return -1;
1696
1697 if (strlen(subkey) == strlen(token))
1698 return -1;
1699
1700 subkey += strlen(token);
1701
1702 cglist = malloc(sizeof(*cglist));
1703 if (!cglist)
1704 goto out;
1705
1706 cgelem = malloc(sizeof(*cgelem));
1707 if (!cgelem)
1708 goto out;
1709 memset(cgelem, 0, sizeof(*cgelem));
1710
1711 cgelem->subsystem = strdup(subkey);
1712 cgelem->value = strdup(value);
1713
1714 if (!cgelem->subsystem || !cgelem->value)
1715 goto out;
1716
1717 cglist->elem = cgelem;
1718
1719 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
1720
1721 return 0;
1722
1723 out:
1724 free(cglist);
1725
1726 if (cgelem) {
1727 free(cgelem->subsystem);
1728
1729 free(cgelem->value);
1730
1731 free(cgelem);
1732 }
1733
1734 return -1;
1735 }
1736
1737 static bool parse_limit_value(const char **value, unsigned long *res) {
1738 char *endptr = NULL;
1739
1740 if (strncmp(*value, "unlimited", sizeof("unlimited")-1) == 0) {
1741 *res = RLIM_INFINITY;
1742 *value += sizeof("unlimited")-1;
1743 return true;
1744 }
1745
1746 errno = 0;
1747 *res = strtoul(*value, &endptr, 10);
1748 if (errno || !endptr)
1749 return false;
1750 *value = endptr;
1751
1752 return true;
1753 }
1754
1755 static int set_config_limit(const char *key, const char *value,
1756 struct lxc_conf *lxc_conf)
1757 {
1758 struct lxc_list *limlist = NULL;
1759 struct lxc_limit *limelem = NULL;
1760 struct lxc_list *iter;
1761 struct rlimit limit;
1762 unsigned long limit_value;
1763
1764 if (config_value_empty(value))
1765 return lxc_clear_limits(lxc_conf, key);
1766
1767 if (strncmp(key, "lxc.limit.", sizeof("lxc.limit.")-1) != 0)
1768 return -1;
1769
1770 key += sizeof("lxc.limit.")-1;
1771
1772 /* soft limit comes first in the value */
1773 if (!parse_limit_value(&value, &limit_value))
1774 return -1;
1775 limit.rlim_cur = limit_value;
1776
1777 /* skip spaces and a colon */
1778 while (isspace(*value))
1779 ++value;
1780 if (*value == ':')
1781 ++value;
1782 else if (*value) /* any other character is an error here */
1783 return -1;
1784 while (isspace(*value))
1785 ++value;
1786
1787 /* optional hard limit */
1788 if (*value) {
1789 if (!parse_limit_value(&value, &limit_value))
1790 return -1;
1791 limit.rlim_max = limit_value;
1792 /* check for trailing garbage */
1793 while (isspace(*value))
1794 ++value;
1795 if (*value)
1796 return -1;
1797 } else {
1798 /* a single value sets both hard and soft limit */
1799 limit.rlim_max = limit.rlim_cur;
1800 }
1801
1802 /* find existing list element */
1803 lxc_list_for_each(iter, &lxc_conf->limits) {
1804 limelem = iter->elem;
1805 if (!strcmp(key, limelem->resource)) {
1806 limelem->limit = limit;
1807 return 0;
1808 }
1809 }
1810
1811 /* allocate list element */
1812 limlist = malloc(sizeof(*limlist));
1813 if (!limlist)
1814 goto out;
1815
1816 limelem = malloc(sizeof(*limelem));
1817 if (!limelem)
1818 goto out;
1819 memset(limelem, 0, sizeof(*limelem));
1820
1821 limelem->resource = strdup(key);
1822 if (!limelem->resource)
1823 goto out;
1824 limelem->limit = limit;
1825
1826 limlist->elem = limelem;
1827
1828 lxc_list_add_tail(&lxc_conf->limits, limlist);
1829
1830 return 0;
1831
1832 out:
1833 free(limlist);
1834 if (limelem) {
1835 free(limelem->resource);
1836 free(limelem);
1837 }
1838 return -1;
1839 }
1840
1841 static int set_config_idmaps(const char *key, const char *value,
1842 struct lxc_conf *lxc_conf)
1843 {
1844 unsigned long hostid, nsid, range;
1845 char type;
1846 char *window, *slide;
1847 char *dup = NULL;
1848 struct lxc_list *idmaplist = NULL;
1849 struct id_map *idmap = NULL;
1850
1851 if (config_value_empty(value))
1852 return lxc_clear_idmaps(lxc_conf);
1853
1854 idmaplist = malloc(sizeof(*idmaplist));
1855 if (!idmaplist)
1856 goto on_error;
1857
1858 idmap = malloc(sizeof(*idmap));
1859 if (!idmap)
1860 goto on_error;
1861 memset(idmap, 0, sizeof(*idmap));
1862
1863 /* Duplicate string. */
1864 dup = strdup(value);
1865 if (!dup)
1866 goto on_error;
1867
1868 /* A prototypical idmap entry would be: "0 1000 1000000 65536" */
1869
1870 /* align */
1871 slide = window = dup;
1872 /* skip whitespace */
1873 slide += strspn(slide, " \t\r");
1874 if (slide != window && *slide == '\0')
1875 goto on_error;
1876
1877 /* Validate type. */
1878 if (*slide != 'u' && *slide != 'g')
1879 goto on_error;
1880 /* Assign type. */
1881 type = *slide;
1882
1883 /* move beyond type */
1884 slide++;
1885 /* align */
1886 window = slide;
1887 /* Validate that only whitespace follows. */
1888 slide += strspn(slide, " \t\r");
1889 /* There must be whitespace. */
1890 if (slide == window)
1891 goto on_error;
1892
1893 /* Mark beginning of nsuid. */
1894 window = slide;
1895 /* Validate that non-whitespace follows. */
1896 slide += strcspn(slide, " \t\r");
1897 /* There must be non-whitespace. */
1898 if (slide == window || *slide == '\0')
1899 goto on_error;
1900 /* Mark end of nsuid. */
1901 *slide = '\0';
1902
1903 /* Parse nsuid. */
1904 if (lxc_safe_ulong(window, &nsid) < 0)
1905 goto on_error;
1906
1907 /* Move beyond \0. */
1908 slide++;
1909 /* align */
1910 window = slide;
1911 /* Validate that only whitespace follows. */
1912 slide += strspn(slide, " \t\r");
1913 /* If there was only one whitespace then we whiped it with our \0 above.
1914 * So only ensure that we're not at the end of the string.
1915 */
1916 if (*slide == '\0')
1917 goto on_error;
1918
1919 /* Mark beginning of hostid. */
1920 window = slide;
1921 /* Validate that non-whitespace follows. */
1922 slide += strcspn(slide, " \t\r");
1923 /* There must be non-whitespace. */
1924 if (slide == window || *slide == '\0')
1925 goto on_error;
1926 /* Mark end of nsuid. */
1927 *slide = '\0';
1928
1929 /* Parse hostid. */
1930 if (lxc_safe_ulong(window, &hostid) < 0)
1931 goto on_error;
1932
1933 /* Move beyond \0. */
1934 slide++;
1935 /* align */
1936 window = slide;
1937 /* Validate that only whitespace follows. */
1938 slide += strspn(slide, " \t\r");
1939 /* If there was only one whitespace then we whiped it with our \0 above.
1940 * So only ensure that we're not at the end of the string.
1941 */
1942 if (*slide == '\0')
1943 goto on_error;
1944
1945 /* Mark beginning of range. */
1946 window = slide;
1947 /* Validate that non-whitespace follows. */
1948 slide += strcspn(slide, " \t\r");
1949 /* There must be non-whitespace. */
1950 if (slide == window)
1951 goto on_error;
1952
1953 /* The range is the last valid entry we expect. So make sure that there
1954 * is not trailing garbage and if there is, error out.
1955 */
1956 if (*(slide + strspn(slide, " \t\r\n")) != '\0')
1957 goto on_error;
1958 /* Mark end of range. */
1959 *slide = '\0';
1960
1961 /* Parse range. */
1962 if (lxc_safe_ulong(window, &range) < 0)
1963 goto on_error;
1964
1965 /* Yay, we survived. */
1966 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
1967 if (type == 'u')
1968 idmap->idtype = ID_TYPE_UID;
1969 else if (type == 'g')
1970 idmap->idtype = ID_TYPE_GID;
1971 else
1972 goto on_error;
1973
1974 idmap->hostid = hostid;
1975 idmap->nsid = nsid;
1976 idmap->range = range;
1977 idmaplist->elem = idmap;
1978 lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
1979 idmap = NULL;
1980
1981 return 0;
1982
1983 on_error:
1984 free(idmaplist);
1985 free(idmap);
1986 free(dup);
1987
1988 return -1;
1989 }
1990
1991 static int set_config_fstab(const char *key, const char *value,
1992 struct lxc_conf *lxc_conf)
1993 {
1994 if (config_value_empty(value)) {
1995 lxc_clear_config_item(lxc_conf, key);
1996 return -1;
1997 }
1998
1999 return set_config_path_item(&lxc_conf->fstab, value);
2000 }
2001
2002 static int set_config_mount_auto(const char *key, const char *value,
2003 struct lxc_conf *lxc_conf)
2004 {
2005 char *autos, *autoptr, *sptr, *token;
2006 static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = {
2007 { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
2008 { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
2009 { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
2010 { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
2011 { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
2012 { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
2013 { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
2014 { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
2015 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
2016 { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
2017 { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
2018 { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
2019 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
2020 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
2021 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
2022 /* NB: For adding anything that is just a single on/off, but has
2023 * no options: keep mask and flag identical and just define the
2024 * enum value as an unused bit so far
2025 */
2026 { NULL, 0 }
2027 };
2028 int i;
2029 int ret = -1;
2030
2031 if (config_value_empty(value)) {
2032 lxc_conf->auto_mounts = 0;
2033 return 0;
2034 }
2035
2036 autos = strdup(value);
2037 if (!autos) {
2038 SYSERROR("failed to dup '%s'", value);
2039 return -1;
2040 }
2041
2042 for (autoptr = autos; ; autoptr = NULL) {
2043 token = strtok_r(autoptr, " \t", &sptr);
2044 if (!token) {
2045 ret = 0;
2046 break;
2047 }
2048
2049 for (i = 0; allowed_auto_mounts[i].token; i++) {
2050 if (!strcmp(allowed_auto_mounts[i].token, token))
2051 break;
2052 }
2053
2054 if (!allowed_auto_mounts[i].token) {
2055 ERROR("Invalid filesystem to automount: %s", token);
2056 break;
2057 }
2058
2059 lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
2060 lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
2061 }
2062
2063 free(autos);
2064
2065 return ret;
2066 }
2067
2068 static int set_config_mount(const char *key, const char *value,
2069 struct lxc_conf *lxc_conf)
2070 {
2071 char *mntelem;
2072 struct lxc_list *mntlist;
2073
2074 if (config_value_empty(value))
2075 return lxc_clear_mount_entries(lxc_conf);
2076
2077 mntlist = malloc(sizeof(*mntlist));
2078 if (!mntlist)
2079 return -1;
2080
2081 mntelem = strdup(value);
2082 if (!mntelem) {
2083 free(mntlist);
2084 return -1;
2085 }
2086 mntlist->elem = mntelem;
2087
2088 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
2089
2090 return 0;
2091 }
2092
2093 static int set_config_cap_keep(const char *key, const char *value,
2094 struct lxc_conf *lxc_conf)
2095 {
2096 char *keepcaps, *keepptr, *sptr, *token;
2097 struct lxc_list *keeplist;
2098 int ret = -1;
2099
2100 if (config_value_empty(value))
2101 return lxc_clear_config_keepcaps(lxc_conf);
2102
2103 keepcaps = strdup(value);
2104 if (!keepcaps) {
2105 SYSERROR("failed to dup '%s'", value);
2106 return -1;
2107 }
2108
2109 /* in case several capability keep is specified in a single line
2110 * split these caps in a single element for the list */
2111 for (keepptr = keepcaps;;keepptr = NULL) {
2112 token = strtok_r(keepptr, " \t", &sptr);
2113 if (!token) {
2114 ret = 0;
2115 break;
2116 }
2117
2118 if (!strcmp(token, "none"))
2119 lxc_clear_config_keepcaps(lxc_conf);
2120
2121 keeplist = malloc(sizeof(*keeplist));
2122 if (!keeplist) {
2123 SYSERROR("failed to allocate keepcap list");
2124 break;
2125 }
2126
2127 keeplist->elem = strdup(token);
2128 if (!keeplist->elem) {
2129 SYSERROR("failed to dup '%s'", token);
2130 free(keeplist);
2131 break;
2132 }
2133
2134 lxc_list_add_tail(&lxc_conf->keepcaps, keeplist);
2135 }
2136
2137 free(keepcaps);
2138
2139 return ret;
2140 }
2141
2142 static int set_config_cap_drop(const char *key, const char *value,
2143 struct lxc_conf *lxc_conf)
2144 {
2145 char *dropcaps, *dropptr, *sptr, *token;
2146 struct lxc_list *droplist;
2147 int ret = -1;
2148
2149 if (config_value_empty(value))
2150 return lxc_clear_config_caps(lxc_conf);
2151
2152 dropcaps = strdup(value);
2153 if (!dropcaps) {
2154 SYSERROR("failed to dup '%s'", value);
2155 return -1;
2156 }
2157
2158 /* in case several capability drop is specified in a single line
2159 * split these caps in a single element for the list */
2160 for (dropptr = dropcaps;;dropptr = NULL) {
2161 token = strtok_r(dropptr, " \t", &sptr);
2162 if (!token) {
2163 ret = 0;
2164 break;
2165 }
2166
2167 droplist = malloc(sizeof(*droplist));
2168 if (!droplist) {
2169 SYSERROR("failed to allocate drop list");
2170 break;
2171 }
2172
2173 droplist->elem = strdup(token);
2174 if (!droplist->elem) {
2175 SYSERROR("failed to dup '%s'", token);
2176 free(droplist);
2177 break;
2178 }
2179
2180 lxc_list_add_tail(&lxc_conf->caps, droplist);
2181 }
2182
2183 free(dropcaps);
2184
2185 return ret;
2186 }
2187
2188 static int set_config_console(const char *key, const char *value,
2189 struct lxc_conf *lxc_conf)
2190 {
2191 return set_config_path_item(&lxc_conf->console.path, value);
2192 }
2193
2194 static int set_config_console_logfile(const char *key, const char *value,
2195 struct lxc_conf *lxc_conf)
2196 {
2197 return set_config_path_item(&lxc_conf->console.log_path, value);
2198 }
2199
2200 /*
2201 * If we find a lxc.network.hwaddr in the original config file,
2202 * we expand it in the unexpanded_config, so that after a save_config
2203 * we store the hwaddr for re-use.
2204 * This is only called when reading the config file, not when executing
2205 * a lxc.include.
2206 * 'x' and 'X' are substituted in-place.
2207 */
2208 static void update_hwaddr(const char *line)
2209 {
2210 char *p;
2211
2212 line += lxc_char_left_gc(line, strlen(line));
2213 if (line[0] == '#')
2214 return;
2215 if (strncmp(line, "lxc.network.hwaddr", 18) != 0)
2216 return;
2217 p = strchr(line, '=');
2218 if (!p)
2219 return; // let config_network_hwaddr raise the error
2220 p++;
2221 while (isblank(*p))
2222 p++;
2223 if (!*p)
2224 return;
2225
2226 rand_complete_hwaddr(p);
2227 }
2228
2229 int append_unexp_config_line(const char *line, struct lxc_conf *conf)
2230 {
2231 size_t len = conf->unexpanded_len, linelen = strlen(line);
2232
2233 update_hwaddr(line);
2234
2235 while (conf->unexpanded_alloced <= len + linelen + 2) {
2236 char *tmp = realloc(conf->unexpanded_config, conf->unexpanded_alloced + 1024);
2237 if (!tmp)
2238 return -1;
2239 if (!conf->unexpanded_config)
2240 *tmp = '\0';
2241 conf->unexpanded_config = tmp;
2242 conf->unexpanded_alloced += 1024;
2243 }
2244 strcat(conf->unexpanded_config, line);
2245 conf->unexpanded_len += linelen;
2246 if (line[linelen-1] != '\n') {
2247 strcat(conf->unexpanded_config, "\n");
2248 conf->unexpanded_len++;
2249 }
2250 return 0;
2251 }
2252
2253 static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
2254 {
2255 struct dirent *direntp;
2256 DIR *dir;
2257 char path[MAXPATHLEN];
2258 int ret = -1, len;
2259
2260 dir = opendir(dirp);
2261 if (!dir) {
2262 SYSERROR("failed to open '%s'", dirp);
2263 return -1;
2264 }
2265
2266 while ((direntp = readdir(dir))) {
2267 const char *fnam;
2268 if (!direntp)
2269 break;
2270
2271 fnam = direntp->d_name;
2272 if (!strcmp(fnam, "."))
2273 continue;
2274
2275 if (!strcmp(fnam, ".."))
2276 continue;
2277
2278 len = strlen(fnam);
2279 if (len < 6 || strncmp(fnam+len-5, ".conf", 5) != 0)
2280 continue;
2281 len = snprintf(path, MAXPATHLEN, "%s/%s", dirp, fnam);
2282 if (len < 0 || len >= MAXPATHLEN) {
2283 ERROR("lxc.include filename too long under '%s'", dirp);
2284 ret = -1;
2285 goto out;
2286 }
2287
2288 ret = lxc_config_read(path, lxc_conf, true);
2289 if (ret < 0)
2290 goto out;
2291 }
2292 ret = 0;
2293
2294 out:
2295 if (closedir(dir))
2296 WARN("lxc.include dir: failed to close directory");
2297
2298 return ret;
2299 }
2300
2301 static int set_config_includefile(const char *key, const char *value,
2302 struct lxc_conf *lxc_conf)
2303 {
2304 /* Set config value to default. */
2305 if (config_value_empty(value)) {
2306 lxc_clear_config_item(lxc_conf, key);
2307 return 0;
2308 }
2309
2310 /* Parse new config value. */
2311 if (is_dir(value))
2312 return do_includedir(value, lxc_conf);
2313
2314 return lxc_config_read(value, lxc_conf, true);
2315 }
2316
2317 static int set_config_rootfs(const char *key, const char *value,
2318 struct lxc_conf *lxc_conf)
2319 {
2320 return set_config_path_item(&lxc_conf->rootfs.path, value);
2321 }
2322
2323 static int set_config_rootfs_mount(const char *key, const char *value,
2324 struct lxc_conf *lxc_conf)
2325 {
2326 return set_config_path_item(&lxc_conf->rootfs.mount, value);
2327 }
2328
2329 static int set_config_rootfs_options(const char *key, const char *value,
2330 struct lxc_conf *lxc_conf)
2331 {
2332 return set_config_string_item(&lxc_conf->rootfs.options, value);
2333 }
2334
2335 static int set_config_rootfs_backend(const char *key, const char *value,
2336 struct lxc_conf *lxc_conf)
2337 {
2338 if (config_value_empty(value)) {
2339 free(lxc_conf->rootfs.bdev_type);
2340 lxc_conf->rootfs.bdev_type = NULL;
2341 return 0;
2342 }
2343
2344 if (!is_valid_bdev_type(value)) {
2345 ERROR("Bad rootfs.backend: '%s'", value);
2346 return -1;
2347 }
2348
2349 return set_config_string_item(&lxc_conf->rootfs.bdev_type, value);
2350 }
2351
2352 static int set_config_pivotdir(const char *key, const char *value,
2353 struct lxc_conf *lxc_conf)
2354 {
2355 WARN("lxc.pivotdir is ignored. It will soon become an error.");
2356 return 0;
2357 }
2358
2359 static int set_config_utsname(const char *key, const char *value,
2360 struct lxc_conf *lxc_conf)
2361 {
2362 struct utsname *utsname;
2363
2364 if (config_value_empty(value)) {
2365 lxc_clear_config_item(lxc_conf, key);
2366 return 0;
2367 }
2368
2369 utsname = malloc(sizeof(*utsname));
2370 if (!utsname) {
2371 SYSERROR("failed to allocate memory");
2372 return -1;
2373 }
2374
2375 if (strlen(value) >= sizeof(utsname->nodename)) {
2376 ERROR("node name '%s' is too long", value);
2377 free(utsname);
2378 return -1;
2379 }
2380
2381 strcpy(utsname->nodename, value);
2382 free(lxc_conf->utsname);
2383 lxc_conf->utsname = utsname;
2384
2385 return 0;
2386 }
2387
2388 struct parse_line_conf {
2389 struct lxc_conf *conf;
2390 bool from_include;
2391 };
2392
2393 static int parse_line(char *buffer, void *data)
2394 {
2395 struct lxc_config_t *config;
2396 char *line, *linep;
2397 char *dot;
2398 char *key;
2399 char *value;
2400 int ret = 0;
2401 struct parse_line_conf *plc = data;
2402
2403 if (lxc_is_line_empty(buffer))
2404 return 0;
2405
2406 /* we have to dup the buffer otherwise, at the re-exec for
2407 * reboot we modified the original string on the stack by
2408 * replacing '=' by '\0' below
2409 */
2410 linep = line = strdup(buffer);
2411 if (!line) {
2412 SYSERROR("failed to allocate memory for '%s'", buffer);
2413 return -1;
2414 }
2415
2416 if (!plc->from_include)
2417 if ((ret = append_unexp_config_line(line, plc->conf)))
2418 goto out;
2419
2420 line += lxc_char_left_gc(line, strlen(line));
2421
2422 /* ignore comments */
2423 if (line[0] == '#')
2424 goto out;
2425
2426 /* martian option - don't add it to the config itself */
2427 if (strncmp(line, "lxc.", 4))
2428 goto out;
2429
2430 ret = -1;
2431
2432 dot = strstr(line, "=");
2433 if (!dot) {
2434 ERROR("invalid configuration line: %s", line);
2435 goto out;
2436 }
2437
2438 *dot = '\0';
2439 value = dot + 1;
2440
2441 key = line;
2442 key[lxc_char_right_gc(key, strlen(key))] = '\0';
2443
2444 value += lxc_char_left_gc(value, strlen(value));
2445 value[lxc_char_right_gc(value, strlen(value))] = '\0';
2446
2447 if (*value == '\'' || *value == '\"') {
2448 size_t len = strlen(value);
2449 if (len > 1 && value[len-1] == *value) {
2450 value[len-1] = '\0';
2451 value++;
2452 }
2453 }
2454
2455 config = lxc_getconfig(key);
2456 if (!config) {
2457 ERROR("unknown key %s", key);
2458 goto out;
2459 }
2460
2461 ret = config->set(key, value, plc->conf);
2462
2463 out:
2464 free(linep);
2465 return ret;
2466 }
2467
2468 static int lxc_config_readline(char *buffer, struct lxc_conf *conf)
2469 {
2470 struct parse_line_conf c;
2471
2472 c.conf = conf;
2473 c.from_include = false;
2474
2475 return parse_line(buffer, &c);
2476 }
2477
2478 int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
2479 {
2480 struct parse_line_conf c;
2481
2482 c.conf = conf;
2483 c.from_include = from_include;
2484
2485 if( access(file, R_OK) == -1 ) {
2486 return -1;
2487 }
2488
2489 /* Catch only the top level config file name in the structure */
2490 if(!conf->rcfile)
2491 conf->rcfile = strdup(file);
2492
2493 return lxc_file_for_each_line(file, parse_line, &c);
2494 }
2495
2496 int lxc_config_define_add(struct lxc_list *defines, char* arg)
2497 {
2498 struct lxc_list *dent;
2499
2500 dent = malloc(sizeof(struct lxc_list));
2501 if (!dent)
2502 return -1;
2503
2504 dent->elem = arg;
2505 lxc_list_add_tail(defines, dent);
2506 return 0;
2507 }
2508
2509 int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
2510 {
2511 struct lxc_list *it,*next;
2512 int ret = 0;
2513
2514 lxc_list_for_each(it, defines) {
2515 ret = lxc_config_readline(it->elem, conf);
2516 if (ret)
2517 break;
2518 }
2519
2520 lxc_list_for_each_safe(it, defines, next) {
2521 lxc_list_del(it);
2522 free(it);
2523 }
2524
2525 return ret;
2526 }
2527
2528 signed long lxc_config_parse_arch(const char *arch)
2529 {
2530 #if HAVE_SYS_PERSONALITY_H
2531 struct per_name {
2532 char *name;
2533 unsigned long per;
2534 } pername[] = {
2535 { "x86", PER_LINUX32 },
2536 { "linux32", PER_LINUX32 },
2537 { "i386", PER_LINUX32 },
2538 { "i486", PER_LINUX32 },
2539 { "i586", PER_LINUX32 },
2540 { "i686", PER_LINUX32 },
2541 { "athlon", PER_LINUX32 },
2542 { "mips", PER_LINUX32 },
2543 { "mipsel", PER_LINUX32 },
2544 { "ppc", PER_LINUX32 },
2545 { "arm", PER_LINUX32 },
2546 { "armv7l", PER_LINUX32 },
2547 { "armhf", PER_LINUX32 },
2548 { "armel", PER_LINUX32 },
2549 { "powerpc", PER_LINUX32 },
2550 { "linux64", PER_LINUX },
2551 { "x86_64", PER_LINUX },
2552 { "amd64", PER_LINUX },
2553 { "mips64", PER_LINUX },
2554 { "mips64el", PER_LINUX },
2555 { "ppc64", PER_LINUX },
2556 { "ppc64le", PER_LINUX },
2557 { "ppc64el", PER_LINUX },
2558 { "powerpc64", PER_LINUX },
2559 { "s390x", PER_LINUX },
2560 { "aarch64", PER_LINUX },
2561 { "arm64", PER_LINUX },
2562 };
2563 size_t len = sizeof(pername) / sizeof(pername[0]);
2564
2565 size_t i;
2566
2567 for (i = 0; i < len; i++) {
2568 if (!strcmp(pername[i].name, arch))
2569 return pername[i].per;
2570 }
2571 #endif
2572
2573 return -1;
2574 }
2575
2576 int lxc_fill_elevated_privileges(char *flaglist, int *flags)
2577 {
2578 char *token, *saveptr = NULL;
2579 int i, aflag;
2580 struct { const char *token; int flag; } all_privs[] = {
2581 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
2582 { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
2583 { "LSM", LXC_ATTACH_LSM_EXEC },
2584 { NULL, 0 }
2585 };
2586
2587 if (!flaglist) {
2588 /* for the sake of backward compatibility, drop all privileges
2589 if none is specified */
2590 for (i = 0; all_privs[i].token; i++) {
2591 *flags |= all_privs[i].flag;
2592 }
2593 return 0;
2594 }
2595
2596 token = strtok_r(flaglist, "|", &saveptr);
2597 while (token) {
2598 aflag = -1;
2599 for (i = 0; all_privs[i].token; i++) {
2600 if (!strcmp(all_privs[i].token, token))
2601 aflag = all_privs[i].flag;
2602 }
2603 if (aflag < 0)
2604 return -1;
2605
2606 *flags |= aflag;
2607
2608 token = strtok_r(NULL, "|", &saveptr);
2609 }
2610 return 0;
2611 }
2612
2613 static inline int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen,
2614 int v)
2615 {
2616 if (!retv)
2617 inlen = 0;
2618 else
2619 memset(retv, 0, inlen);
2620
2621 return snprintf(retv, inlen, "%d", v);
2622 }
2623
2624 /*
2625 * If you ask for a specific value, i.e. lxc.limit.nofile, then just the value
2626 * will be printed. If you ask for 'lxc.limit', then all limit entries will be
2627 * printed, in 'lxc.limit.resource = value' format.
2628 */
2629 static int lxc_get_limit_entry(struct lxc_conf *c, char *retv, int inlen,
2630 const char *key)
2631 {
2632 int fulllen = 0, len;
2633 int all = 0;
2634 struct lxc_list *it;
2635
2636 if (!retv)
2637 inlen = 0;
2638 else
2639 memset(retv, 0, inlen);
2640
2641 if (strcmp(key, "all") == 0)
2642 all = 1;
2643
2644 lxc_list_for_each(it, &c->limits) {
2645 char buf[LXC_NUMSTRLEN64*2+2]; /* 2 colon separated 64 bit integers or the word 'unlimited' */
2646 int partlen;
2647 struct lxc_limit *lim = it->elem;
2648
2649 if (lim->limit.rlim_cur == RLIM_INFINITY) {
2650 memcpy(buf, "unlimited", sizeof("unlimited"));
2651 partlen = sizeof("unlimited")-1;
2652 } else {
2653 partlen = sprintf(buf, "%"PRIu64, (uint64_t)lim->limit.rlim_cur);
2654 }
2655 if (lim->limit.rlim_cur != lim->limit.rlim_max) {
2656 if (lim->limit.rlim_max == RLIM_INFINITY) {
2657 memcpy(buf+partlen, ":unlimited", sizeof(":unlimited"));
2658 } else {
2659 sprintf(buf+partlen, ":%"PRIu64, (uint64_t)lim->limit.rlim_max);
2660 }
2661 }
2662
2663 if (all) {
2664 strprint(retv, inlen, "lxc.limit.%s = %s\n", lim->resource, buf);
2665 } else if (strcmp(lim->resource, key) == 0) {
2666 strprint(retv, inlen, "%s", buf);
2667 }
2668 }
2669
2670 return fulllen;
2671 }
2672
2673 static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
2674 const char *key)
2675 {
2676 char *subkey;
2677 int len, fulllen = 0, found = -1;
2678 struct lxc_list *it;
2679 int i;
2680
2681 /* "lxc.hook.mount" */
2682 subkey = strchr(key, '.');
2683 if (subkey) subkey = strchr(subkey+1, '.');
2684 if (!subkey)
2685 return -1;
2686 subkey++;
2687 if (!*subkey)
2688 return -1;
2689 for (i=0; i<NUM_LXC_HOOKS; i++) {
2690 if (strcmp(lxchook_names[i], subkey) == 0) {
2691 found=i;
2692 break;
2693 }
2694 }
2695 if (found == -1)
2696 return -1;
2697
2698 if (!retv)
2699 inlen = 0;
2700 else
2701 memset(retv, 0, inlen);
2702
2703 lxc_list_for_each(it, &c->hooks[found]) {
2704 strprint(retv, inlen, "%s\n", (char *)it->elem);
2705 }
2706 return fulllen;
2707 }
2708
2709 static int lxc_get_item_groups(struct lxc_conf *c, char *retv, int inlen)
2710 {
2711 int len, fulllen = 0;
2712 struct lxc_list *it;
2713
2714 if (!retv)
2715 inlen = 0;
2716 else
2717 memset(retv, 0, inlen);
2718
2719 lxc_list_for_each(it, &c->groups) {
2720 strprint(retv, inlen, "%s\n", (char *)it->elem);
2721 }
2722 return fulllen;
2723 }
2724
2725 static int lxc_get_item_environment(struct lxc_conf *c, char *retv, int inlen)
2726 {
2727 int len, fulllen = 0;
2728 struct lxc_list *it;
2729
2730 if (!retv)
2731 inlen = 0;
2732 else
2733 memset(retv, 0, inlen);
2734
2735 lxc_list_for_each(it, &c->environment) {
2736 strprint(retv, inlen, "%s\n", (char *)it->elem);
2737 }
2738 return fulllen;
2739 }
2740
2741 static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen)
2742 {
2743 int len, fulllen = 0;
2744 struct lxc_list *it;
2745
2746 if (!retv)
2747 inlen = 0;
2748 else
2749 memset(retv, 0, inlen);
2750
2751 lxc_list_for_each(it, &c->caps) {
2752 strprint(retv, inlen, "%s\n", (char *)it->elem);
2753 }
2754 return fulllen;
2755 }
2756
2757 static int lxc_get_item_cap_keep(struct lxc_conf *c, char *retv, int inlen)
2758 {
2759 int len, fulllen = 0;
2760 struct lxc_list *it;
2761
2762 if (!retv)
2763 inlen = 0;
2764 else
2765 memset(retv, 0, inlen);
2766
2767 lxc_list_for_each(it, &c->keepcaps) {
2768 strprint(retv, inlen, "%s\n", (char *)it->elem);
2769 }
2770 return fulllen;
2771 }
2772
2773 /*
2774 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
2775 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
2776 * ipv4.gateway, ipv6.gateway. ipvX.gateway can return 'auto' instead
2777 * of an address. ipv4 and ipv6 return lists (newline-separated).
2778 * things like veth.pair return '' if invalid (i.e. if called for vlan
2779 * type).
2780 */
2781 static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
2782 const char *key)
2783 {
2784 char *p1;
2785 int len, fulllen = 0;
2786 struct lxc_netdev *netdev;
2787
2788 if (!retv)
2789 inlen = 0;
2790 else
2791 memset(retv, 0, inlen);
2792
2793 p1 = strchr(key, '.');
2794 if (!p1 || *(p1+1) == '\0') return -1;
2795 p1++;
2796
2797 netdev = get_netdev_from_key(key, &c->network);
2798 if (!netdev)
2799 return -1;
2800 if (strcmp(p1, "name") == 0) {
2801 if (netdev->name)
2802 strprint(retv, inlen, "%s", netdev->name);
2803 } else if (strcmp(p1, "type") == 0) {
2804 strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type));
2805 } else if (strcmp(p1, "link") == 0) {
2806 if (netdev->link)
2807 strprint(retv, inlen, "%s", netdev->link);
2808 } else if (strcmp(p1, "flags") == 0) {
2809 if (netdev->flags & IFF_UP)
2810 strprint(retv, inlen, "up");
2811 } else if (strcmp(p1, "script.up") == 0) {
2812 if (netdev->upscript)
2813 strprint(retv, inlen, "%s", netdev->upscript);
2814 } else if (strcmp(p1, "script.down") == 0) {
2815 if (netdev->downscript)
2816 strprint(retv, inlen, "%s", netdev->downscript);
2817 } else if (strcmp(p1, "hwaddr") == 0) {
2818 if (netdev->hwaddr)
2819 strprint(retv, inlen, "%s", netdev->hwaddr);
2820 } else if (strcmp(p1, "mtu") == 0) {
2821 if (netdev->mtu)
2822 strprint(retv, inlen, "%s", netdev->mtu);
2823 } else if (strcmp(p1, "macvlan.mode") == 0) {
2824 if (netdev->type == LXC_NET_MACVLAN) {
2825 const char *mode;
2826 switch (netdev->priv.macvlan_attr.mode) {
2827 case MACVLAN_MODE_PRIVATE: mode = "private"; break;
2828 case MACVLAN_MODE_VEPA: mode = "vepa"; break;
2829 case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
2830 case MACVLAN_MODE_PASSTHRU: mode = "passthru"; break;
2831 default: mode = "(invalid)"; break;
2832 }
2833 strprint(retv, inlen, "%s", mode);
2834 }
2835 } else if (strcmp(p1, "veth.pair") == 0) {
2836 if (netdev->type == LXC_NET_VETH) {
2837 strprint(retv, inlen, "%s",
2838 netdev->priv.veth_attr.pair ?
2839 netdev->priv.veth_attr.pair :
2840 netdev->priv.veth_attr.veth1);
2841 }
2842 } else if (strcmp(p1, "vlan") == 0) {
2843 if (netdev->type == LXC_NET_VLAN) {
2844 strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
2845 }
2846 } else if (strcmp(p1, "ipv4.gateway") == 0) {
2847 if (netdev->ipv4_gateway_auto) {
2848 strprint(retv, inlen, "auto");
2849 } else if (netdev->ipv4_gateway) {
2850 char buf[INET_ADDRSTRLEN];
2851 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
2852 strprint(retv, inlen, "%s", buf);
2853 }
2854 } else if (strcmp(p1, "ipv4") == 0) {
2855 struct lxc_list *it2;
2856 lxc_list_for_each(it2, &netdev->ipv4) {
2857 struct lxc_inetdev *i = it2->elem;
2858 char buf[INET_ADDRSTRLEN];
2859 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
2860 strprint(retv, inlen, "%s/%d\n", buf, i->prefix);
2861 }
2862 } else if (strcmp(p1, "ipv6.gateway") == 0) {
2863 if (netdev->ipv6_gateway_auto) {
2864 strprint(retv, inlen, "auto");
2865 } else if (netdev->ipv6_gateway) {
2866 char buf[INET6_ADDRSTRLEN];
2867 inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
2868 strprint(retv, inlen, "%s", buf);
2869 }
2870 } else if (strcmp(p1, "ipv6") == 0) {
2871 struct lxc_list *it2;
2872 lxc_list_for_each(it2, &netdev->ipv6) {
2873 struct lxc_inet6dev *i = it2->elem;
2874 char buf[INET6_ADDRSTRLEN];
2875 inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
2876 strprint(retv, inlen, "%s/%d\n", buf, i->prefix);
2877 }
2878 }
2879 return fulllen;
2880 }
2881
2882 static int lxc_get_item_network(struct lxc_conf *c, char *retv, int inlen)
2883 {
2884 int len, fulllen = 0;
2885 struct lxc_list *it;
2886
2887 if (!retv)
2888 inlen = 0;
2889 else
2890 memset(retv, 0, inlen);
2891
2892 lxc_list_for_each(it, &c->network) {
2893 struct lxc_netdev *n = it->elem;
2894 const char *t = lxc_net_type_to_str(n->type);
2895 strprint(retv, inlen, "%s\n", t ? t : "(invalid)");
2896 }
2897 return fulllen;
2898 }
2899
2900 int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
2901 int inlen)
2902 {
2903 const char *v = NULL;
2904
2905 if (strcmp(key, "lxc.utsname") == 0)
2906 v = c->utsname ? c->utsname->nodename : NULL;
2907 else if (strcmp(key, "lxc.console.logfile") == 0)
2908 v = c->console.log_path;
2909 else if (strcmp(key, "lxc.console") == 0)
2910 v = c->console.path;
2911 else if (strcmp(key, "lxc.rootfs.backend") == 0)
2912 v = c->rootfs.bdev_type;
2913 else if (strcmp(key, "lxc.cap.drop") == 0)
2914 return lxc_get_item_cap_drop(c, retv, inlen);
2915 else if (strcmp(key, "lxc.cap.keep") == 0)
2916 return lxc_get_item_cap_keep(c, retv, inlen);
2917 else if (strncmp(key, "lxc.hook", 8) == 0)
2918 return lxc_get_item_hooks(c, retv, inlen, key);
2919 else if (strcmp(key, "lxc.network") == 0)
2920 return lxc_get_item_network(c, retv, inlen);
2921 else if (strncmp(key, "lxc.network.", 12) == 0)
2922 return lxc_get_item_nic(c, retv, inlen, key + 12);
2923 else if (strcmp(key, "lxc.start.auto") == 0)
2924 return lxc_get_conf_int(c, retv, inlen, c->start_auto);
2925 else if (strcmp(key, "lxc.start.delay") == 0)
2926 return lxc_get_conf_int(c, retv, inlen, c->start_delay);
2927 else if (strcmp(key, "lxc.start.order") == 0)
2928 return lxc_get_conf_int(c, retv, inlen, c->start_order);
2929 else if (strcmp(key, "lxc.monitor.unshare") == 0)
2930 return lxc_get_conf_int(c, retv, inlen, c->monitor_unshare);
2931 else if (strcmp(key, "lxc.group") == 0)
2932 return lxc_get_item_groups(c, retv, inlen);
2933 else if (strcmp(key, "lxc.seccomp") == 0)
2934 v = c->seccomp;
2935 else if (strcmp(key, "lxc.environment") == 0)
2936 return lxc_get_item_environment(c, retv, inlen);
2937 else if (strcmp(key, "lxc.init_cmd") == 0)
2938 v = c->init_cmd;
2939 else if (strcmp(key, "lxc.init_uid") == 0)
2940 return lxc_get_conf_int(c, retv, inlen, c->init_uid);
2941 else if (strcmp(key, "lxc.init_gid") == 0)
2942 return lxc_get_conf_int(c, retv, inlen, c->init_gid);
2943 else if (strcmp(key, "lxc.ephemeral") == 0)
2944 return lxc_get_conf_int(c, retv, inlen, c->ephemeral);
2945 else if (strcmp(key, "lxc.syslog") == 0)
2946 v = c->syslog;
2947 else if (strcmp(key, "lxc.no_new_privs") == 0)
2948 return lxc_get_conf_int(c, retv, inlen, c->no_new_privs);
2949 else if (strcmp(key, "lxc.limit") == 0) // all limits
2950 return lxc_get_limit_entry(c, retv, inlen, "all");
2951 else if (strncmp(key, "lxc.limit.", 10) == 0) // specific limit
2952 return lxc_get_limit_entry(c, retv, inlen, key + 10);
2953 else if (strcmp(key, "lxc.haltsignal") == 0)
2954 return lxc_get_conf_int(c, retv, inlen, c->haltsignal);
2955 else if (strcmp(key, "lxc.rebootsignal") == 0)
2956 return lxc_get_conf_int(c, retv, inlen, c->rebootsignal);
2957 else if (strcmp(key, "lxc.stopsignal") == 0)
2958 return lxc_get_conf_int(c, retv, inlen, c->stopsignal);
2959 else if (strcmp(key, "lxc.autodev") == 0)
2960 return lxc_get_conf_int(c, retv, inlen, c->autodev);
2961 else return -1;
2962
2963 if (!v)
2964 return 0;
2965 if (retv && inlen >= strlen(v) + 1)
2966 strncpy(retv, v, strlen(v)+1);
2967 return strlen(v);
2968 }
2969
2970 int lxc_clear_config_item(struct lxc_conf *c, const char *key)
2971 {
2972 int ret = 0;
2973
2974 if (strcmp(key, "lxc.network") == 0) {
2975 ret = lxc_clear_config_network(c);
2976
2977 } else if (strncmp(key, "lxc.network.", 12) == 0) {
2978 ret = lxc_clear_nic(c, key + 12);
2979
2980 } else if (strcmp(key, "lxc.cap.drop") == 0) {
2981 ret = lxc_clear_config_caps(c);
2982
2983 } else if (strcmp(key, "lxc.cap.keep") == 0) {
2984 ret = lxc_clear_config_keepcaps(c);
2985
2986 } else if (strncmp(key, "lxc.cgroup", 10) == 0) {
2987 ret = lxc_clear_cgroups(c, key);
2988
2989 } else if (strcmp(key, "lxc.mount.entry") == 0) {
2990 ret = lxc_clear_mount_entries(c);
2991
2992 } else if (strcmp(key, "lxc.mount.auto") == 0) {
2993 ret = lxc_clear_automounts(c);
2994
2995 } else if (strncmp(key, "lxc.hook", 8) == 0) {
2996 ret = lxc_clear_hooks(c, key);
2997
2998 } else if (strncmp(key, "lxc.group", 9) == 0) {
2999 ret = lxc_clear_groups(c);
3000
3001 } else if (strncmp(key, "lxc.environment", 15) == 0) {
3002 ret = lxc_clear_environment(c);
3003
3004 } else if (strncmp(key, "lxc.id_map", 10) == 0) {
3005 ret = lxc_clear_idmaps(c);
3006
3007 } else if (strncmp(key, "lxc.limit", 9) == 0) {
3008 ret = lxc_clear_limits(c, key);
3009
3010 } else if (strcmp(key, "lxc.utsname") == 0) {
3011 free(c->utsname);
3012 c->utsname = NULL;
3013
3014 } else if (strcmp(key, "lxc.arch") == 0) {
3015 c->personality = -1;
3016
3017 } else if (strcmp(key, "lxc.haltsignal") == 0) {
3018 c->haltsignal = 0;
3019
3020 } else if (strcmp(key, "lxc.rebootsignal") == 0) {
3021 c->rebootsignal = 0;
3022
3023 } else if (strcmp(key, "lxc.stopsignal") == 0) {
3024 c->stopsignal = 0;
3025
3026 } else if (strcmp(key, "lxc.init_cmd") == 0) {
3027 free(c->init_cmd);
3028 c->init_cmd = NULL;
3029
3030 } else if (strcmp(key, "lxc.init_uid") == 0) {
3031 c->init_uid = 0;
3032
3033 } else if (strcmp(key, "lxc.init_gid") == 0) {
3034 c->init_gid = 0;
3035
3036 } else if (strcmp(key, "lxc.ephemeral") == 0) {
3037 c->ephemeral = 0;
3038
3039 } else if (strcmp(key, "lxc.console.logfile") == 0) {
3040 free(c->console.log_path);
3041 c->console.log_path = NULL;
3042
3043 } else if (strcmp(key, "lxc.console") == 0) {
3044 free(c->console.path);
3045 c->console.path = NULL;
3046
3047 } else if (strcmp(key, "lxc.tty") == 0) {
3048 c->tty = 0;
3049
3050 } else if (strcmp(key, "lxc.devttydir") == 0) {
3051 free(c->ttydir);
3052 c->ttydir = NULL;
3053
3054 } else if (strcmp(key, "lxc.autodev") == 0) {
3055 c->autodev = 1;
3056
3057 } else if (strcmp(key, "lxc.kmsg") == 0) {
3058 c->kmsg = 0;
3059
3060 } else if (strcmp(key, "lxc.mount") == 0) {
3061 free(c->fstab);
3062 c->fstab = NULL;
3063
3064 } else if (strcmp(key, "lxc.rootfs") == 0) {
3065 free(c->rootfs.path);
3066 c->rootfs.path = NULL;
3067
3068 } else if (strcmp(key, "lxc.rootfs.mount") == 0) {
3069 free(c->rootfs.mount);
3070 c->rootfs.mount = NULL;
3071
3072 } else if (strcmp(key, "lxc.rootfs.options") == 0) {
3073 free(c->rootfs.options);
3074 c->rootfs.options = NULL;
3075
3076 } else if (strcmp(key, "lxc.rootfs.backend") == 0) {
3077 free(c->rootfs.bdev_type);
3078 c->rootfs.bdev_type = NULL;
3079
3080 } else if (strcmp(key, "lxc.aa_profile") == 0) {
3081 free(c->lsm_aa_profile);
3082 c->lsm_aa_profile = NULL;
3083
3084 } else if (strcmp(key, "lxc.aa_allow_incomplete") == 0) {
3085 c->lsm_aa_allow_incomplete = 0;
3086
3087 } else if (strcmp(key, "lxc.se_context") == 0) {
3088 free(c->lsm_se_context);
3089 c->lsm_se_context = NULL;
3090
3091 } else if (strcmp(key, "lxc.seccomp") == 0) {
3092 free(c->seccomp);
3093 c->seccomp = NULL;
3094
3095 } else if (strcmp(key, "lxc.loglevel") == 0) {
3096 c->loglevel = LXC_LOG_PRIORITY_NOTSET;
3097
3098 } else if (strcmp(key, "lxc.logfile") == 0) {
3099 free(c->logfile);
3100 c->logfile = NULL;
3101
3102 } else if (strcmp(key, "lxc.monitor.unshare") == 0) {
3103 c->monitor_unshare = 0;
3104
3105 } else if (strcmp(key, "lxc.pts") == 0) {
3106 c->pts = 0;
3107
3108 } else if (strcmp(key, "lxc.include") == 0) {
3109 lxc_clear_includes(c);
3110
3111 } else if (strcmp(key, "lxc.syslog") == 0) {
3112 free(c->syslog);
3113 c->syslog = NULL;
3114 } else {
3115 ret = -1;
3116 }
3117
3118 return ret;
3119 }
3120
3121 /*
3122 * writing out a confile.
3123 */
3124 void write_config(FILE *fout, struct lxc_conf *c)
3125 {
3126 size_t len = c->unexpanded_len;
3127 int ret;
3128
3129 if (!len)
3130 return;
3131 ret = fwrite(c->unexpanded_config, 1, len, fout);
3132 if (ret != len)
3133 SYSERROR("Error writing configuration file");
3134 }
3135
3136 bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, const char *v)
3137 {
3138 int ret;
3139 size_t len;
3140 char *tmp;
3141
3142 len = strlen(key) + strlen(v) + 4;
3143 tmp = alloca(len);
3144
3145 if (config_value_empty(v))
3146 ret = snprintf(tmp, len, "%s =", key);
3147 else
3148 ret = snprintf(tmp, len, "%s = %s", key, v);
3149 if (ret < 0 || ret >= len)
3150 return false;
3151
3152 /* Save the line verbatim into unexpanded_conf */
3153 if (append_unexp_config_line(tmp, conf))
3154 return false;
3155
3156 return true;
3157 }
3158
3159 void clear_unexp_config_line(struct lxc_conf *conf, const char *key, bool rm_subkeys)
3160 {
3161 char *lstart = conf->unexpanded_config, *lend;
3162
3163 if (!conf->unexpanded_config)
3164 return;
3165 while (*lstart) {
3166 lend = strchr(lstart, '\n');
3167 char v;
3168 if (!lend)
3169 lend = lstart + strlen(lstart);
3170 else
3171 lend++;
3172 if (strncmp(lstart, key, strlen(key)) != 0) {
3173 lstart = lend;
3174 continue;
3175 }
3176 if (!rm_subkeys) {
3177 v = lstart[strlen(key)];
3178 if (!isspace(v) && v != '=') {
3179 lstart = lend;
3180 continue;
3181 }
3182 }
3183 conf->unexpanded_len -= (lend - lstart);
3184 if (*lend == '\0') {
3185 *lstart = '\0';
3186 return;
3187 }
3188 memmove(lstart, lend, strlen(lend)+1);
3189 }
3190 }
3191
3192 bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
3193 const char *newpath, const char *oldname,
3194 const char *newname, const char *ovldir)
3195 {
3196 const char *key = "lxc.mount.entry";
3197 int ret;
3198 char *lstart = conf->unexpanded_config;
3199 char *lend;
3200 char *p;
3201 char *q;
3202 size_t newdirlen = strlen(ovldir) + strlen(newpath) + strlen(newname) + 2;
3203 size_t olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 2;
3204 char *olddir = alloca(olddirlen + 1);
3205 char *newdir = alloca(newdirlen + 1);
3206
3207 ret = snprintf(olddir, olddirlen + 1, "%s=%s/%s", ovldir, oldpath, oldname);
3208 if (ret < 0 || ret >= olddirlen + 1) {
3209 ERROR("Bug in %s", __func__);
3210 return false;
3211 }
3212 ret = snprintf(newdir, newdirlen + 1, "%s=%s/%s", ovldir, newpath, newname);
3213 if (ret < 0 || ret >= newdirlen + 1) {
3214 ERROR("Bug in %s", __func__);
3215 return false;
3216 }
3217 if (!conf->unexpanded_config)
3218 return true;
3219 while (*lstart) {
3220 lend = strchr(lstart, '\n');
3221 if (!lend)
3222 lend = lstart + strlen(lstart);
3223 else
3224 lend++;
3225 if (strncmp(lstart, key, strlen(key)) != 0)
3226 goto next;
3227 p = strchr(lstart + strlen(key), '=');
3228 if (!p)
3229 goto next;
3230 p++;
3231 while (isblank(*p))
3232 p++;
3233 if (p >= lend)
3234 goto next;
3235 /* Whenever an lxc.mount.entry entry is found in a line we check
3236 * if the substring " overlay" or the substring " aufs" is
3237 * present before doing any further work. We check for "
3238 * overlay" and " aufs" since both substrings need to have at
3239 * least one space before them in a valid overlay
3240 * lxc.mount.entry (/A B overlay). When the space before is
3241 * missing it is very likely that these substrings are part of a
3242 * path or something else. (Checking q >= lend ensures that we
3243 * only count matches in the current line.) */
3244 if ((!(q = strstr(p, " overlay")) || q >= lend) && (!(q = strstr(p, " aufs")) || q >= lend))
3245 goto next;
3246 if (!(q = strstr(p, olddir)) || (q >= lend))
3247 goto next;
3248
3249 /* replace the olddir with newdir */
3250 if (olddirlen >= newdirlen) {
3251 size_t diff = olddirlen - newdirlen;
3252 memcpy(q, newdir, newdirlen);
3253 if (olddirlen != newdirlen) {
3254 memmove(q + newdirlen, q + newdirlen + diff,
3255 strlen(q) - newdirlen - diff + 1);
3256 lend -= diff;
3257 conf->unexpanded_len -= diff;
3258 }
3259 } else {
3260 char *new;
3261 size_t diff = newdirlen - olddirlen;
3262 size_t oldlen = conf->unexpanded_len;
3263 size_t newlen = oldlen + diff;
3264 size_t poffset = q - conf->unexpanded_config;
3265 new = realloc(conf->unexpanded_config, newlen + 1);
3266 if (!new) {
3267 ERROR("Out of memory");
3268 return false;
3269 }
3270 conf->unexpanded_len = newlen;
3271 conf->unexpanded_alloced = newlen + 1;
3272 new[newlen - 1] = '\0';
3273 lend = new + (lend - conf->unexpanded_config);
3274 /* move over the remainder to make room for the newdir */
3275 memmove(new + poffset + newdirlen,
3276 new + poffset + olddirlen,
3277 oldlen - poffset - olddirlen + 1);
3278 conf->unexpanded_config = new;
3279 memcpy(new + poffset, newdir, newdirlen);
3280 lend += diff;
3281 }
3282 next:
3283 lstart = lend;
3284 }
3285 return true;
3286 }
3287
3288 bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
3289 const char *newpath, const char *oldname,
3290 const char *newname)
3291 {
3292 const char *key = "lxc.hook";
3293 int ret;
3294 char *lstart = conf->unexpanded_config, *lend, *p;
3295 size_t newdirlen = strlen(newpath) + strlen(newname) + 1;
3296 size_t olddirlen = strlen(oldpath) + strlen(oldname) + 1;
3297 char *olddir = alloca(olddirlen + 1);
3298 char *newdir = alloca(newdirlen + 1);
3299
3300 ret = snprintf(olddir, olddirlen + 1, "%s/%s", oldpath, oldname);
3301 if (ret < 0 || ret >= olddirlen + 1) {
3302 ERROR("Bug in %s", __func__);
3303 return false;
3304 }
3305 ret = snprintf(newdir, newdirlen + 1, "%s/%s", newpath, newname);
3306 if (ret < 0 || ret >= newdirlen + 1) {
3307 ERROR("Bug in %s", __func__);
3308 return false;
3309 }
3310 if (!conf->unexpanded_config)
3311 return true;
3312 while (*lstart) {
3313 lend = strchr(lstart, '\n');
3314 if (!lend)
3315 lend = lstart + strlen(lstart);
3316 else
3317 lend++;
3318 if (strncmp(lstart, key, strlen(key)) != 0)
3319 goto next;
3320 p = strchr(lstart + strlen(key), '=');
3321 if (!p)
3322 goto next;
3323 p++;
3324 while (isblank(*p))
3325 p++;
3326 if (p >= lend)
3327 goto next;
3328 if (strncmp(p, olddir, strlen(olddir)) != 0)
3329 goto next;
3330 /* replace the olddir with newdir */
3331 if (olddirlen >= newdirlen) {
3332 size_t diff = olddirlen - newdirlen;
3333 memcpy(p, newdir, newdirlen);
3334 if (olddirlen != newdirlen) {
3335 memmove(p + newdirlen, p + newdirlen + diff,
3336 strlen(p) - newdirlen - diff + 1);
3337 lend -= diff;
3338 conf->unexpanded_len -= diff;
3339 }
3340 } else {
3341 char *new;
3342 size_t diff = newdirlen - olddirlen;
3343 size_t oldlen = conf->unexpanded_len;
3344 size_t newlen = oldlen + diff;
3345 size_t poffset = p - conf->unexpanded_config;
3346 new = realloc(conf->unexpanded_config, newlen + 1);
3347 if (!new) {
3348 ERROR("Out of memory");
3349 return false;
3350 }
3351 conf->unexpanded_len = newlen;
3352 conf->unexpanded_alloced = newlen + 1;
3353 new[newlen - 1] = '\0';
3354 lend = new + (lend - conf->unexpanded_config);
3355 /* move over the remainder to make room for the newdir */
3356 memmove(new + poffset + newdirlen,
3357 new + poffset + olddirlen,
3358 oldlen - poffset - olddirlen + 1);
3359 conf->unexpanded_config = new;
3360 memcpy(new + poffset, newdir, newdirlen);
3361 lend += diff;
3362 }
3363 next:
3364 lstart = lend;
3365 }
3366 return true;
3367 }
3368
3369 #define DO(cmd) { \
3370 if (!(cmd)) { \
3371 ERROR("Error writing to new config"); \
3372 return false; \
3373 } \
3374 }
3375
3376 static bool new_hwaddr(char *hwaddr)
3377 {
3378 int ret;
3379
3380 (void)randseed(true);
3381
3382 ret = snprintf(hwaddr, 18, "00:16:3e:%02x:%02x:%02x", rand() % 255,
3383 rand() % 255, rand() % 255);
3384 if (ret < 0 || ret >= 18) {
3385 SYSERROR("Failed to call snprintf().");
3386 return false;
3387 }
3388
3389 return true;
3390 }
3391
3392 /*
3393 * This is called only from clone.
3394 * We wish to update all hwaddrs in the unexpanded config file. We
3395 * can't/don't want to update any which come from lxc.includes (there
3396 * shouldn't be any).
3397 * We can't just walk the c->lxc-conf->network list because that includes
3398 * netifs from the include files. So we update the ones which we find in
3399 * the unexp config file, then find the original macaddr in the
3400 * conf->network, and update that to the same value.
3401 */
3402 bool network_new_hwaddrs(struct lxc_conf *conf)
3403 {
3404 struct lxc_list *it;
3405
3406 const char *key = "lxc.network.hwaddr";
3407 char *lstart = conf->unexpanded_config, *lend, *p, *p2;
3408
3409 if (!conf->unexpanded_config)
3410 return true;
3411
3412 while (*lstart) {
3413 char newhwaddr[18], oldhwaddr[17];
3414
3415 lend = strchr(lstart, '\n');
3416 if (!lend)
3417 lend = lstart + strlen(lstart);
3418 else
3419 lend++;
3420
3421 if (strncmp(lstart, key, strlen(key)) != 0) {
3422 lstart = lend;
3423 continue;
3424 }
3425
3426 p = strchr(lstart+strlen(key), '=');
3427 if (!p) {
3428 lstart = lend;
3429 continue;
3430 }
3431
3432 p++;
3433 while (isblank(*p))
3434 p++;
3435 if (!*p)
3436 return true;
3437
3438 p2 = p;
3439 while (*p2 && !isblank(*p2) && *p2 != '\n')
3440 p2++;
3441 if (p2-p != 17) {
3442 WARN("Bad hwaddr entry");
3443 lstart = lend;
3444 continue;
3445 }
3446
3447 memcpy(oldhwaddr, p, 17);
3448
3449 if (!new_hwaddr(newhwaddr))
3450 return false;
3451
3452 memcpy(p, newhwaddr, 17);
3453 lxc_list_for_each(it, &conf->network) {
3454 struct lxc_netdev *n = it->elem;
3455 if (n->hwaddr && memcmp(oldhwaddr, n->hwaddr, 17) == 0)
3456 memcpy(n->hwaddr, newhwaddr, 17);
3457 }
3458
3459 lstart = lend;
3460 }
3461
3462 return true;
3463 }
3464
3465 static int set_config_ephemeral(const char *key, const char *value,
3466 struct lxc_conf *lxc_conf)
3467 {
3468 /* Set config value to default. */
3469 if (config_value_empty(value)) {
3470 lxc_conf->ephemeral = 0;
3471 return 0;
3472 }
3473
3474 /* Parse new config value. */
3475 if (lxc_safe_uint(value, &lxc_conf->ephemeral) < 0)
3476 return -1;
3477
3478 if (lxc_conf->ephemeral > 1) {
3479 ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
3480 return -1;
3481 }
3482
3483 return 0;
3484 }
3485
3486 static int set_config_syslog(const char *key, const char *value,
3487 struct lxc_conf *lxc_conf)
3488 {
3489 int facility;
3490
3491 /* Clear any previously set value. */
3492 if (lxc_conf->syslog) {
3493 free(lxc_conf->syslog);
3494 lxc_conf->syslog = NULL;
3495 }
3496
3497 /* Check if value is empty. */
3498 if (config_value_empty(value))
3499 return 0;
3500
3501 /* Parse value. */
3502 facility = lxc_syslog_priority_to_int(value);
3503 if (facility == -EINVAL) {
3504 ERROR("Wrong value for lxc.syslog.");
3505 return -1;
3506 }
3507
3508 lxc_log_syslog(facility);
3509 return set_config_string_item(&lxc_conf->syslog, value);
3510 }
3511
3512 static int set_config_no_new_privs(const char *key, const char *value,
3513 struct lxc_conf *lxc_conf)
3514 {
3515 unsigned int v;
3516
3517 /* Set config value to default. */
3518 if (config_value_empty(value)) {
3519 lxc_conf->no_new_privs = false;
3520 return 0;
3521 }
3522
3523 /* Parse new config value. */
3524 if (lxc_safe_uint(value, &v) < 0)
3525 return -1;
3526
3527 if (v > 1) {
3528 ERROR("Wrong value for lxc.no_new_privs. Can only be set to 0 or 1");
3529 return -1;
3530 }
3531
3532 lxc_conf->no_new_privs = v ? true : false;
3533
3534 return 0;
3535 }
3536
3537 /* Callbacks to get configuration items. */
3538 static int get_config_personality(struct lxc_container *c, const char *key,
3539 char *retv, int inlen)
3540 {
3541 int fulllen = 0;
3542
3543 if (!retv)
3544 inlen = 0;
3545 else
3546 memset(retv, 0, inlen);
3547
3548 #if HAVE_SYS_PERSONALITY_H
3549 int len = 0;
3550
3551 switch (c->lxc_conf->personality) {
3552 case PER_LINUX32:
3553 strprint(retv, inlen, "i686");
3554 break;
3555 case PER_LINUX:
3556 strprint(retv, inlen, "x86_64");
3557 break;
3558 default:
3559 break;
3560 }
3561 #endif
3562
3563 return fulllen;
3564 }
3565
3566 static int get_config_pts(struct lxc_container *c, const char *key, char *retv,
3567 int inlen)
3568 {
3569 return lxc_get_conf_int(c->lxc_conf, retv, inlen, c->lxc_conf->pts);
3570 }
3571
3572 static int get_config_tty(struct lxc_container *c, const char *key, char *retv,
3573 int inlen)
3574 {
3575 return lxc_get_conf_int(c->lxc_conf, retv, inlen, c->lxc_conf->tty);
3576 }
3577
3578 static inline int lxc_get_conf_str(char *retv, int inlen, const char *value)
3579 {
3580 if (!value)
3581 return 0;
3582 if (retv && inlen >= strlen(value) + 1)
3583 strncpy(retv, value, strlen(value) + 1);
3584
3585 return strlen(value);
3586 }
3587
3588 static int get_config_ttydir(struct lxc_container *c, const char *key,
3589 char *retv, int inlen)
3590 {
3591 return lxc_get_conf_str(retv, inlen, c->lxc_conf->ttydir);
3592 }
3593
3594 static int get_config_kmsg(struct lxc_container *c, const char *key, char *retv,
3595 int inlen)
3596 {
3597 return lxc_get_conf_int(c->lxc_conf, retv, inlen, c->lxc_conf->kmsg);
3598 }
3599
3600 static int get_config_lsm_aa_profile(struct lxc_container *c, const char *key,
3601 char *retv, int inlen)
3602 {
3603 return lxc_get_conf_str(retv, inlen, c->lxc_conf->lsm_aa_profile);
3604 }
3605
3606 static int get_config_lsm_aa_incomplete(struct lxc_container *c,
3607 const char *key, char *retv, int inlen)
3608 {
3609 return lxc_get_conf_int(c->lxc_conf, retv, inlen,
3610 c->lxc_conf->lsm_aa_allow_incomplete);
3611 }
3612
3613 static int get_config_lsm_se_context(struct lxc_container *c, const char *key,
3614 char *retv, int inlen)
3615 {
3616 return lxc_get_conf_str(retv, inlen, c->lxc_conf->lsm_se_context);
3617 }
3618
3619 /*
3620 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
3621 * then just the value(s) will be printed. Since there still could be
3622 * more than one, it is newline-separated.
3623 * (Maybe that's ambigous, since some values, i.e. devices.list, will
3624 * already have newlines?)
3625 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
3626 * in 'lxc.cgroup.subsystem.key = value' format.
3627 */
3628 static int get_config_cgroup(struct lxc_container *c, const char *key,
3629 char *retv, int inlen)
3630 {
3631 struct lxc_list *it;
3632 int len;
3633 int fulllen = 0;
3634 bool get_all = false;
3635
3636 if (!retv)
3637 inlen = 0;
3638 else
3639 memset(retv, 0, inlen);
3640
3641 if (!strcmp(key, "lxc.cgroup"))
3642 get_all = true;
3643 else if (!strncmp(key, "lxc.cgroup.", 11))
3644 key += 11;
3645 else
3646 return -1;
3647
3648 lxc_list_for_each(it, &c->lxc_conf->cgroup) {
3649 struct lxc_cgroup *cg = it->elem;
3650 if (get_all) {
3651 strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
3652 } else if (!strcmp(cg->subsystem, key)) {
3653 strprint(retv, inlen, "%s\n", cg->value);
3654 }
3655 }
3656
3657 return fulllen;
3658 }
3659
3660 static int get_config_idmaps(struct lxc_container *c, const char *key,
3661 char *retv, int inlen)
3662 {
3663 struct lxc_list *it;
3664 int len, listlen, ret;
3665 int fulllen = 0;
3666 /* "u 1000 1000000 65536"
3667 *
3668 * let's render this as
3669 *
3670 * sizeof(char)
3671 * +
3672 * sizeof(" ")
3673 * +
3674 * sizeof(uint64_t)
3675 * +
3676 * sizeof(" ")
3677 * +
3678 * sizeof(uint64_t)
3679 * +
3680 * sizeof(" ")
3681 * +
3682 * sizeof(uint64_t)
3683 * +
3684 * \0
3685 */
3686 #define __LXC_IDMAP_STR_BUF (3 * LXC_NUMSTRLEN64 + 3 + 1 + 1)
3687 char buf[__LXC_IDMAP_STR_BUF];
3688
3689 if (!retv)
3690 inlen = 0;
3691 else
3692 memset(retv, 0, inlen);
3693
3694 listlen = lxc_list_len(&c->lxc_conf->id_map);
3695 lxc_list_for_each(it, &c->lxc_conf->id_map)
3696 {
3697 struct id_map *map = it->elem;
3698 ret = snprintf(buf, __LXC_IDMAP_STR_BUF, "%c %lu %lu %lu",
3699 (map->idtype == ID_TYPE_UID) ? 'u' : 'g',
3700 map->nsid, map->hostid, map->range);
3701 if (ret < 0 || ret >= __LXC_IDMAP_STR_BUF)
3702 return -1;
3703
3704 strprint(retv, inlen, "%s%s", buf, (listlen-- > 1) ? "\n" : "");
3705 }
3706 return fulllen;
3707 }
3708
3709 static int get_config_loglevel(struct lxc_container *c, const char *key,
3710 char *retv, int inlen)
3711 {
3712 const char *v;
3713 v = lxc_log_priority_to_string(c->lxc_conf->loglevel);
3714 return lxc_get_conf_str(retv, inlen, v);
3715 }
3716
3717 static int get_config_logfile(struct lxc_container *c, const char *key,
3718 char *retv, int inlen)
3719 {
3720 return lxc_get_conf_str(retv, inlen, c->lxc_conf->logfile);
3721 }
3722
3723 static int get_config_fstab(struct lxc_container *c, const char *key,
3724 char *retv, int inlen)
3725 {
3726 return lxc_get_conf_str(retv, inlen, c->lxc_conf->fstab);
3727 }
3728
3729 static int get_config_mount_auto(struct lxc_container *c, const char *key,
3730 char *retv, int inlen)
3731 {
3732 int len, fulllen = 0;
3733 const char *sep = "";
3734
3735 if (!retv)
3736 inlen = 0;
3737 else
3738 memset(retv, 0, inlen);
3739
3740 if (!(c->lxc_conf->auto_mounts & LXC_AUTO_ALL_MASK))
3741 return 0;
3742
3743 switch (c->lxc_conf->auto_mounts & LXC_AUTO_PROC_MASK) {
3744 case LXC_AUTO_PROC_MIXED:
3745 strprint(retv, inlen, "%sproc:mixed", sep);
3746 sep = " ";
3747 break;
3748 case LXC_AUTO_PROC_RW:
3749 strprint(retv, inlen, "%sproc:rw", sep);
3750 sep = " ";
3751 break;
3752 default:
3753 break;
3754 }
3755
3756 switch (c->lxc_conf->auto_mounts & LXC_AUTO_SYS_MASK) {
3757 case LXC_AUTO_SYS_RO:
3758 strprint(retv, inlen, "%ssys:ro", sep);
3759 sep = " ";
3760 break;
3761 case LXC_AUTO_SYS_RW:
3762 strprint(retv, inlen, "%ssys:rw", sep);
3763 sep = " ";
3764 break;
3765 case LXC_AUTO_SYS_MIXED:
3766 strprint(retv, inlen, "%ssys:mixed", sep);
3767 sep = " ";
3768 break;
3769 default:
3770 break;
3771 }
3772
3773 switch (c->lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK) {
3774 case LXC_AUTO_CGROUP_NOSPEC:
3775 strprint(retv, inlen, "%scgroup", sep);
3776 sep = " ";
3777 break;
3778 case LXC_AUTO_CGROUP_MIXED:
3779 strprint(retv, inlen, "%scgroup:mixed", sep);
3780 sep = " ";
3781 break;
3782 case LXC_AUTO_CGROUP_RO:
3783 strprint(retv, inlen, "%scgroup:ro", sep);
3784 sep = " ";
3785 break;
3786 case LXC_AUTO_CGROUP_RW:
3787 strprint(retv, inlen, "%scgroup:rw", sep);
3788 sep = " ";
3789 break;
3790 case LXC_AUTO_CGROUP_FULL_NOSPEC:
3791 strprint(retv, inlen, "%scgroup-full", sep);
3792 sep = " ";
3793 break;
3794 case LXC_AUTO_CGROUP_FULL_MIXED:
3795 strprint(retv, inlen, "%scgroup-full:mixed", sep);
3796 sep = " ";
3797 break;
3798 case LXC_AUTO_CGROUP_FULL_RO:
3799 strprint(retv, inlen, "%scgroup-full:ro", sep);
3800 sep = " ";
3801 break;
3802 case LXC_AUTO_CGROUP_FULL_RW:
3803 strprint(retv, inlen, "%scgroup-full:rw", sep);
3804 sep = " ";
3805 break;
3806 default:
3807 break;
3808 }
3809
3810 return fulllen;
3811 }
3812
3813 static int get_config_mount(struct lxc_container *c, const char *key,
3814 char *retv, int inlen)
3815 {
3816 int len, fulllen = 0;
3817 struct lxc_list *it;
3818
3819 if (!retv)
3820 inlen = 0;
3821 else
3822 memset(retv, 0, inlen);
3823
3824 lxc_list_for_each(it, &c->lxc_conf->mount_list)
3825 {
3826 strprint(retv, inlen, "%s\n", (char *)it->elem);
3827 }
3828
3829 return fulllen;
3830 }
3831
3832 static int get_config_rootfs(struct lxc_container *c, const char *key,
3833 char *retv, int inlen)
3834 {
3835 return lxc_get_conf_str(retv, inlen, c->lxc_conf->rootfs.path);
3836 }
3837
3838 static int get_config_rootfs_mount(struct lxc_container *c, const char *key,
3839 char *retv, int inlen)
3840 {
3841 return lxc_get_conf_str(retv, inlen, c->lxc_conf->rootfs.mount);
3842 }
3843
3844 static int get_config_rootfs_options(struct lxc_container *c, const char *key,
3845 char *retv, int inlen)
3846 {
3847 return lxc_get_conf_str(retv, inlen, c->lxc_conf->rootfs.options);
3848 }