~serge-hallyn/ubuntu/quantal/lxc/lxc-user-ns

« back to all changes in this revision

Viewing changes to .pc/lxc-use-user-namespace.patch/src/lxc/conf.c

  • Committer: Serge Hallyn
  • Date: 2012-10-29 16:51:57 UTC
  • Revision ID: serge.hallyn@ubuntu.com-20121029165157-xw2nxym7eo0ocxu4
Add user namespaces patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lxc: linux Container library
 
3
 *
 
4
 * (C) Copyright IBM Corp. 2007, 2008
 
5
 *
 
6
 * Authors:
 
7
 * Daniel Lezcano <dlezcano at fr.ibm.com>
 
8
 *
 
9
 * This library is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU Lesser General Public
 
11
 * License as published by the Free Software Foundation; either
 
12
 * version 2.1 of the License, or (at your option) any later version.
 
13
 *
 
14
 * This library is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * Lesser General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public
 
20
 * License along with this library; if not, write to the Free Software
 
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
22
 */
 
23
#define _GNU_SOURCE
 
24
#include <stdio.h>
 
25
#undef _GNU_SOURCE
 
26
#include <stdlib.h>
 
27
#include <stdarg.h>
 
28
#include <errno.h>
 
29
#include <string.h>
 
30
#include <dirent.h>
 
31
#include <mntent.h>
 
32
#include <unistd.h>
 
33
#include <sys/wait.h>
 
34
#include <pty.h>
 
35
 
 
36
#include <linux/loop.h>
 
37
 
 
38
#include <sys/types.h>
 
39
#include <sys/utsname.h>
 
40
#include <sys/param.h>
 
41
#include <sys/stat.h>
 
42
#include <sys/socket.h>
 
43
#include <sys/mount.h>
 
44
#include <sys/mman.h>
 
45
#include <sys/prctl.h>
 
46
#include <sys/capability.h>
 
47
#include <sys/personality.h>
 
48
 
 
49
#include <arpa/inet.h>
 
50
#include <fcntl.h>
 
51
#include <netinet/in.h>
 
52
#include <net/if.h>
 
53
#include <libgen.h>
 
54
 
 
55
#include "network.h"
 
56
#include "error.h"
 
57
#include "parse.h"
 
58
#include "config.h"
 
59
#include "utils.h"
 
60
#include "conf.h"
 
61
#include "log.h"
 
62
#include "lxc.h"        /* for lxc_cgroup_set() */
 
63
#include "caps.h"       /* for lxc_caps_last_cap() */
 
64
 
 
65
lxc_log_define(lxc_conf, lxc);
 
66
 
 
67
#define MAXHWLEN    18
 
68
#define MAXINDEXLEN 20
 
69
#define MAXMTULEN   16
 
70
#define MAXLINELEN  128
 
71
 
 
72
#ifndef MS_DIRSYNC
 
73
#define MS_DIRSYNC  128
 
74
#endif
 
75
 
 
76
#ifndef MS_REC
 
77
#define MS_REC 16384
 
78
#endif
 
79
 
 
80
#ifndef MNT_DETACH
 
81
#define MNT_DETACH 2
 
82
#endif
 
83
 
 
84
#ifndef MS_RELATIME
 
85
#define MS_RELATIME (1 << 21)
 
86
#endif
 
87
 
 
88
#ifndef MS_STRICTATIME
 
89
#define MS_STRICTATIME (1 << 24)
 
90
#endif
 
91
 
 
92
#ifndef CAP_SETFCAP
 
93
#define CAP_SETFCAP 31
 
94
#endif
 
95
 
 
96
#ifndef CAP_MAC_OVERRIDE
 
97
#define CAP_MAC_OVERRIDE 32
 
98
#endif
 
99
 
 
100
#ifndef CAP_MAC_ADMIN
 
101
#define CAP_MAC_ADMIN 33
 
102
#endif
 
103
 
 
104
#ifndef PR_CAPBSET_DROP
 
105
#define PR_CAPBSET_DROP 24
 
106
#endif
 
107
 
 
108
char *lxchook_names[NUM_LXC_HOOKS] = {
 
109
        "pre-start", "pre-mount", "mount", "start", "post-stop" };
 
110
 
 
111
extern int pivot_root(const char * new_root, const char * put_old);
 
112
 
 
113
typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
 
114
 
 
115
struct mount_opt {
 
116
        char *name;
 
117
        int clear;
 
118
        int flag;
 
119
};
 
120
 
 
121
struct caps_opt {
 
122
        char *name;
 
123
        int value;
 
124
};
 
125
 
 
126
static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
 
127
static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
 
128
static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
 
129
static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
 
130
static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
 
131
 
 
132
static  instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
 
133
        [LXC_NET_VETH]    = instanciate_veth,
 
134
        [LXC_NET_MACVLAN] = instanciate_macvlan,
 
135
        [LXC_NET_VLAN]    = instanciate_vlan,
 
136
        [LXC_NET_PHYS]    = instanciate_phys,
 
137
        [LXC_NET_EMPTY]   = instanciate_empty,
 
138
};
 
139
 
 
140
static struct mount_opt mount_opt[] = {
 
141
        { "defaults",      0, 0              },
 
142
        { "ro",            0, MS_RDONLY      },
 
143
        { "rw",            1, MS_RDONLY      },
 
144
        { "suid",          1, MS_NOSUID      },
 
145
        { "nosuid",        0, MS_NOSUID      },
 
146
        { "dev",           1, MS_NODEV       },
 
147
        { "nodev",         0, MS_NODEV       },
 
148
        { "exec",          1, MS_NOEXEC      },
 
149
        { "noexec",        0, MS_NOEXEC      },
 
150
        { "sync",          0, MS_SYNCHRONOUS },
 
151
        { "async",         1, MS_SYNCHRONOUS },
 
152
        { "dirsync",       0, MS_DIRSYNC     },
 
153
        { "remount",       0, MS_REMOUNT     },
 
154
        { "mand",          0, MS_MANDLOCK    },
 
155
        { "nomand",        1, MS_MANDLOCK    },
 
156
        { "atime",         1, MS_NOATIME     },
 
157
        { "noatime",       0, MS_NOATIME     },
 
158
        { "diratime",      1, MS_NODIRATIME  },
 
159
        { "nodiratime",    0, MS_NODIRATIME  },
 
160
        { "bind",          0, MS_BIND        },
 
161
        { "rbind",         0, MS_BIND|MS_REC },
 
162
        { "relatime",      0, MS_RELATIME    },
 
163
        { "norelatime",    1, MS_RELATIME    },
 
164
        { "strictatime",   0, MS_STRICTATIME },
 
165
        { "nostrictatime", 1, MS_STRICTATIME },
 
166
        { NULL,            0, 0              },
 
167
};
 
168
 
 
169
static struct caps_opt caps_opt[] = {
 
170
        { "chown",             CAP_CHOWN             },
 
171
        { "dac_override",      CAP_DAC_OVERRIDE      },
 
172
        { "dac_read_search",   CAP_DAC_READ_SEARCH   },
 
173
        { "fowner",            CAP_FOWNER            },
 
174
        { "fsetid",            CAP_FSETID            },
 
175
        { "kill",              CAP_KILL              },
 
176
        { "setgid",            CAP_SETGID            },
 
177
        { "setuid",            CAP_SETUID            },
 
178
        { "setpcap",           CAP_SETPCAP           },
 
179
        { "linux_immutable",   CAP_LINUX_IMMUTABLE   },
 
180
        { "net_bind_service",  CAP_NET_BIND_SERVICE  },
 
181
        { "net_broadcast",     CAP_NET_BROADCAST     },
 
182
        { "net_admin",         CAP_NET_ADMIN         },
 
183
        { "net_raw",           CAP_NET_RAW           },
 
184
        { "ipc_lock",          CAP_IPC_LOCK          },
 
185
        { "ipc_owner",         CAP_IPC_OWNER         },
 
186
        { "sys_module",        CAP_SYS_MODULE        },
 
187
        { "sys_rawio",         CAP_SYS_RAWIO         },
 
188
        { "sys_chroot",        CAP_SYS_CHROOT        },
 
189
        { "sys_ptrace",        CAP_SYS_PTRACE        },
 
190
        { "sys_pacct",         CAP_SYS_PACCT         },
 
191
        { "sys_admin",         CAP_SYS_ADMIN         },
 
192
        { "sys_boot",          CAP_SYS_BOOT          },
 
193
        { "sys_nice",          CAP_SYS_NICE          },
 
194
        { "sys_resource",      CAP_SYS_RESOURCE      },
 
195
        { "sys_time",          CAP_SYS_TIME          },
 
196
        { "sys_tty_config",    CAP_SYS_TTY_CONFIG    },
 
197
        { "mknod",             CAP_MKNOD             },
 
198
        { "lease",             CAP_LEASE             },
 
199
#ifdef CAP_AUDIT_WRITE
 
200
        { "audit_write",       CAP_AUDIT_WRITE       },
 
201
#endif
 
202
#ifdef CAP_AUDIT_CONTROL
 
203
        { "audit_control",     CAP_AUDIT_CONTROL     },
 
204
#endif
 
205
        { "setfcap",           CAP_SETFCAP           },
 
206
        { "mac_override",      CAP_MAC_OVERRIDE      },
 
207
        { "mac_admin",         CAP_MAC_ADMIN         },
 
208
#ifdef CAP_SYSLOG
 
209
        { "syslog",            CAP_SYSLOG            },
 
210
#endif
 
211
#ifdef CAP_WAKE_ALARM
 
212
        { "wake_alarm",        CAP_WAKE_ALARM        },
 
213
#endif
 
214
};
 
215
 
 
216
static int run_script(const char *name, const char *section,
 
217
                      const char *script, ...)
 
218
{
 
219
        int ret;
 
220
        FILE *f;
 
221
        char *buffer, *p, *output;
 
222
        size_t size = 0;
 
223
        va_list ap;
 
224
 
 
225
        INFO("Executing script '%s' for container '%s', config section '%s'",
 
226
             script, name, section);
 
227
 
 
228
        va_start(ap, script);
 
229
        while ((p = va_arg(ap, char *)))
 
230
                size += strlen(p) + 1;
 
231
        va_end(ap);
 
232
 
 
233
        size += strlen(script);
 
234
        size += strlen(name);
 
235
        size += strlen(section);
 
236
        size += 3;
 
237
 
 
238
        if (size > INT_MAX)
 
239
                return -1;
 
240
 
 
241
        buffer = alloca(size);
 
242
        if (!buffer) {
 
243
                ERROR("failed to allocate memory");
 
244
                return -1;
 
245
        }
 
246
 
 
247
        ret = snprintf(buffer, size, "%s %s %s", script, name, section);
 
248
        if (ret < 0 || ret >= size) {
 
249
                ERROR("Script name too long");
 
250
                free(buffer);
 
251
                return -1;
 
252
        }
 
253
 
 
254
        va_start(ap, script);
 
255
        while ((p = va_arg(ap, char *))) {
 
256
                int len = size-ret;
 
257
                int rc;
 
258
                rc = snprintf(buffer + ret, len, " %s", p);
 
259
                if (rc < 0 || rc >= len) {
 
260
                        free(buffer);
 
261
                        ERROR("Script args too long");
 
262
                        return -1;
 
263
                }
 
264
                ret += rc;
 
265
        }
 
266
        va_end(ap);
 
267
 
 
268
        f = popen(buffer, "r");
 
269
        if (!f) {
 
270
                SYSERROR("popen failed");
 
271
                return -1;
 
272
        }
 
273
 
 
274
        output = malloc(LXC_LOG_BUFFER_SIZE);
 
275
        if (!output) {
 
276
                ERROR("failed to allocate memory for script output");
 
277
                return -1;
 
278
        }
 
279
 
 
280
        while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
 
281
                DEBUG("script output: %s", output);
 
282
 
 
283
        free(output);
 
284
 
 
285
        if (pclose(f) == -1) {
 
286
                SYSERROR("Script exited on error");
 
287
                return -1;
 
288
        }
 
289
 
 
290
        return 0;
 
291
}
 
292
 
 
293
static int find_fstype_cb(char* buffer, void *data)
 
294
{
 
295
        struct cbarg {
 
296
                const char *rootfs;
 
297
                const char *target;
 
298
                int mntopt;
 
299
        } *cbarg = data;
 
300
 
 
301
        char *fstype;
 
302
 
 
303
        /* we don't try 'nodev' entries */
 
304
        if (strstr(buffer, "nodev"))
 
305
                return 0;
 
306
 
 
307
        fstype = buffer;
 
308
        fstype += lxc_char_left_gc(fstype, strlen(fstype));
 
309
        fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
 
310
 
 
311
        DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
 
312
              cbarg->rootfs, cbarg->target, fstype);
 
313
 
 
314
        if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) {
 
315
                DEBUG("mount failed with error: %s", strerror(errno));
 
316
                return 0;
 
317
        }
 
318
 
 
319
        INFO("mounted '%s' on '%s', with fstype '%s'",
 
320
             cbarg->rootfs, cbarg->target, fstype);
 
321
 
 
322
        return 1;
 
323
}
 
324
 
 
325
static int mount_unknow_fs(const char *rootfs, const char *target, int mntopt)
 
326
{
 
327
        int i;
 
328
 
 
329
        struct cbarg {
 
330
                const char *rootfs;
 
331
                const char *target;
 
332
                int mntopt;
 
333
        } cbarg = {
 
334
                .rootfs = rootfs,
 
335
                .target = target,
 
336
                .mntopt = mntopt,
 
337
        };
 
338
 
 
339
        /*
 
340
         * find the filesystem type with brute force:
 
341
         * first we check with /etc/filesystems, in case the modules
 
342
         * are auto-loaded and fall back to the supported kernel fs
 
343
         */
 
344
        char *fsfile[] = {
 
345
                "/etc/filesystems",
 
346
                "/proc/filesystems",
 
347
        };
 
348
 
 
349
        for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
 
350
 
 
351
                int ret;
 
352
 
 
353
                if (access(fsfile[i], F_OK))
 
354
                        continue;
 
355
 
 
356
                ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
 
357
                if (ret < 0) {
 
358
                        ERROR("failed to parse '%s'", fsfile[i]);
 
359
                        return -1;
 
360
                }
 
361
 
 
362
                if (ret)
 
363
                        return 0;
 
364
        }
 
365
 
 
366
        ERROR("failed to determine fs type for '%s'", rootfs);
 
367
        return -1;
 
368
}
 
369
 
 
370
static int mount_rootfs_dir(const char *rootfs, const char *target)
 
371
{
 
372
        return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL);
 
373
}
 
374
 
 
375
static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
 
376
{
 
377
        int rfd;
 
378
        int ret = -1;
 
379
 
 
380
        rfd = open(rootfs, O_RDWR);
 
381
        if (rfd < 0) {
 
382
                SYSERROR("failed to open '%s'", rootfs);
 
383
                return -1;
 
384
        }
 
385
 
 
386
        memset(loinfo, 0, sizeof(*loinfo));
 
387
 
 
388
        loinfo->lo_flags = LO_FLAGS_AUTOCLEAR;
 
389
 
 
390
        if (ioctl(fd, LOOP_SET_FD, rfd)) {
 
391
                SYSERROR("failed to LOOP_SET_FD");
 
392
                goto out;
 
393
        }
 
394
 
 
395
        if (ioctl(fd, LOOP_SET_STATUS64, loinfo)) {
 
396
                SYSERROR("failed to LOOP_SET_STATUS64");
 
397
                goto out;
 
398
        }
 
399
 
 
400
        ret = 0;
 
401
out:
 
402
        close(rfd);
 
403
 
 
404
        return ret;
 
405
}
 
406
 
 
407
static int mount_rootfs_file(const char *rootfs, const char *target)
 
408
{
 
409
        struct dirent dirent, *direntp;
 
410
        struct loop_info64 loinfo;
 
411
        int ret = -1, fd = -1, rc;
 
412
        DIR *dir;
 
413
        char path[MAXPATHLEN];
 
414
 
 
415
        dir = opendir("/dev");
 
416
        if (!dir) {
 
417
                SYSERROR("failed to open '/dev'");
 
418
                return -1;
 
419
        }
 
420
 
 
421
        while (!readdir_r(dir, &dirent, &direntp)) {
 
422
 
 
423
                if (!direntp)
 
424
                        break;
 
425
 
 
426
                if (!strcmp(direntp->d_name, "."))
 
427
                        continue;
 
428
 
 
429
                if (!strcmp(direntp->d_name, ".."))
 
430
                        continue;
 
431
 
 
432
                if (strncmp(direntp->d_name, "loop", 4))
 
433
                        continue;
 
434
 
 
435
                rc = snprintf(path, MAXPATHLEN, "/dev/%s", direntp->d_name);
 
436
                if (rc < 0 || rc >= MAXPATHLEN)
 
437
                        continue;
 
438
 
 
439
                fd = open(path, O_RDWR);
 
440
                if (fd < 0)
 
441
                        continue;
 
442
 
 
443
                if (ioctl(fd, LOOP_GET_STATUS64, &loinfo) == 0) {
 
444
                        close(fd);
 
445
                        continue;
 
446
                }
 
447
 
 
448
                if (errno != ENXIO) {
 
449
                        WARN("unexpected error for ioctl on '%s': %m",
 
450
                             direntp->d_name);
 
451
                        continue;
 
452
                }
 
453
 
 
454
                DEBUG("found '%s' free lodev", path);
 
455
 
 
456
                ret = setup_lodev(rootfs, fd, &loinfo);
 
457
                if (!ret)
 
458
                        ret = mount_unknow_fs(path, target, 0);
 
459
                close(fd);
 
460
 
 
461
                break;
 
462
        }
 
463
 
 
464
        if (closedir(dir))
 
465
                WARN("failed to close directory");
 
466
 
 
467
        return ret;
 
468
}
 
469
 
 
470
static int mount_rootfs_block(const char *rootfs, const char *target)
 
471
{
 
472
        return mount_unknow_fs(rootfs, target, 0);
 
473
}
 
474
 
 
475
/*
 
476
 * pin_rootfs
 
477
 * if rootfs is a directory, then open ${rootfs}.hold for writing for the
 
478
 * duration of the container run, to prevent the container from marking the
 
479
 * underlying fs readonly on shutdown.
 
480
 * return -1 on error.
 
481
 * return -2 if nothing needed to be pinned.
 
482
 * return an open fd (>=0) if we pinned it.
 
483
 */
 
484
int pin_rootfs(const char *rootfs)
 
485
{
 
486
        char absrootfs[MAXPATHLEN];
 
487
        char absrootfspin[MAXPATHLEN];
 
488
        struct stat s;
 
489
        int ret, fd;
 
490
 
 
491
        if (rootfs == NULL || strlen(rootfs) == 0)
 
492
                return 0;
 
493
 
 
494
        if (!realpath(rootfs, absrootfs)) {
 
495
                SYSERROR("failed to get real path for '%s'", rootfs);
 
496
                return -1;
 
497
        }
 
498
 
 
499
        if (access(absrootfs, F_OK)) {
 
500
                SYSERROR("'%s' is not accessible", absrootfs);
 
501
                return -1;
 
502
        }
 
503
 
 
504
        if (stat(absrootfs, &s)) {
 
505
                SYSERROR("failed to stat '%s'", absrootfs);
 
506
                return -1;
 
507
        }
 
508
 
 
509
        if (!__S_ISTYPE(s.st_mode, S_IFDIR))
 
510
                return -2;
 
511
 
 
512
        ret = snprintf(absrootfspin, MAXPATHLEN, "%s%s", absrootfs, ".hold");
 
513
        if (ret >= MAXPATHLEN) {
 
514
                SYSERROR("pathname too long for rootfs hold file");
 
515
                return -1;
 
516
        }
 
517
 
 
518
        fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR|S_IRUSR);
 
519
        INFO("opened %s as fd %d\n", absrootfspin, fd);
 
520
        return fd;
 
521
}
 
522
 
 
523
static int mount_rootfs(const char *rootfs, const char *target)
 
524
{
 
525
        char absrootfs[MAXPATHLEN];
 
526
        struct stat s;
 
527
        int i;
 
528
 
 
529
        typedef int (*rootfs_cb)(const char *, const char *);
 
530
 
 
531
        struct rootfs_type {
 
532
                int type;
 
533
                rootfs_cb cb;
 
534
        } rtfs_type[] = {
 
535
                { S_IFDIR, mount_rootfs_dir },
 
536
                { S_IFBLK, mount_rootfs_block },
 
537
                { S_IFREG, mount_rootfs_file },
 
538
        };
 
539
 
 
540
        if (!realpath(rootfs, absrootfs)) {
 
541
                SYSERROR("failed to get real path for '%s'", rootfs);
 
542
                return -1;
 
543
        }
 
544
 
 
545
        if (access(absrootfs, F_OK)) {
 
546
                SYSERROR("'%s' is not accessible", absrootfs);
 
547
                return -1;
 
548
        }
 
549
 
 
550
        if (stat(absrootfs, &s)) {
 
551
                SYSERROR("failed to stat '%s'", absrootfs);
 
552
                return -1;
 
553
        }
 
554
 
 
555
        for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
 
556
 
 
557
                if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
 
558
                        continue;
 
559
 
 
560
                return rtfs_type[i].cb(absrootfs, target);
 
561
        }
 
562
 
 
563
        ERROR("unsupported rootfs type for '%s'", absrootfs);
 
564
        return -1;
 
565
}
 
566
 
 
567
static int setup_utsname(struct utsname *utsname)
 
568
{
 
569
        if (!utsname)
 
570
                return 0;
 
571
 
 
572
        if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
 
573
                SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
 
574
                return -1;
 
575
        }
 
576
 
 
577
        INFO("'%s' hostname has been setup", utsname->nodename);
 
578
 
 
579
        return 0;
 
580
}
 
581
 
 
582
static int setup_tty(const struct lxc_rootfs *rootfs,
 
583
                     const struct lxc_tty_info *tty_info, char *ttydir)
 
584
{
 
585
        char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
 
586
        int i, ret;
 
587
 
 
588
        if (!rootfs->path)
 
589
                return 0;
 
590
 
 
591
        for (i = 0; i < tty_info->nbtty; i++) {
 
592
 
 
593
                struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
 
594
 
 
595
                ret = snprintf(path, sizeof(path), "%s/dev/tty%d",
 
596
                         rootfs->mount, i + 1);
 
597
                if (ret >= sizeof(path)) {
 
598
                        ERROR("pathname too long for ttys");
 
599
                        return -1;
 
600
                }
 
601
                if (ttydir) {
 
602
                        /* create dev/lxc/tty%d" */
 
603
                        ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
 
604
                                 rootfs->mount, ttydir, i + 1);
 
605
                        if (ret >= sizeof(lxcpath)) {
 
606
                                ERROR("pathname too long for ttys");
 
607
                                return -1;
 
608
                        }
 
609
                        ret = creat(lxcpath, 0660);
 
610
                        if (ret==-1 && errno != EEXIST) {
 
611
                                SYSERROR("error creating %s\n", lxcpath);
 
612
                                return -1;
 
613
                        }
 
614
                        close(ret);
 
615
                        ret = unlink(path);
 
616
                        if (ret && errno != ENOENT) {
 
617
                                SYSERROR("error unlinking %s\n", path);
 
618
                                return -1;
 
619
                        }
 
620
 
 
621
                        if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) {
 
622
                                WARN("failed to mount '%s'->'%s'",
 
623
                                     pty_info->name, path);
 
624
                                continue;
 
625
                        }
 
626
 
 
627
                        ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1);
 
628
                        if (ret >= sizeof(lxcpath)) {
 
629
                                ERROR("tty pathname too long");
 
630
                                return -1;
 
631
                        }
 
632
                        ret = symlink(lxcpath, path);
 
633
                        if (ret) {
 
634
                                SYSERROR("failed to create symlink for tty %d\n", i+1);
 
635
                                return -1;
 
636
                        }
 
637
                } else {
 
638
                        if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
 
639
                                WARN("failed to mount '%s'->'%s'",
 
640
                                                pty_info->name, path);
 
641
                                continue;
 
642
                        }
 
643
                }
 
644
        }
 
645
 
 
646
        INFO("%d tty(s) has been setup", tty_info->nbtty);
 
647
 
 
648
        return 0;
 
649
}
 
650
 
 
651
static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
 
652
{
 
653
        struct lxc_list *mountlist, *listentry, *iterator;
 
654
        char *pivotdir, *mountpoint, *mountentry;
 
655
        int found;
 
656
        void **cbparm;
 
657
 
 
658
        mountentry = buffer;
 
659
        cbparm = (void **)data;
 
660
 
 
661
        mountlist = cbparm[0];
 
662
        pivotdir  = cbparm[1];
 
663
 
 
664
        /* parse entry, first field is mountname, ignore */
 
665
        mountpoint = strtok(mountentry, " ");
 
666
        if (!mountpoint)
 
667
                return -1;
 
668
 
 
669
        /* second field is mountpoint */
 
670
        mountpoint = strtok(NULL, " ");
 
671
        if (!mountpoint)
 
672
                return -1;
 
673
 
 
674
        /* only consider mountpoints below old root fs */
 
675
        if (strncmp(mountpoint, pivotdir, strlen(pivotdir)))
 
676
                return 0;
 
677
 
 
678
        /* filter duplicate mountpoints */
 
679
        found = 0;
 
680
        lxc_list_for_each(iterator, mountlist) {
 
681
                if (!strcmp(iterator->elem, mountpoint)) {
 
682
                        found = 1;
 
683
                        break;
 
684
                }
 
685
        }
 
686
        if (found)
 
687
                return 0;
 
688
 
 
689
        /* add entry to list */
 
690
        listentry = malloc(sizeof(*listentry));
 
691
        if (!listentry) {
 
692
                SYSERROR("malloc for mountpoint listentry failed");
 
693
                return -1;
 
694
        }
 
695
 
 
696
        listentry->elem = strdup(mountpoint);
 
697
        if (!listentry->elem) {
 
698
                SYSERROR("strdup failed");
 
699
                return -1;
 
700
        }
 
701
        lxc_list_add_tail(mountlist, listentry);
 
702
 
 
703
        return 0;
 
704
}
 
705
 
 
706
static int umount_oldrootfs(const char *oldrootfs)
 
707
{
 
708
        char path[MAXPATHLEN];
 
709
        void *cbparm[2];
 
710
        struct lxc_list mountlist, *iterator;
 
711
        int ok, still_mounted, last_still_mounted;
 
712
        int rc;
 
713
 
 
714
        /* read and parse /proc/mounts in old root fs */
 
715
        lxc_list_init(&mountlist);
 
716
 
 
717
        /* oldrootfs is on the top tree directory now */
 
718
        rc = snprintf(path, sizeof(path), "/%s", oldrootfs);
 
719
        if (rc >= sizeof(path)) {
 
720
                ERROR("rootfs name too long");
 
721
                return -1;
 
722
        }
 
723
        cbparm[0] = &mountlist;
 
724
 
 
725
        cbparm[1] = strdup(path);
 
726
        if (!cbparm[1]) {
 
727
                SYSERROR("strdup failed");
 
728
                return -1;
 
729
        }
 
730
 
 
731
        rc = snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
 
732
        if (rc >= sizeof(path)) {
 
733
                ERROR("container proc/mounts name too long");
 
734
                return -1;
 
735
        }
 
736
 
 
737
        ok = lxc_file_for_each_line(path,
 
738
                                    setup_rootfs_pivot_root_cb, &cbparm);
 
739
        if (ok < 0) {
 
740
                SYSERROR("failed to read or parse mount list '%s'", path);
 
741
                return -1;
 
742
        }
 
743
 
 
744
        /* umount filesystems until none left or list no longer shrinks */
 
745
        still_mounted = 0;
 
746
        do {
 
747
                last_still_mounted = still_mounted;
 
748
                still_mounted = 0;
 
749
 
 
750
                lxc_list_for_each(iterator, &mountlist) {
 
751
 
 
752
                        /* umount normally */
 
753
                        if (!umount(iterator->elem)) {
 
754
                                DEBUG("umounted '%s'", (char *)iterator->elem);
 
755
                                lxc_list_del(iterator);
 
756
                                continue;
 
757
                        }
 
758
 
 
759
                        still_mounted++;
 
760
                }
 
761
 
 
762
        } while (still_mounted > 0 && still_mounted != last_still_mounted);
 
763
 
 
764
 
 
765
        lxc_list_for_each(iterator, &mountlist) {
 
766
 
 
767
                /* let's try a lazy umount */
 
768
                if (!umount2(iterator->elem, MNT_DETACH)) {
 
769
                        INFO("lazy unmount of '%s'", (char *)iterator->elem);
 
770
                        continue;
 
771
                }
 
772
 
 
773
                /* be more brutal (nfs) */
 
774
                if (!umount2(iterator->elem, MNT_FORCE)) {
 
775
                        INFO("forced unmount of '%s'", (char *)iterator->elem);
 
776
                        continue;
 
777
                }
 
778
 
 
779
                WARN("failed to unmount '%s'", (char *)iterator->elem);
 
780
        }
 
781
 
 
782
        return 0;
 
783
}
 
784
 
 
785
static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
 
786
{
 
787
        char path[MAXPATHLEN];
 
788
        int remove_pivotdir = 0;
 
789
        int rc;
 
790
 
 
791
        /* change into new root fs */
 
792
        if (chdir(rootfs)) {
 
793
                SYSERROR("can't chdir to new rootfs '%s'", rootfs);
 
794
                return -1;
 
795
        }
 
796
 
 
797
        if (!pivotdir)
 
798
                pivotdir = "mnt";
 
799
 
 
800
        /* compute the full path to pivotdir under rootfs */
 
801
        rc = snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
 
802
        if (rc >= sizeof(path)) {
 
803
                ERROR("pivot dir name too long");
 
804
                return -1;
 
805
        }
 
806
 
 
807
        if (access(path, F_OK)) {
 
808
 
 
809
                if (mkdir_p(path, 0755)) {
 
810
                        SYSERROR("failed to create pivotdir '%s'", path);
 
811
                        return -1;
 
812
                }
 
813
 
 
814
                remove_pivotdir = 1;
 
815
                DEBUG("created '%s' directory", path);
 
816
        }
 
817
 
 
818
        DEBUG("mountpoint for old rootfs is '%s'", path);
 
819
 
 
820
        /* pivot_root into our new root fs */
 
821
        if (pivot_root(".", path)) {
 
822
                SYSERROR("pivot_root syscall failed");
 
823
                return -1;
 
824
        }
 
825
 
 
826
        if (chdir("/")) {
 
827
                SYSERROR("can't chdir to / after pivot_root");
 
828
                return -1;
 
829
        }
 
830
 
 
831
        DEBUG("pivot_root syscall to '%s' successful", rootfs);
 
832
 
 
833
        /* we switch from absolute path to relative path */
 
834
        if (umount_oldrootfs(pivotdir))
 
835
                return -1;
 
836
 
 
837
        /* remove temporary mount point, we don't consider the removing
 
838
         * as fatal */
 
839
        if (remove_pivotdir && rmdir(pivotdir))
 
840
                WARN("can't remove mountpoint '%s': %m", pivotdir);
 
841
 
 
842
        return 0;
 
843
}
 
844
 
 
845
static int setup_rootfs(const struct lxc_rootfs *rootfs)
 
846
{
 
847
        if (!rootfs->path)
 
848
                return 0;
 
849
 
 
850
        if (access(rootfs->mount, F_OK)) {
 
851
                SYSERROR("failed to access to '%s', check it is present",
 
852
                         rootfs->mount);
 
853
                return -1;
 
854
        }
 
855
 
 
856
        if (mount_rootfs(rootfs->path, rootfs->mount)) {
 
857
                ERROR("failed to mount rootfs");
 
858
                return -1;
 
859
        }
 
860
 
 
861
        DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
 
862
 
 
863
        return 0;
 
864
}
 
865
 
 
866
int setup_pivot_root(const struct lxc_rootfs *rootfs)
 
867
{
 
868
        if (!rootfs->path)
 
869
                return 0;
 
870
 
 
871
        if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
 
872
                ERROR("failed to setup pivot root");
 
873
                return -1;
 
874
        }
 
875
 
 
876
        return 0;
 
877
}
 
878
 
 
879
static int setup_pts(int pts)
 
880
{
 
881
        char target[PATH_MAX];
 
882
 
 
883
        if (!pts)
 
884
                return 0;
 
885
 
 
886
        if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
 
887
                SYSERROR("failed to umount 'dev/pts'");
 
888
                return -1;
 
889
        }
 
890
 
 
891
        if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL,
 
892
                  "newinstance,ptmxmode=0666")) {
 
893
                SYSERROR("failed to mount a new instance of '/dev/pts'");
 
894
                return -1;
 
895
        }
 
896
 
 
897
        if (access("/dev/ptmx", F_OK)) {
 
898
                if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
 
899
                        goto out;
 
900
                SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
 
901
                return -1;
 
902
        }
 
903
 
 
904
        if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
 
905
                goto out;
 
906
 
 
907
        /* fallback here, /dev/pts/ptmx exists just mount bind */
 
908
        if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
 
909
                SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
 
910
                return -1;
 
911
        }
 
912
 
 
913
        INFO("created new pts instance");
 
914
 
 
915
out:
 
916
        return 0;
 
917
}
 
918
 
 
919
static int setup_personality(int persona)
 
920
{
 
921
        if (persona == -1)
 
922
                return 0;
 
923
 
 
924
        if (personality(persona) < 0) {
 
925
                SYSERROR("failed to set personality to '0x%x'", persona);
 
926
                return -1;
 
927
        }
 
928
 
 
929
        INFO("set personality to '0x%x'", persona);
 
930
 
 
931
        return 0;
 
932
}
 
933
 
 
934
static int setup_dev_console(const struct lxc_rootfs *rootfs,
 
935
                         const struct lxc_console *console)
 
936
{
 
937
        char path[MAXPATHLEN];
 
938
        struct stat s;
 
939
        int ret;
 
940
 
 
941
        ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
 
942
        if (ret >= sizeof(path)) {
 
943
                ERROR("console path too long\n");
 
944
                return -1;
 
945
        }
 
946
 
 
947
        if (access(path, F_OK)) {
 
948
                WARN("rootfs specified but no console found at '%s'", path);
 
949
                return 0;
 
950
        }
 
951
 
 
952
        if (console->peer == -1) {
 
953
                INFO("no console output required");
 
954
                return 0;
 
955
        }
 
956
 
 
957
        if (stat(path, &s)) {
 
958
                SYSERROR("failed to stat '%s'", path);
 
959
                return -1;
 
960
        }
 
961
 
 
962
        if (chmod(console->name, s.st_mode)) {
 
963
                SYSERROR("failed to set mode '0%o' to '%s'",
 
964
                         s.st_mode, console->name);
 
965
                return -1;
 
966
        }
 
967
 
 
968
        if (mount(console->name, path, "none", MS_BIND, 0)) {
 
969
                ERROR("failed to mount '%s' on '%s'", console->name, path);
 
970
                return -1;
 
971
        }
 
972
 
 
973
        INFO("console has been setup");
 
974
        return 0;
 
975
}
 
976
 
 
977
static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
 
978
                         const struct lxc_console *console,
 
979
                         char *ttydir)
 
980
{
 
981
        char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
 
982
        int ret;
 
983
 
 
984
        /* create rootfs/dev/<ttydir> directory */
 
985
        ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount,
 
986
                       ttydir);
 
987
        if (ret >= sizeof(path))
 
988
                return -1;
 
989
        ret = mkdir(path, 0755);
 
990
        if (ret && errno != EEXIST) {
 
991
                SYSERROR("failed with errno %d to create %s\n", errno, path);
 
992
                return -1;
 
993
        }
 
994
        INFO("created %s\n", path);
 
995
 
 
996
        ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console",
 
997
                       rootfs->mount, ttydir);
 
998
        if (ret >= sizeof(lxcpath)) {
 
999
                ERROR("console path too long\n");
 
1000
                return -1;
 
1001
        }
 
1002
 
 
1003
        snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
 
1004
        ret = unlink(path);
 
1005
        if (ret && errno != ENOENT) {
 
1006
                SYSERROR("error unlinking %s\n", path);
 
1007
                return -1;
 
1008
        }
 
1009
 
 
1010
        ret = creat(lxcpath, 0660);
 
1011
        if (ret==-1 && errno != EEXIST) {
 
1012
                SYSERROR("error %d creating %s\n", errno, lxcpath);
 
1013
                return -1;
 
1014
        }
 
1015
        close(ret);
 
1016
 
 
1017
        if (console->peer == -1) {
 
1018
                INFO("no console output required");
 
1019
                return 0;
 
1020
        }
 
1021
 
 
1022
        if (mount(console->name, lxcpath, "none", MS_BIND, 0)) {
 
1023
                ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
 
1024
                return -1;
 
1025
        }
 
1026
 
 
1027
        /* create symlink from rootfs/dev/console to 'lxc/console' */
 
1028
        ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
 
1029
        if (ret >= sizeof(lxcpath)) {
 
1030
                ERROR("lxc/console path too long");
 
1031
                return -1;
 
1032
        }
 
1033
        ret = symlink(lxcpath, path);
 
1034
        if (ret) {
 
1035
                SYSERROR("failed to create symlink for console");
 
1036
                return -1;
 
1037
        }
 
1038
 
 
1039
        INFO("console has been setup on %s", lxcpath);
 
1040
 
 
1041
        return 0;
 
1042
}
 
1043
 
 
1044
static int setup_console(const struct lxc_rootfs *rootfs,
 
1045
                         const struct lxc_console *console,
 
1046
                         char *ttydir)
 
1047
{
 
1048
        /* We don't have a rootfs, /dev/console will be shared */
 
1049
        if (!rootfs->path)
 
1050
                return 0;
 
1051
        if (!ttydir)
 
1052
                return setup_dev_console(rootfs, console);
 
1053
 
 
1054
        return setup_ttydir_console(rootfs, console, ttydir);
 
1055
}
 
1056
 
 
1057
static int setup_kmsg(const struct lxc_rootfs *rootfs,
 
1058
                       const struct lxc_console *console)
 
1059
{
 
1060
        char kpath[MAXPATHLEN];
 
1061
        int ret;
 
1062
 
 
1063
        ret = snprintf(kpath, sizeof(kpath), "%s/dev/kmsg", rootfs->mount);
 
1064
        if (ret < 0 || ret >= sizeof(kpath))
 
1065
                return -1;
 
1066
 
 
1067
        ret = unlink(kpath);
 
1068
        if (ret && errno != ENOENT) {
 
1069
                SYSERROR("error unlinking %s\n", kpath);
 
1070
                return -1;
 
1071
        }
 
1072
 
 
1073
        ret = symlink("console", kpath);
 
1074
        if (ret) {
 
1075
                SYSERROR("failed to create symlink for kmsg");
 
1076
                return -1;
 
1077
        }
 
1078
 
 
1079
        return 0;
 
1080
}
 
1081
 
 
1082
static int setup_cgroup(const char *name, struct lxc_list *cgroups)
 
1083
{
 
1084
        struct lxc_list *iterator;
 
1085
        struct lxc_cgroup *cg;
 
1086
        int ret = -1;
 
1087
 
 
1088
        if (lxc_list_empty(cgroups))
 
1089
                return 0;
 
1090
 
 
1091
        lxc_list_for_each(iterator, cgroups) {
 
1092
 
 
1093
                cg = iterator->elem;
 
1094
 
 
1095
                if (lxc_cgroup_set(name, cg->subsystem, cg->value))
 
1096
                        goto out;
 
1097
 
 
1098
                DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
 
1099
        }
 
1100
 
 
1101
        ret = 0;
 
1102
        INFO("cgroup has been setup");
 
1103
out:
 
1104
        return ret;
 
1105
}
 
1106
 
 
1107
static void parse_mntopt(char *opt, unsigned long *flags, char **data)
 
1108
{
 
1109
        struct mount_opt *mo;
 
1110
 
 
1111
        /* If opt is found in mount_opt, set or clear flags.
 
1112
         * Otherwise append it to data. */
 
1113
 
 
1114
        for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
 
1115
                if (!strncmp(opt, mo->name, strlen(mo->name))) {
 
1116
                        if (mo->clear)
 
1117
                                *flags &= ~mo->flag;
 
1118
                        else
 
1119
                                *flags |= mo->flag;
 
1120
                        return;
 
1121
                }
 
1122
        }
 
1123
 
 
1124
        if (strlen(*data))
 
1125
                strcat(*data, ",");
 
1126
        strcat(*data, opt);
 
1127
}
 
1128
 
 
1129
static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
 
1130
                         char **mntdata)
 
1131
{
 
1132
        char *s, *data;
 
1133
        char *p, *saveptr = NULL;
 
1134
 
 
1135
        *mntdata = NULL;
 
1136
        *mntflags = 0L;
 
1137
 
 
1138
        if (!mntopts)
 
1139
                return 0;
 
1140
 
 
1141
        s = strdup(mntopts);
 
1142
        if (!s) {
 
1143
                SYSERROR("failed to allocate memory");
 
1144
                return -1;
 
1145
        }
 
1146
 
 
1147
        data = malloc(strlen(s) + 1);
 
1148
        if (!data) {
 
1149
                SYSERROR("failed to allocate memory");
 
1150
                free(s);
 
1151
                return -1;
 
1152
        }
 
1153
        *data = 0;
 
1154
 
 
1155
        for (p = strtok_r(s, ",", &saveptr); p != NULL;
 
1156
             p = strtok_r(NULL, ",", &saveptr))
 
1157
                parse_mntopt(p, mntflags, &data);
 
1158
 
 
1159
        if (*data)
 
1160
                *mntdata = data;
 
1161
        else
 
1162
                free(data);
 
1163
        free(s);
 
1164
 
 
1165
        return 0;
 
1166
}
 
1167
 
 
1168
static int mount_entry(const char *fsname, const char *target,
 
1169
                       const char *fstype, unsigned long mountflags,
 
1170
                       const char *data)
 
1171
{
 
1172
        if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
 
1173
                SYSERROR("failed to mount '%s' on '%s'", fsname, target);
 
1174
                return -1;
 
1175
        }
 
1176
 
 
1177
        if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
 
1178
 
 
1179
                DEBUG("remounting %s on %s to respect bind or remount options",
 
1180
                      fsname, target);
 
1181
 
 
1182
                if (mount(fsname, target, fstype,
 
1183
                          mountflags | MS_REMOUNT, data)) {
 
1184
                        SYSERROR("failed to mount '%s' on '%s'",
 
1185
                                 fsname, target);
 
1186
                        return -1;
 
1187
                }
 
1188
        }
 
1189
 
 
1190
        DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
 
1191
 
 
1192
        return 0;
 
1193
}
 
1194
 
 
1195
static inline int mount_entry_on_systemfs(struct mntent *mntent)
 
1196
{
 
1197
        unsigned long mntflags;
 
1198
        char *mntdata;
 
1199
        int ret;
 
1200
 
 
1201
        if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
 
1202
                ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
 
1203
                return -1;
 
1204
        }
 
1205
 
 
1206
        ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
 
1207
                          mntent->mnt_type, mntflags, mntdata);
 
1208
 
 
1209
        free(mntdata);
 
1210
 
 
1211
        return ret;
 
1212
}
 
1213
 
 
1214
static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
 
1215
                                          const struct lxc_rootfs *rootfs,
 
1216
                                          const char *lxc_name)
 
1217
{
 
1218
        char *aux;
 
1219
        char path[MAXPATHLEN];
 
1220
        unsigned long mntflags;
 
1221
        char *mntdata;
 
1222
        int r, ret = 0, offset;
 
1223
 
 
1224
        if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
 
1225
                ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
 
1226
                return -1;
 
1227
        }
 
1228
 
 
1229
        /* if rootfs->path is a blockdev path, allow container fstab to
 
1230
         * use /var/lib/lxc/CN/rootfs as the target prefix */
 
1231
        r = snprintf(path, MAXPATHLEN, "/var/lib/lxc/%s/rootfs", lxc_name);
 
1232
        if (r < 0 || r >= MAXPATHLEN)
 
1233
                goto skipvarlib;
 
1234
 
 
1235
        aux = strstr(mntent->mnt_dir, path);
 
1236
        if (aux) {
 
1237
                offset = strlen(path);
 
1238
                goto skipabs;
 
1239
        }
 
1240
 
 
1241
skipvarlib:
 
1242
        aux = strstr(mntent->mnt_dir, rootfs->path);
 
1243
        if (!aux) {
 
1244
                WARN("ignoring mount point '%s'", mntent->mnt_dir);
 
1245
                goto out;
 
1246
        }
 
1247
        offset = strlen(rootfs->path);
 
1248
 
 
1249
skipabs:
 
1250
 
 
1251
        r = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
 
1252
                 aux + offset);
 
1253
        if (r < 0 || r >= MAXPATHLEN) {
 
1254
                WARN("pathnme too long for '%s'", mntent->mnt_dir);
 
1255
                ret = -1;
 
1256
                goto out;
 
1257
        }
 
1258
 
 
1259
 
 
1260
        ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
 
1261
                          mntflags, mntdata);
 
1262
 
 
1263
out:
 
1264
        free(mntdata);
 
1265
        return ret;
 
1266
}
 
1267
 
 
1268
static int mount_entry_on_relative_rootfs(struct mntent *mntent,
 
1269
                                          const char *rootfs)
 
1270
{
 
1271
        char path[MAXPATHLEN];
 
1272
        unsigned long mntflags;
 
1273
        char *mntdata;
 
1274
        int ret;
 
1275
 
 
1276
        if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
 
1277
                ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
 
1278
                return -1;
 
1279
        }
 
1280
 
 
1281
        /* relative to root mount point */
 
1282
        ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
 
1283
        if (ret >= sizeof(path)) {
 
1284
                ERROR("path name too long");
 
1285
                return -1;
 
1286
        }
 
1287
 
 
1288
        ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
 
1289
                          mntflags, mntdata);
 
1290
 
 
1291
        free(mntdata);
 
1292
 
 
1293
        return ret;
 
1294
}
 
1295
 
 
1296
static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file,
 
1297
        const char *lxc_name)
 
1298
{
 
1299
        struct mntent *mntent;
 
1300
        int ret = -1;
 
1301
 
 
1302
        while ((mntent = getmntent(file))) {
 
1303
 
 
1304
                if (!rootfs->path) {
 
1305
                        if (mount_entry_on_systemfs(mntent))
 
1306
                                goto out;
 
1307
                        continue;
 
1308
                }
 
1309
 
 
1310
                /* We have a separate root, mounts are relative to it */
 
1311
                if (mntent->mnt_dir[0] != '/') {
 
1312
                        if (mount_entry_on_relative_rootfs(mntent,
 
1313
                                                           rootfs->mount))
 
1314
                                goto out;
 
1315
                        continue;
 
1316
                }
 
1317
 
 
1318
                if (mount_entry_on_absolute_rootfs(mntent, rootfs, lxc_name))
 
1319
                        goto out;
 
1320
        }
 
1321
 
 
1322
        ret = 0;
 
1323
 
 
1324
        INFO("mount points have been setup");
 
1325
out:
 
1326
        return ret;
 
1327
}
 
1328
 
 
1329
static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
 
1330
        const char *lxc_name)
 
1331
{
 
1332
        FILE *file;
 
1333
        int ret;
 
1334
 
 
1335
        if (!fstab)
 
1336
                return 0;
 
1337
 
 
1338
        file = setmntent(fstab, "r");
 
1339
        if (!file) {
 
1340
                SYSERROR("failed to use '%s'", fstab);
 
1341
                return -1;
 
1342
        }
 
1343
 
 
1344
        ret = mount_file_entries(rootfs, file, lxc_name);
 
1345
 
 
1346
        endmntent(file);
 
1347
        return ret;
 
1348
}
 
1349
 
 
1350
static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount,
 
1351
        const char *lxc_name)
 
1352
{
 
1353
        FILE *file;
 
1354
        struct lxc_list *iterator;
 
1355
        char *mount_entry;
 
1356
        int ret;
 
1357
 
 
1358
        file = tmpfile();
 
1359
        if (!file) {
 
1360
                ERROR("tmpfile error: %m");
 
1361
                return -1;
 
1362
        }
 
1363
 
 
1364
        lxc_list_for_each(iterator, mount) {
 
1365
                mount_entry = iterator->elem;
 
1366
                fprintf(file, "%s\n", mount_entry);
 
1367
        }
 
1368
 
 
1369
        rewind(file);
 
1370
 
 
1371
        ret = mount_file_entries(rootfs, file, lxc_name);
 
1372
 
 
1373
        fclose(file);
 
1374
        return ret;
 
1375
}
 
1376
 
 
1377
static int setup_caps(struct lxc_list *caps)
 
1378
{
 
1379
        struct lxc_list *iterator;
 
1380
        char *drop_entry;
 
1381
        char *ptr;
 
1382
        int i, capid;
 
1383
 
 
1384
        lxc_list_for_each(iterator, caps) {
 
1385
 
 
1386
                drop_entry = iterator->elem;
 
1387
 
 
1388
                capid = -1;
 
1389
 
 
1390
                for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
 
1391
 
 
1392
                        if (strcmp(drop_entry, caps_opt[i].name))
 
1393
                                continue;
 
1394
 
 
1395
                        capid = caps_opt[i].value;
 
1396
                        break;
 
1397
                }
 
1398
 
 
1399
                if (capid < 0) {
 
1400
                        /* try to see if it's numeric, so the user may specify
 
1401
                        * capabilities  that the running kernel knows about but
 
1402
                        * we don't */
 
1403
                        capid = strtol(drop_entry, &ptr, 10);
 
1404
                        if (!ptr || *ptr != '\0' ||
 
1405
                        capid == LONG_MIN || capid == LONG_MAX)
 
1406
                                /* not a valid number */
 
1407
                                capid = -1;
 
1408
                        else if (capid > lxc_caps_last_cap())
 
1409
                                /* we have a number but it's not a valid
 
1410
                                * capability */
 
1411
                                capid = -1;
 
1412
                }
 
1413
 
 
1414
                if (capid < 0) {
 
1415
                        ERROR("unknown capability %s", drop_entry);
 
1416
                        return -1;
 
1417
                }
 
1418
 
 
1419
                DEBUG("drop capability '%s' (%d)", drop_entry, capid);
 
1420
 
 
1421
                if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
 
1422
                       SYSERROR("failed to remove %s capability", drop_entry);
 
1423
                       return -1;
 
1424
                }
 
1425
 
 
1426
        }
 
1427
 
 
1428
        DEBUG("capabilities has been setup");
 
1429
 
 
1430
        return 0;
 
1431
}
 
1432
 
 
1433
static int setup_hw_addr(char *hwaddr, const char *ifname)
 
1434
{
 
1435
        struct sockaddr sockaddr;
 
1436
        struct ifreq ifr;
 
1437
        int ret, fd;
 
1438
 
 
1439
        ret = lxc_convert_mac(hwaddr, &sockaddr);
 
1440
        if (ret) {
 
1441
                ERROR("mac address '%s' conversion failed : %s",
 
1442
                      hwaddr, strerror(-ret));
 
1443
                return -1;
 
1444
        }
 
1445
 
 
1446
        memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
 
1447
        memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
 
1448
 
 
1449
        fd = socket(AF_INET, SOCK_DGRAM, 0);
 
1450
        if (fd < 0) {
 
1451
                ERROR("socket failure : %s", strerror(errno));
 
1452
                return -1;
 
1453
        }
 
1454
 
 
1455
        ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
 
1456
        close(fd);
 
1457
        if (ret)
 
1458
                ERROR("ioctl failure : %s", strerror(errno));
 
1459
 
 
1460
        DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
 
1461
 
 
1462
        return ret;
 
1463
}
 
1464
 
 
1465
static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
 
1466
{
 
1467
        struct lxc_list *iterator;
 
1468
        struct lxc_inetdev *inetdev;
 
1469
        int err;
 
1470
 
 
1471
        lxc_list_for_each(iterator, ip) {
 
1472
 
 
1473
                inetdev = iterator->elem;
 
1474
 
 
1475
                err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
 
1476
                                        &inetdev->bcast, inetdev->prefix);
 
1477
                if (err) {
 
1478
                        ERROR("failed to setup_ipv4_addr ifindex %d : %s",
 
1479
                              ifindex, strerror(-err));
 
1480
                        return -1;
 
1481
                }
 
1482
        }
 
1483
 
 
1484
        return 0;
 
1485
}
 
1486
 
 
1487
static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
 
1488
{
 
1489
        struct lxc_list *iterator;
 
1490
        struct lxc_inet6dev *inet6dev;
 
1491
        int err;
 
1492
 
 
1493
        lxc_list_for_each(iterator, ip) {
 
1494
 
 
1495
                inet6dev = iterator->elem;
 
1496
 
 
1497
                err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
 
1498
                                        &inet6dev->mcast, &inet6dev->acast,
 
1499
                                        inet6dev->prefix);
 
1500
                if (err) {
 
1501
                        ERROR("failed to setup_ipv6_addr ifindex %d : %s",
 
1502
                              ifindex, strerror(-err));
 
1503
                        return -1;
 
1504
                }
 
1505
        }
 
1506
 
 
1507
        return 0;
 
1508
}
 
1509
 
 
1510
static int setup_netdev(struct lxc_netdev *netdev)
 
1511
{
 
1512
        char ifname[IFNAMSIZ];
 
1513
        char *current_ifname = ifname;
 
1514
        int err;
 
1515
 
 
1516
        /* empty network namespace */
 
1517
        if (!netdev->ifindex) {
 
1518
                if (netdev->flags & IFF_UP) {
 
1519
                        err = lxc_netdev_up("lo");
 
1520
                        if (err) {
 
1521
                                ERROR("failed to set the loopback up : %s",
 
1522
                                      strerror(-err));
 
1523
                                return -1;
 
1524
                        }
 
1525
                }
 
1526
                return 0;
 
1527
        }
 
1528
 
 
1529
        /* retrieve the name of the interface */
 
1530
        if (!if_indextoname(netdev->ifindex, current_ifname)) {
 
1531
                ERROR("no interface corresponding to index '%d'",
 
1532
                      netdev->ifindex);
 
1533
                return -1;
 
1534
        }
 
1535
 
 
1536
        /* default: let the system to choose one interface name */
 
1537
        if (!netdev->name)
 
1538
                netdev->name = netdev->type == LXC_NET_PHYS ?
 
1539
                        netdev->link : "eth%d";
 
1540
 
 
1541
        /* rename the interface name */
 
1542
        err = lxc_netdev_rename_by_name(ifname, netdev->name);
 
1543
        if (err) {
 
1544
                ERROR("failed to rename %s->%s : %s", ifname, netdev->name,
 
1545
                      strerror(-err));
 
1546
                return -1;
 
1547
        }
 
1548
 
 
1549
        /* Re-read the name of the interface because its name has changed
 
1550
         * and would be automatically allocated by the system
 
1551
         */
 
1552
        if (!if_indextoname(netdev->ifindex, current_ifname)) {
 
1553
                ERROR("no interface corresponding to index '%d'",
 
1554
                      netdev->ifindex);
 
1555
                return -1;
 
1556
        }
 
1557
 
 
1558
        /* set a mac address */
 
1559
        if (netdev->hwaddr) {
 
1560
                if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
 
1561
                        ERROR("failed to setup hw address for '%s'",
 
1562
                              current_ifname);
 
1563
                        return -1;
 
1564
                }
 
1565
        }
 
1566
 
 
1567
        /* setup ipv4 addresses on the interface */
 
1568
        if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
 
1569
                ERROR("failed to setup ip addresses for '%s'",
 
1570
                              ifname);
 
1571
                return -1;
 
1572
        }
 
1573
 
 
1574
        /* setup ipv6 addresses on the interface */
 
1575
        if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
 
1576
                ERROR("failed to setup ipv6 addresses for '%s'",
 
1577
                              ifname);
 
1578
                return -1;
 
1579
        }
 
1580
 
 
1581
        /* set the network device up */
 
1582
        if (netdev->flags & IFF_UP) {
 
1583
                int err;
 
1584
 
 
1585
                err = lxc_netdev_up(current_ifname);
 
1586
                if (err) {
 
1587
                        ERROR("failed to set '%s' up : %s", current_ifname,
 
1588
                              strerror(-err));
 
1589
                        return -1;
 
1590
                }
 
1591
 
 
1592
                /* the network is up, make the loopback up too */
 
1593
                err = lxc_netdev_up("lo");
 
1594
                if (err) {
 
1595
                        ERROR("failed to set the loopback up : %s",
 
1596
                              strerror(-err));
 
1597
                        return -1;
 
1598
                }
 
1599
        }
 
1600
 
 
1601
        /* We can only set up the default routes after bringing
 
1602
         * up the interface, sine bringing up the interface adds
 
1603
         * the link-local routes and we can't add a default
 
1604
         * route if the gateway is not reachable. */
 
1605
 
 
1606
        /* setup ipv4 gateway on the interface */
 
1607
        if (netdev->ipv4_gateway) {
 
1608
                if (!(netdev->flags & IFF_UP)) {
 
1609
                        ERROR("Cannot add ipv4 gateway for %s when not bringing up the interface", ifname);
 
1610
                        return -1;
 
1611
                }
 
1612
 
 
1613
                if (lxc_list_empty(&netdev->ipv4)) {
 
1614
                        ERROR("Cannot add ipv4 gateway for %s when not assigning an address", ifname);
 
1615
                        return -1;
 
1616
                }
 
1617
 
 
1618
                err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
 
1619
                if (err) {
 
1620
                        ERROR("failed to setup ipv4 gateway for '%s': %s",
 
1621
                                      ifname, strerror(-err));
 
1622
                        if (netdev->ipv4_gateway_auto) {
 
1623
                                char buf[INET_ADDRSTRLEN];
 
1624
                                inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
 
1625
                                ERROR("tried to set autodetected ipv4 gateway '%s'", buf);
 
1626
                        }
 
1627
                        return -1;
 
1628
                }
 
1629
        }
 
1630
 
 
1631
        /* setup ipv6 gateway on the interface */
 
1632
        if (netdev->ipv6_gateway) {
 
1633
                if (!(netdev->flags & IFF_UP)) {
 
1634
                        ERROR("Cannot add ipv6 gateway for %s when not bringing up the interface", ifname);
 
1635
                        return -1;
 
1636
                }
 
1637
 
 
1638
                if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
 
1639
                        ERROR("Cannot add ipv6 gateway for %s when not assigning an address", ifname);
 
1640
                        return -1;
 
1641
                }
 
1642
 
 
1643
                err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
 
1644
                if (err) {
 
1645
                        ERROR("failed to setup ipv6 gateway for '%s': %s",
 
1646
                                      ifname, strerror(-err));
 
1647
                        if (netdev->ipv6_gateway_auto) {
 
1648
                                char buf[INET6_ADDRSTRLEN];
 
1649
                                inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
 
1650
                                ERROR("tried to set autodetected ipv6 gateway '%s'", buf);
 
1651
                        }
 
1652
                        return -1;
 
1653
                }
 
1654
        }
 
1655
 
 
1656
        DEBUG("'%s' has been setup", current_ifname);
 
1657
 
 
1658
        return 0;
 
1659
}
 
1660
 
 
1661
static int setup_network(struct lxc_list *network)
 
1662
{
 
1663
        struct lxc_list *iterator;
 
1664
        struct lxc_netdev *netdev;
 
1665
 
 
1666
        lxc_list_for_each(iterator, network) {
 
1667
 
 
1668
                netdev = iterator->elem;
 
1669
 
 
1670
                if (setup_netdev(netdev)) {
 
1671
                        ERROR("failed to setup netdev");
 
1672
                        return -1;
 
1673
                }
 
1674
        }
 
1675
 
 
1676
        if (!lxc_list_empty(network))
 
1677
                INFO("network has been setup");
 
1678
 
 
1679
        return 0;
 
1680
}
 
1681
 
 
1682
static int setup_private_host_hw_addr(char *veth1)
 
1683
{
 
1684
        struct ifreq ifr;
 
1685
        int err;
 
1686
        int sockfd;
 
1687
 
 
1688
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 
1689
        if (sockfd < 0)
 
1690
                return -errno;
 
1691
 
 
1692
        snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
 
1693
        err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
 
1694
        if (err < 0) {
 
1695
                close(sockfd);
 
1696
                return -errno;
 
1697
        }
 
1698
 
 
1699
        ifr.ifr_hwaddr.sa_data[0] = 0xfe;
 
1700
        err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
 
1701
        close(sockfd);
 
1702
        if (err < 0)
 
1703
                return -errno;
 
1704
 
 
1705
        DEBUG("mac address of host interface '%s' changed to private "
 
1706
              "%02x:%02x:%02x:%02x:%02x:%02x", veth1,
 
1707
              ifr.ifr_hwaddr.sa_data[0] & 0xff,
 
1708
              ifr.ifr_hwaddr.sa_data[1] & 0xff,
 
1709
              ifr.ifr_hwaddr.sa_data[2] & 0xff,
 
1710
              ifr.ifr_hwaddr.sa_data[3] & 0xff,
 
1711
              ifr.ifr_hwaddr.sa_data[4] & 0xff,
 
1712
              ifr.ifr_hwaddr.sa_data[5] & 0xff);
 
1713
 
 
1714
        return 0;
 
1715
}
 
1716
 
 
1717
struct lxc_conf *lxc_conf_init(void)
 
1718
{
 
1719
        struct lxc_conf *new;
 
1720
        int i;
 
1721
 
 
1722
        new =   malloc(sizeof(*new));
 
1723
        if (!new) {
 
1724
                ERROR("lxc_conf_init : %m");
 
1725
                return NULL;
 
1726
        }
 
1727
        memset(new, 0, sizeof(*new));
 
1728
 
 
1729
        new->umount_proc = 0;
 
1730
        new->personality = -1;
 
1731
        new->console.path = NULL;
 
1732
        new->console.peer = -1;
 
1733
        new->console.master = -1;
 
1734
        new->console.slave = -1;
 
1735
        new->console.name[0] = '\0';
 
1736
        new->rootfs.mount = LXCROOTFSMOUNT;
 
1737
        lxc_list_init(&new->cgroup);
 
1738
        lxc_list_init(&new->network);
 
1739
        lxc_list_init(&new->mount_list);
 
1740
        lxc_list_init(&new->caps);
 
1741
        new->aa_profile = NULL;
 
1742
        for (i=0; i<NUM_LXC_HOOKS; i++)
 
1743
                lxc_list_init(&new->hooks[i]);
 
1744
 
 
1745
        return new;
 
1746
}
 
1747
 
 
1748
static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
 
1749
{
 
1750
        char veth1buf[IFNAMSIZ], *veth1;
 
1751
        char veth2buf[IFNAMSIZ], *veth2;
 
1752
        int err;
 
1753
 
 
1754
        if (netdev->priv.veth_attr.pair)
 
1755
                veth1 = netdev->priv.veth_attr.pair;
 
1756
        else {
 
1757
                err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
 
1758
                if (err >= sizeof(veth1buf)) { /* can't *really* happen, but... */
 
1759
                        ERROR("veth1 name too long");
 
1760
                        return -1;
 
1761
                }
 
1762
                veth1 = mktemp(veth1buf);
 
1763
        }
 
1764
 
 
1765
        snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
 
1766
        veth2 = mktemp(veth2buf);
 
1767
 
 
1768
        if (!strlen(veth1) || !strlen(veth2)) {
 
1769
                ERROR("failed to allocate a temporary name");
 
1770
                return -1;
 
1771
        }
 
1772
 
 
1773
        err = lxc_veth_create(veth1, veth2);
 
1774
        if (err) {
 
1775
                ERROR("failed to create %s-%s : %s", veth1, veth2,
 
1776
                      strerror(-err));
 
1777
                return -1;
 
1778
        }
 
1779
 
 
1780
        /* changing the high byte of the mac address to 0xfe, the bridge interface
 
1781
         * will always keep the host's mac address and not take the mac address
 
1782
         * of a container */
 
1783
        err = setup_private_host_hw_addr(veth1);
 
1784
        if (err) {
 
1785
                ERROR("failed to change mac address of host interface '%s' : %s",
 
1786
                        veth1, strerror(-err));
 
1787
                goto out_delete;
 
1788
        }
 
1789
 
 
1790
        if (netdev->mtu) {
 
1791
                err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
 
1792
                if (!err)
 
1793
                        err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
 
1794
                if (err) {
 
1795
                        ERROR("failed to set mtu '%s' for %s-%s : %s",
 
1796
                              netdev->mtu, veth1, veth2, strerror(-err));
 
1797
                        goto out_delete;
 
1798
                }
 
1799
        }
 
1800
 
 
1801
        if (netdev->link) {
 
1802
                err = lxc_bridge_attach(netdev->link, veth1);
 
1803
                if (err) {
 
1804
                        ERROR("failed to attach '%s' to the bridge '%s' : %s",
 
1805
                                      veth1, netdev->link, strerror(-err));
 
1806
                        goto out_delete;
 
1807
                }
 
1808
        }
 
1809
 
 
1810
        netdev->ifindex = if_nametoindex(veth2);
 
1811
        if (!netdev->ifindex) {
 
1812
                ERROR("failed to retrieve the index for %s", veth2);
 
1813
                goto out_delete;
 
1814
        }
 
1815
 
 
1816
        err = lxc_netdev_up(veth1);
 
1817
        if (err) {
 
1818
                ERROR("failed to set %s up : %s", veth1, strerror(-err));
 
1819
                goto out_delete;
 
1820
        }
 
1821
 
 
1822
        if (netdev->upscript) {
 
1823
                err = run_script(handler->name, "net", netdev->upscript, "up",
 
1824
                                 "veth", veth1, (char*) NULL);
 
1825
                if (err)
 
1826
                        goto out_delete;
 
1827
        }
 
1828
 
 
1829
        DEBUG("instanciated veth '%s/%s', index is '%d'",
 
1830
              veth1, veth2, netdev->ifindex);
 
1831
 
 
1832
        return 0;
 
1833
 
 
1834
out_delete:
 
1835
        lxc_netdev_delete_by_name(veth1);
 
1836
        return -1;
 
1837
}
 
1838
 
 
1839
static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 
1840
{
 
1841
        char peerbuf[IFNAMSIZ], *peer;
 
1842
        int err;
 
1843
 
 
1844
        if (!netdev->link) {
 
1845
                ERROR("no link specified for macvlan netdev");
 
1846
                return -1;
 
1847
        }
 
1848
 
 
1849
        err = snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
 
1850
        if (err >= sizeof(peerbuf))
 
1851
                return -1;
 
1852
 
 
1853
        peer = mktemp(peerbuf);
 
1854
        if (!strlen(peer)) {
 
1855
                ERROR("failed to make a temporary name");
 
1856
                return -1;
 
1857
        }
 
1858
 
 
1859
        err = lxc_macvlan_create(netdev->link, peer,
 
1860
                                 netdev->priv.macvlan_attr.mode);
 
1861
        if (err) {
 
1862
                ERROR("failed to create macvlan interface '%s' on '%s' : %s",
 
1863
                      peer, netdev->link, strerror(-err));
 
1864
                return -1;
 
1865
        }
 
1866
 
 
1867
        netdev->ifindex = if_nametoindex(peer);
 
1868
        if (!netdev->ifindex) {
 
1869
                ERROR("failed to retrieve the index for %s", peer);
 
1870
                lxc_netdev_delete_by_name(peer);
 
1871
                return -1;
 
1872
        }
 
1873
 
 
1874
        if (netdev->upscript) {
 
1875
                err = run_script(handler->name, "net", netdev->upscript, "up",
 
1876
                                 "macvlan", netdev->link, (char*) NULL);
 
1877
                if (err)
 
1878
                        return -1;
 
1879
        }
 
1880
 
 
1881
        DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
 
1882
              peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
 
1883
 
 
1884
        return 0;
 
1885
}
 
1886
 
 
1887
/* XXX: merge with instanciate_macvlan */
 
1888
static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 
1889
{
 
1890
        char peer[IFNAMSIZ];
 
1891
        int err;
 
1892
 
 
1893
        if (!netdev->link) {
 
1894
                ERROR("no link specified for vlan netdev");
 
1895
                return -1;
 
1896
        }
 
1897
 
 
1898
        err = snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
 
1899
        if (err >= sizeof(peer)) {
 
1900
                ERROR("peer name too long");
 
1901
                return -1;
 
1902
        }
 
1903
 
 
1904
        err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
 
1905
        if (err) {
 
1906
                ERROR("failed to create vlan interface '%s' on '%s' : %s",
 
1907
                      peer, netdev->link, strerror(-err));
 
1908
                return -1;
 
1909
        }
 
1910
 
 
1911
        netdev->ifindex = if_nametoindex(peer);
 
1912
        if (!netdev->ifindex) {
 
1913
                ERROR("failed to retrieve the ifindex for %s", peer);
 
1914
                lxc_netdev_delete_by_name(peer);
 
1915
                return -1;
 
1916
        }
 
1917
 
 
1918
        DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
 
1919
              netdev->ifindex);
 
1920
 
 
1921
        return 0;
 
1922
}
 
1923
 
 
1924
static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
 
1925
{
 
1926
        if (!netdev->link) {
 
1927
                ERROR("no link specified for the physical interface");
 
1928
                return -1;
 
1929
        }
 
1930
 
 
1931
        netdev->ifindex = if_nametoindex(netdev->link);
 
1932
        if (!netdev->ifindex) {
 
1933
                ERROR("failed to retrieve the index for %s", netdev->link);
 
1934
                return -1;
 
1935
        }
 
1936
 
 
1937
        if (netdev->upscript) {
 
1938
                int err;
 
1939
                err = run_script(handler->name, "net", netdev->upscript,
 
1940
                                 "up", "phys", netdev->link, (char*) NULL);
 
1941
                if (err)
 
1942
                        return -1;
 
1943
        }
 
1944
 
 
1945
        return 0;
 
1946
}
 
1947
 
 
1948
static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
 
1949
{
 
1950
        netdev->ifindex = 0;
 
1951
        if (netdev->upscript) {
 
1952
                int err;
 
1953
                err = run_script(handler->name, "net", netdev->upscript,
 
1954
                                 "up", "empty", (char*) NULL);
 
1955
                if (err)
 
1956
                        return -1;
 
1957
        }
 
1958
        return 0;
 
1959
}
 
1960
 
 
1961
int lxc_create_network(struct lxc_handler *handler)
 
1962
{
 
1963
        struct lxc_list *network = &handler->conf->network;
 
1964
        struct lxc_list *iterator;
 
1965
        struct lxc_netdev *netdev;
 
1966
 
 
1967
        lxc_list_for_each(iterator, network) {
 
1968
 
 
1969
                netdev = iterator->elem;
 
1970
 
 
1971
                if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
 
1972
                        ERROR("invalid network configuration type '%d'",
 
1973
                              netdev->type);
 
1974
                        return -1;
 
1975
                }
 
1976
 
 
1977
                if (netdev_conf[netdev->type](handler, netdev)) {
 
1978
                        ERROR("failed to create netdev");
 
1979
                        return -1;
 
1980
                }
 
1981
 
 
1982
        }
 
1983
 
 
1984
        return 0;
 
1985
}
 
1986
 
 
1987
void lxc_delete_network(struct lxc_list *network)
 
1988
{
 
1989
        struct lxc_list *iterator;
 
1990
        struct lxc_netdev *netdev;
 
1991
 
 
1992
        lxc_list_for_each(iterator, network) {
 
1993
                netdev = iterator->elem;
 
1994
                if (netdev->ifindex == 0)
 
1995
                        continue;
 
1996
 
 
1997
                if (netdev->type == LXC_NET_PHYS) {
 
1998
                        if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
 
1999
                                WARN("failed to rename to the initial name the " \
 
2000
                                     "netdev '%s'", netdev->link);
 
2001
                        continue;
 
2002
                }
 
2003
 
 
2004
                /* Recent kernel remove the virtual interfaces when the network
 
2005
                 * namespace is destroyed but in case we did not moved the
 
2006
                 * interface to the network namespace, we have to destroy it
 
2007
                 */
 
2008
                if (lxc_netdev_delete_by_index(netdev->ifindex))
 
2009
                        WARN("failed to remove interface '%s'", netdev->name);
 
2010
        }
 
2011
}
 
2012
 
 
2013
int lxc_assign_network(struct lxc_list *network, pid_t pid)
 
2014
{
 
2015
        struct lxc_list *iterator;
 
2016
        struct lxc_netdev *netdev;
 
2017
        int err;
 
2018
 
 
2019
        lxc_list_for_each(iterator, network) {
 
2020
 
 
2021
                netdev = iterator->elem;
 
2022
 
 
2023
                /* empty network namespace, nothing to move */
 
2024
                if (!netdev->ifindex)
 
2025
                        continue;
 
2026
 
 
2027
                err = lxc_netdev_move_by_index(netdev->ifindex, pid);
 
2028
                if (err) {
 
2029
                        ERROR("failed to move '%s' to the container : %s",
 
2030
                              netdev->link, strerror(-err));
 
2031
                        return -1;
 
2032
                }
 
2033
 
 
2034
                DEBUG("move '%s' to '%d'", netdev->name, pid);
 
2035
        }
 
2036
 
 
2037
        return 0;
 
2038
}
 
2039
 
 
2040
int lxc_find_gateway_addresses(struct lxc_handler *handler)
 
2041
{
 
2042
        struct lxc_list *network = &handler->conf->network;
 
2043
        struct lxc_list *iterator;
 
2044
        struct lxc_netdev *netdev;
 
2045
        int link_index;
 
2046
 
 
2047
        lxc_list_for_each(iterator, network) {
 
2048
                netdev = iterator->elem;
 
2049
 
 
2050
                if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto)
 
2051
                        continue;
 
2052
 
 
2053
                if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) {
 
2054
                        ERROR("gateway = auto only supported for "
 
2055
                              "veth and macvlan");
 
2056
                        return -1;
 
2057
                }
 
2058
 
 
2059
                if (!netdev->link) {
 
2060
                        ERROR("gateway = auto needs a link interface");
 
2061
                        return -1;
 
2062
                }
 
2063
 
 
2064
                link_index = if_nametoindex(netdev->link);
 
2065
                if (!link_index)
 
2066
                        return -EINVAL;
 
2067
 
 
2068
                if (netdev->ipv4_gateway_auto) {
 
2069
                        if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) {
 
2070
                                ERROR("failed to automatically find ipv4 gateway "
 
2071
                                      "address from link interface '%s'", netdev->link);
 
2072
                                return -1;
 
2073
                        }
 
2074
                }
 
2075
 
 
2076
                if (netdev->ipv6_gateway_auto) {
 
2077
                        if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) {
 
2078
                                ERROR("failed to automatically find ipv6 gateway "
 
2079
                                      "address from link interface '%s'", netdev->link);
 
2080
                                return -1;
 
2081
                        }
 
2082
                }
 
2083
        }
 
2084
 
 
2085
        return 0;
 
2086
}
 
2087
 
 
2088
int lxc_create_tty(const char *name, struct lxc_conf *conf)
 
2089
{
 
2090
        struct lxc_tty_info *tty_info = &conf->tty_info;
 
2091
        int i;
 
2092
 
 
2093
        /* no tty in the configuration */
 
2094
        if (!conf->tty)
 
2095
                return 0;
 
2096
 
 
2097
        tty_info->pty_info =
 
2098
                malloc(sizeof(*tty_info->pty_info)*conf->tty);
 
2099
        if (!tty_info->pty_info) {
 
2100
                SYSERROR("failed to allocate pty_info");
 
2101
                return -1;
 
2102
        }
 
2103
 
 
2104
        for (i = 0; i < conf->tty; i++) {
 
2105
 
 
2106
                struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
 
2107
 
 
2108
                if (openpty(&pty_info->master, &pty_info->slave,
 
2109
                            pty_info->name, NULL, NULL)) {
 
2110
                        SYSERROR("failed to create pty #%d", i);
 
2111
                        tty_info->nbtty = i;
 
2112
                        lxc_delete_tty(tty_info);
 
2113
                        return -1;
 
2114
                }
 
2115
 
 
2116
                DEBUG("allocated pty '%s' (%d/%d)",
 
2117
                      pty_info->name, pty_info->master, pty_info->slave);
 
2118
 
 
2119
                /* Prevent leaking the file descriptors to the container */
 
2120
                fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
 
2121
                fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
 
2122
 
 
2123
                pty_info->busy = 0;
 
2124
        }
 
2125
 
 
2126
        tty_info->nbtty = conf->tty;
 
2127
 
 
2128
        INFO("tty's configured");
 
2129
 
 
2130
        return 0;
 
2131
}
 
2132
 
 
2133
void lxc_delete_tty(struct lxc_tty_info *tty_info)
 
2134
{
 
2135
        int i;
 
2136
 
 
2137
        for (i = 0; i < tty_info->nbtty; i++) {
 
2138
                struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
 
2139
 
 
2140
                close(pty_info->master);
 
2141
                close(pty_info->slave);
 
2142
        }
 
2143
 
 
2144
        free(tty_info->pty_info);
 
2145
        tty_info->nbtty = 0;
 
2146
}
 
2147
 
 
2148
/*
 
2149
 * make sure /proc/self exists, and points to '1', since we are the
 
2150
 * container init.
 
2151
 * Else mount /proc.  Return 0 if proc was
 
2152
 * already mounted, 1 if we mounted it, -1 if we failed.
 
2153
 */
 
2154
static int mount_proc_if_needed(char *root_src, char *rootfs_tgt)
 
2155
{
 
2156
        char path[MAXPATHLEN];
 
2157
        char link[20];
 
2158
        int linklen, ret;
 
2159
 
 
2160
        ret = snprintf(path, MAXPATHLEN, "%s/proc/self", root_src ? rootfs_tgt : "");
 
2161
        if (ret < 0 || ret >= MAXPATHLEN) {
 
2162
                SYSERROR("proc path name too long");
 
2163
                return -1;
 
2164
        }
 
2165
        memset(link, 0, 20);
 
2166
        linklen = readlink(path, link, 20);
 
2167
        INFO("I am %d, /proc/self points to %s\n", getpid(), link);
 
2168
        ret = snprintf(path, MAXPATHLEN, "%s/proc", root_src ? rootfs_tgt : "");
 
2169
        if (linklen < 0) /* /proc not mounted */
 
2170
                goto domount;
 
2171
        /* can't be longer than rootfs/proc/1 */
 
2172
        if (strncmp(link, "1", linklen) != 0) {
 
2173
                /* wrong /procs mounted */
 
2174
                umount2(path, MNT_DETACH); /* ignore failure */
 
2175
                goto domount;
 
2176
        }
 
2177
        /* the right proc is already mounted */
 
2178
        return 0;
 
2179
 
 
2180
domount:
 
2181
        if (mount("proc", path, "proc", 0, NULL))
 
2182
                return -1;
 
2183
        INFO("Mounted /proc for the container\n");
 
2184
        return 1;
 
2185
}
 
2186
 
 
2187
int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
 
2188
{
 
2189
        int mounted;
 
2190
 
 
2191
        if (setup_utsname(lxc_conf->utsname)) {
 
2192
                ERROR("failed to setup the utsname for '%s'", name);
 
2193
                return -1;
 
2194
        }
 
2195
 
 
2196
        if (setup_network(&lxc_conf->network)) {
 
2197
                ERROR("failed to setup the network for '%s'", name);
 
2198
                return -1;
 
2199
        }
 
2200
 
 
2201
        if (run_lxc_hooks(name, "pre-mount", lxc_conf)) {
 
2202
                ERROR("failed to run pre-mount hooks for container '%s'.", name);
 
2203
                return -1;
 
2204
        }
 
2205
 
 
2206
        if (setup_rootfs(&lxc_conf->rootfs)) {
 
2207
                ERROR("failed to setup rootfs for '%s'", name);
 
2208
                return -1;
 
2209
        }
 
2210
 
 
2211
        if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name)) {
 
2212
                ERROR("failed to setup the mounts for '%s'", name);
 
2213
                return -1;
 
2214
        }
 
2215
 
 
2216
        if (setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list, name)) {
 
2217
                ERROR("failed to setup the mount entries for '%s'", name);
 
2218
                return -1;
 
2219
        }
 
2220
 
 
2221
        if (setup_cgroup(name, &lxc_conf->cgroup)) {
 
2222
                ERROR("failed to setup the cgroups for '%s'", name);
 
2223
                return -1;
 
2224
        }
 
2225
        if (run_lxc_hooks(name, "mount", lxc_conf)) {
 
2226
                ERROR("failed to run mount hooks for container '%s'.", name);
 
2227
                return -1;
 
2228
        }
 
2229
 
 
2230
        if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
 
2231
                ERROR("failed to setup the console for '%s'", name);
 
2232
                return -1;
 
2233
        }
 
2234
 
 
2235
        if (setup_kmsg(&lxc_conf->rootfs, &lxc_conf->console)) {
 
2236
                ERROR("failed to setup kmsg for '%s'", name);
 
2237
                return -1;
 
2238
        }
 
2239
 
 
2240
        if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info, lxc_conf->ttydir)) {
 
2241
                ERROR("failed to setup the ttys for '%s'", name);
 
2242
                return -1;
 
2243
        }
 
2244
 
 
2245
        /* aa_change_onexec makes more sense since we want to transition when
 
2246
         * /sbin/init is exec'd.  But the transitions doesn't seem to work
 
2247
         * then (refused).  aa_change_onexec will work since we're doing it
 
2248
         * right before the exec, so we'll just use that for now.
 
2249
         * In case the container fstab didn't mount /proc, we mount it.
 
2250
         */
 
2251
        INFO("rootfs path is .%s., mount is .%s.", lxc_conf->rootfs.path,
 
2252
                lxc_conf->rootfs.mount);
 
2253
 
 
2254
        mounted = mount_proc_if_needed(lxc_conf->rootfs.path, lxc_conf->rootfs.mount);
 
2255
        if (mounted == -1) {
 
2256
                SYSERROR("failed to mount /proc in the container.");
 
2257
                return -1;
 
2258
        } else if (mounted == 1) {
 
2259
                lxc_conf->umount_proc = 1;
 
2260
        }
 
2261
 
 
2262
        if (setup_pivot_root(&lxc_conf->rootfs)) {
 
2263
                ERROR("failed to set rootfs for '%s'", name);
 
2264
                return -1;
 
2265
        }
 
2266
 
 
2267
        if (setup_pts(lxc_conf->pts)) {
 
2268
                ERROR("failed to setup the new pts instance");
 
2269
                return -1;
 
2270
        }
 
2271
 
 
2272
        if (setup_personality(lxc_conf->personality)) {
 
2273
                ERROR("failed to setup personality");
 
2274
                return -1;
 
2275
        }
 
2276
 
 
2277
        if (setup_caps(&lxc_conf->caps)) {
 
2278
                ERROR("failed to drop capabilities");
 
2279
                return -1;
 
2280
        }
 
2281
 
 
2282
        NOTICE("'%s' is setup.", name);
 
2283
 
 
2284
        return 0;
 
2285
}
 
2286
 
 
2287
int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf)
 
2288
{
 
2289
        int which = -1;
 
2290
        struct lxc_list *it;
 
2291
 
 
2292
        if (strcmp(hook, "pre-start") == 0)
 
2293
                which = LXCHOOK_PRESTART;
 
2294
        else if (strcmp(hook, "pre-mount") == 0)
 
2295
                which = LXCHOOK_PREMOUNT;
 
2296
        else if (strcmp(hook, "mount") == 0)
 
2297
                which = LXCHOOK_MOUNT;
 
2298
        else if (strcmp(hook, "start") == 0)
 
2299
                which = LXCHOOK_START;
 
2300
        else if (strcmp(hook, "post-stop") == 0)
 
2301
                which = LXCHOOK_POSTSTOP;
 
2302
        else
 
2303
                return -1;
 
2304
        lxc_list_for_each(it, &conf->hooks[which]) {
 
2305
                int ret;
 
2306
                char *hookname = it->elem;
 
2307
                ret = run_script(name, "lxc", hookname, hook, NULL);
 
2308
                if (ret)
 
2309
                        return ret;
 
2310
        }
 
2311
        return 0;
 
2312
}
 
2313
 
 
2314
static void lxc_remove_nic(struct lxc_list *it)
 
2315
{
 
2316
        struct lxc_netdev *netdev = it->elem;
 
2317
        struct lxc_list *it2;
 
2318
 
 
2319
        lxc_list_del(it);
 
2320
 
 
2321
        if (netdev->link)
 
2322
                free(netdev->link);
 
2323
        if (netdev->name)
 
2324
                free(netdev->name);
 
2325
        if (netdev->upscript)
 
2326
                free(netdev->upscript);
 
2327
        if (netdev->hwaddr)
 
2328
                free(netdev->hwaddr);
 
2329
        if (netdev->mtu)
 
2330
                free(netdev->mtu);
 
2331
        if (netdev->ipv4_gateway)
 
2332
                free(netdev->ipv4_gateway);
 
2333
        if (netdev->ipv6_gateway)
 
2334
                free(netdev->ipv6_gateway);
 
2335
        lxc_list_for_each(it2, &netdev->ipv4) {
 
2336
                lxc_list_del(it2);
 
2337
                free(it2->elem);
 
2338
                free(it2);
 
2339
        }
 
2340
        lxc_list_for_each(it2, &netdev->ipv6) {
 
2341
                lxc_list_del(it2);
 
2342
                free(it2->elem);
 
2343
                free(it2);
 
2344
        }
 
2345
        free(it);
 
2346
}
 
2347
 
 
2348
/* we get passed in something like '0', '0.ipv4' or '1.ipv6' */
 
2349
int lxc_clear_nic(struct lxc_conf *c, char *key)
 
2350
{
 
2351
        char *p1;
 
2352
        int ret, idx, i;
 
2353
        struct lxc_list *it;
 
2354
        struct lxc_netdev *netdev;
 
2355
 
 
2356
        p1 = index(key, '.');
 
2357
        if (!p1 || *(p1+1) == '\0')
 
2358
                p1 = NULL;
 
2359
 
 
2360
        ret = sscanf(key, "%d", &idx);
 
2361
        if (ret != 1) return -1;
 
2362
        if (idx < 0)
 
2363
                return -1;
 
2364
 
 
2365
        i = 0;
 
2366
        lxc_list_for_each(it, &c->network) {
 
2367
                if (i == idx)
 
2368
                        break;
 
2369
                i++;
 
2370
        }
 
2371
        if (i < idx)  // we don't have that many nics defined
 
2372
                return -1;
 
2373
 
 
2374
        if (!it || !it->elem)
 
2375
                return -1;
 
2376
 
 
2377
        netdev = it->elem;
 
2378
 
 
2379
        if (!p1) {
 
2380
                lxc_remove_nic(it);
 
2381
        } else if (strcmp(p1, "ipv4") == 0) {
 
2382
                struct lxc_list *it2;
 
2383
                lxc_list_for_each(it2, &netdev->ipv4) {
 
2384
                        lxc_list_del(it2);
 
2385
                        free(it2->elem);
 
2386
                        free(it2);
 
2387
                }
 
2388
        } else if (strcmp(p1, "ipv6") == 0) {
 
2389
                struct lxc_list *it2;
 
2390
                lxc_list_for_each(it2, &netdev->ipv6) {
 
2391
                        lxc_list_del(it2);
 
2392
                        free(it2->elem);
 
2393
                        free(it2);
 
2394
                }
 
2395
        } else if (strcmp(p1, "link") == 0) {
 
2396
                if (netdev->link) {
 
2397
                        free(netdev->link);
 
2398
                        netdev->link = NULL;
 
2399
                }
 
2400
        } else if (strcmp(p1, "name") == 0) {
 
2401
                if (netdev->name) {
 
2402
                        free(netdev->name);
 
2403
                        netdev->name = NULL;
 
2404
                }
 
2405
        } else if (strcmp(p1, "script.up") == 0) {
 
2406
                if (netdev->upscript) {
 
2407
                        free(netdev->upscript);
 
2408
                        netdev->upscript = NULL;
 
2409
                }
 
2410
        } else if (strcmp(p1, "hwaddr") == 0) {
 
2411
                if (netdev->hwaddr) {
 
2412
                        free(netdev->hwaddr);
 
2413
                        netdev->hwaddr = NULL;
 
2414
                }
 
2415
        } else if (strcmp(p1, "mtu") == 0) {
 
2416
                if (netdev->mtu) {
 
2417
                        free(netdev->mtu);
 
2418
                        netdev->mtu = NULL;
 
2419
                }
 
2420
        } else if (strcmp(p1, "ipv4_gateway") == 0) {
 
2421
                if (netdev->ipv4_gateway) {
 
2422
                        free(netdev->ipv4_gateway);
 
2423
                        netdev->ipv4_gateway = NULL;
 
2424
                }
 
2425
        } else if (strcmp(p1, "ipv6_gateway") == 0) {
 
2426
                if (netdev->ipv6_gateway) {
 
2427
                        free(netdev->ipv6_gateway);
 
2428
                        netdev->ipv6_gateway = NULL;
 
2429
                }
 
2430
        }
 
2431
                else return -1;
 
2432
 
 
2433
        return 0;
 
2434
}
 
2435
 
 
2436
int lxc_clear_config_network(struct lxc_conf *c)
 
2437
{
 
2438
        struct lxc_list *it;
 
2439
        lxc_list_for_each(it, &c->network) {
 
2440
                lxc_remove_nic(it);
 
2441
        }
 
2442
        return 0;
 
2443
}
 
2444
 
 
2445
int lxc_clear_config_caps(struct lxc_conf *c)
 
2446
{
 
2447
        struct lxc_list *it;
 
2448
 
 
2449
        lxc_list_for_each(it, &c->caps) {
 
2450
                lxc_list_del(it);
 
2451
                free(it->elem);
 
2452
                free(it);
 
2453
        }
 
2454
        return 0;
 
2455
}
 
2456
 
 
2457
int lxc_clear_cgroups(struct lxc_conf *c, char *key)
 
2458
{
 
2459
        struct lxc_list *it;
 
2460
        bool all = false;
 
2461
        char *k = key + 11;
 
2462
 
 
2463
        if (strcmp(key, "lxc.cgroup") == 0)
 
2464
                all = true;
 
2465
 
 
2466
        lxc_list_for_each(it, &c->cgroup) {
 
2467
                struct lxc_cgroup *cg = it->elem;
 
2468
                if (!all && strcmp(cg->subsystem, k) != 0)
 
2469
                        continue;
 
2470
                lxc_list_del(it);
 
2471
                free(cg->subsystem);
 
2472
                free(cg->value);
 
2473
                free(cg);
 
2474
                free(it);
 
2475
        }
 
2476
        return 0;
 
2477
}
 
2478
 
 
2479
int lxc_clear_mount_entries(struct lxc_conf *c)
 
2480
{
 
2481
        struct lxc_list *it;
 
2482
 
 
2483
        lxc_list_for_each(it, &c->mount_list) {
 
2484
                lxc_list_del(it);
 
2485
                free(it->elem);
 
2486
                free(it);
 
2487
        }
 
2488
        return 0;
 
2489
}
 
2490
 
 
2491
int lxc_clear_hooks(struct lxc_conf *c, char *key)
 
2492
{
 
2493
        struct lxc_list *it;
 
2494
        bool all = false, done = false;
 
2495
        char *k = key + 9;
 
2496
        int i;
 
2497
 
 
2498
        if (strcmp(key, "lxc.hook") == 0)
 
2499
                all = true;
 
2500
 
 
2501
        for (i=0; i<NUM_LXC_HOOKS; i++) {
 
2502
                if (all || strcmp(k, lxchook_names[i]) == 0) {
 
2503
                        lxc_list_for_each(it, &c->hooks[i]) {
 
2504
                                lxc_list_del(it);
 
2505
                                free(it->elem);
 
2506
                                free(it);
 
2507
                        }
 
2508
                        done = true;
 
2509
                }
 
2510
        }
 
2511
 
 
2512
        if (!done) {
 
2513
                ERROR("Invalid hook key: %s", key);
 
2514
                return -1;
 
2515
        }
 
2516
        return 0;
 
2517
}
 
2518
 
 
2519
void lxc_conf_free(struct lxc_conf *conf)
 
2520
{
 
2521
        if (!conf)
 
2522
                return;
 
2523
        if (conf->console.path)
 
2524
                free(conf->console.path);
 
2525
        if (conf->rootfs.mount != LXCROOTFSMOUNT)
 
2526
                free(conf->rootfs.mount);
 
2527
        lxc_clear_config_network(conf);
 
2528
        if (conf->aa_profile)
 
2529
                free(conf->aa_profile);
 
2530
        lxc_clear_config_caps(conf);
 
2531
        lxc_clear_cgroups(conf, "lxc.cgroup");
 
2532
        lxc_clear_hooks(conf, "lxc.hook");
 
2533
        lxc_clear_mount_entries(conf);
 
2534
        free(conf);
 
2535
}