[lxc-devel] [PATCH 1/1] apparmor: auto-generate the blacklist rules (v2)

Stéphane Graber stgraber at ubuntu.com
Tue Apr 1 17:50:22 UTC 2014


On Fri, Mar 28, 2014 at 09:05:31PM -0500, Serge Hallyn wrote:
> This uses the generate-apparmor-rules.py script I sent out some time
> ago to auto-generate apparmor rules based on a higher level set of
> block/allow rules.
> 
> Add apparmor policy testcase to make sure that some of the paths we
> expect to be denied (and allowed) write access to are in fact in
> effect in the final policy.
> 
> With this policy, libvirt in a container is able to start its
> default network, which previously it could not.
> 
> v2: address feedback from stgraber
> 	. put lxc-generate-aa-rules.py into EXTRA_DIST
> 	. add lxc-test-apparmor, container-base and container-rules to .gitignore
> 	. take lxc-test-apparmor out of EXTRA_DIST
> 	. make lxc-generate-aa-rules.py pep8-compliant
> 	. don't automatically generate apparmor rules
> 	  This is only bc we can't be guaranteed that python3 will be
> 	  available.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Acked-by: Stéphane Graber <stgraber at ubuntu.com>

> ---
>  .gitignore                                     |   1 +
>  config/apparmor/Makefile.am                    |   3 +-
>  config/apparmor/README                         |  12 ++
>  config/apparmor/abstractions/container-base    |  51 ++++++-
>  config/apparmor/abstractions/container-base.in |  45 ++++++
>  config/apparmor/container-rules                |  43 ++++++
>  config/apparmor/container-rules.base           |  10 ++
>  config/apparmor/lxc-generate-aa-rules.py       | 135 ++++++++++++++++++
>  src/tests/Makefile.am                          |   4 +-
>  src/tests/aa.c                                 | 190 +++++++++++++++++++++++++
>  10 files changed, 485 insertions(+), 9 deletions(-)
>  create mode 100644 config/apparmor/README
>  create mode 100644 config/apparmor/abstractions/container-base.in
>  create mode 100644 config/apparmor/container-rules
>  create mode 100644 config/apparmor/container-rules.base
>  create mode 100755 config/apparmor/lxc-generate-aa-rules.py
>  create mode 100644 src/tests/aa.c
> 
> diff --git a/.gitignore b/.gitignore
> index df55240..2ee10b1 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -79,6 +79,7 @@ src/python-lxc/lxc/__pycache__/
>  
>  src/tests/lxc-test-device-add-remove
>  src/tests/lxc-test-attach
> +src/tests/lxc-test-aparmor
>  src/tests/lxc-test-cgpath
>  src/tests/lxc-test-clonetest
>  src/tests/lxc-test-concurrent
> diff --git a/config/apparmor/Makefile.am b/config/apparmor/Makefile.am
> index 801866d..7ac2bd2 100644
> --- a/config/apparmor/Makefile.am
> +++ b/config/apparmor/Makefile.am
> @@ -5,7 +5,8 @@ EXTRA_DIST = \
>  	profiles/lxc-default-with-mounting \
>  	profiles/lxc-default-with-nesting \
>  	lxc-containers \
> -	usr.bin.lxc-start
> +	usr.bin.lxc-start \
> +	lxc-generate-aa-rules.py
>  
>  if ENABLE_APPARMOR
>  install-apparmor:
> diff --git a/config/apparmor/README b/config/apparmor/README
> new file mode 100644
> index 0000000..432956b
> --- /dev/null
> +++ b/config/apparmor/README
> @@ -0,0 +1,12 @@
> +The abstractions/container-base file is partially automatically
> +generated.  The two source files are container-rules.base and
> +abstractions/container-base.in.  If these file are updated,
> +then
> +
> +1. Generate a new container-rules file using
> +
> +./lxc-generate-aa-rules.py container-rules.base > container-rules
> +
> +2. Concatenate container-base.in with container-rules using
> +
> +cat abstractions/container-base.in container-rules > abstractions/container-base
> diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
> index d1cd84a..d094aab 100644
> --- a/config/apparmor/abstractions/container-base
> +++ b/config/apparmor/abstractions/container-base
> @@ -30,8 +30,6 @@
>    deny @{PROC}/sysrq-trigger rwklx,
>    deny @{PROC}/mem rwklx,
>    deny @{PROC}/kmem rwklx,
> -  deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx,
> -  deny @{PROC}/sys/kernel/*/** wklx,
>  
>    # deny writes in /sys except for /sys/fs/cgroup, also allow
>    # fusectl, securityfs and debugfs to be mounted there (read-only)
> @@ -41,11 +39,50 @@
>    deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
>    mount fstype=proc -> /proc/,
>    mount fstype=sysfs -> /sys/,
> -  deny /sys/[^f]*/** wklx,
> -  deny /sys/f[^s]*/** wklx,
> -  deny /sys/fs/[^c]*/** wklx,
> -  deny /sys/fs/c[^g]*/** wklx,
> -  deny /sys/fs/cg[^r]*/** wklx,
>    deny /sys/firmware/efi/efivars/** rwklx,
>    deny /sys/kernel/security/** rwklx,
>    mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/,
> +
> +  # generated by: lxc-generate-aa-rules.py container-rules.base
> +  deny /proc/sys/kernel/[^s]*{,/**} wklx,
> +  deny /proc/sys/kernel/s[^h]*{,/**} wklx,
> +  deny /proc/sys/kernel/sh[^m]*{,/**} wklx,
> +  deny /proc/sys/kernel/shm*/** wklx,
> +  deny /sys/[^fdc]*{,/**} wklx,
> +  deny /sys/c[^l]*{,/**} wklx,
> +  deny /sys/cl[^a]*{,/**} wklx,
> +  deny /sys/cla[^s]*{,/**} wklx,
> +  deny /sys/clas[^s]*{,/**} wklx,
> +  deny /sys/class/[^n]*{,/**} wklx,
> +  deny /sys/class/n[^e]*{,/**} wklx,
> +  deny /sys/class/ne[^t]*{,/**} wklx,
> +  deny /sys/class/net?*{,/**} wklx,
> +  deny /sys/class?*{,/**} wklx,
> +  deny /sys/d[^e]*{,/**} wklx,
> +  deny /sys/de[^v]*{,/**} wklx,
> +  deny /sys/dev[^i]*{,/**} wklx,
> +  deny /sys/devi[^c]*{,/**} wklx,
> +  deny /sys/devic[^e]*{,/**} wklx,
> +  deny /sys/device[^s]*{,/**} wklx,
> +  deny /sys/devices/[^v]*{,/**} wklx,
> +  deny /sys/devices/v[^i]*{,/**} wklx,
> +  deny /sys/devices/vi[^r]*{,/**} wklx,
> +  deny /sys/devices/vir[^t]*{,/**} wklx,
> +  deny /sys/devices/virt[^u]*{,/**} wklx,
> +  deny /sys/devices/virtu[^a]*{,/**} wklx,
> +  deny /sys/devices/virtua[^l]*{,/**} wklx,
> +  deny /sys/devices/virtual/[^n]*{,/**} wklx,
> +  deny /sys/devices/virtual/n[^e]*{,/**} wklx,
> +  deny /sys/devices/virtual/ne[^t]*{,/**} wklx,
> +  deny /sys/devices/virtual/net?*{,/**} wklx,
> +  deny /sys/devices/virtual?*{,/**} wklx,
> +  deny /sys/devices?*{,/**} wklx,
> +  deny /sys/f[^s]*{,/**} wklx,
> +  deny /sys/fs/[^c]*{,/**} wklx,
> +  deny /sys/fs/c[^g]*{,/**} wklx,
> +  deny /sys/fs/cg[^r]*{,/**} wklx,
> +  deny /sys/fs/cgr[^o]*{,/**} wklx,
> +  deny /sys/fs/cgro[^u]*{,/**} wklx,
> +  deny /sys/fs/cgrou[^p]*{,/**} wklx,
> +  deny /sys/fs/cgroup?*{,/**} wklx,
> +  deny /sys/fs?*{,/**} wklx,
> diff --git a/config/apparmor/abstractions/container-base.in b/config/apparmor/abstractions/container-base.in
> new file mode 100644
> index 0000000..84eadd0
> --- /dev/null
> +++ b/config/apparmor/abstractions/container-base.in
> @@ -0,0 +1,45 @@
> +  network,
> +  capability,
> +  file,
> +  umount,
> +  dbus,
> +
> +  # ignore DENIED message on / remount
> +  deny mount options=(ro, remount) -> /,
> +
> +  # allow tmpfs mounts everywhere
> +  mount fstype=tmpfs,
> +
> +  # allow mqueue mounts everywhere
> +  mount fstype=mqueue,
> +
> +  # allow fuse mounts everywhere
> +  mount fstype=fuse.*,
> +
> +  # allow bind mount of /lib/init/fstab for lxcguest
> +  mount options=(rw, bind) /lib/init/fstab.lxc/ -> /lib/init/fstab/,
> +
> +  # deny writes in /proc/sys/fs but allow binfmt_misc to be mounted
> +  mount fstype=binfmt_misc -> /proc/sys/fs/binfmt_misc/,
> +  deny @{PROC}/sys/fs/** wklx,
> +
> +  # allow efivars to be mounted, writing to it will be blocked though
> +  mount fstype=efivarfs -> /sys/firmware/efi/efivars/,
> +
> +  # block some other dangerous paths
> +  deny @{PROC}/sysrq-trigger rwklx,
> +  deny @{PROC}/mem rwklx,
> +  deny @{PROC}/kmem rwklx,
> +
> +  # deny writes in /sys except for /sys/fs/cgroup, also allow
> +  # fusectl, securityfs and debugfs to be mounted there (read-only)
> +  mount fstype=fusectl -> /sys/fs/fuse/connections/,
> +  mount fstype=securityfs -> /sys/kernel/security/,
> +  mount fstype=debugfs -> /sys/kernel/debug/,
> +  deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
> +  mount fstype=proc -> /proc/,
> +  mount fstype=sysfs -> /sys/,
> +  deny /sys/firmware/efi/efivars/** rwklx,
> +  deny /sys/kernel/security/** rwklx,
> +  mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/,
> +
> diff --git a/config/apparmor/container-rules b/config/apparmor/container-rules
> new file mode 100644
> index 0000000..47dd4c2
> --- /dev/null
> +++ b/config/apparmor/container-rules
> @@ -0,0 +1,43 @@
> +  # generated by: lxc-generate-aa-rules.py container-rules.base
> +  deny /proc/sys/kernel/[^s]*{,/**} wklx,
> +  deny /proc/sys/kernel/s[^h]*{,/**} wklx,
> +  deny /proc/sys/kernel/sh[^m]*{,/**} wklx,
> +  deny /proc/sys/kernel/shm*/** wklx,
> +  deny /sys/[^fdc]*{,/**} wklx,
> +  deny /sys/c[^l]*{,/**} wklx,
> +  deny /sys/cl[^a]*{,/**} wklx,
> +  deny /sys/cla[^s]*{,/**} wklx,
> +  deny /sys/clas[^s]*{,/**} wklx,
> +  deny /sys/class/[^n]*{,/**} wklx,
> +  deny /sys/class/n[^e]*{,/**} wklx,
> +  deny /sys/class/ne[^t]*{,/**} wklx,
> +  deny /sys/class/net?*{,/**} wklx,
> +  deny /sys/class?*{,/**} wklx,
> +  deny /sys/d[^e]*{,/**} wklx,
> +  deny /sys/de[^v]*{,/**} wklx,
> +  deny /sys/dev[^i]*{,/**} wklx,
> +  deny /sys/devi[^c]*{,/**} wklx,
> +  deny /sys/devic[^e]*{,/**} wklx,
> +  deny /sys/device[^s]*{,/**} wklx,
> +  deny /sys/devices/[^v]*{,/**} wklx,
> +  deny /sys/devices/v[^i]*{,/**} wklx,
> +  deny /sys/devices/vi[^r]*{,/**} wklx,
> +  deny /sys/devices/vir[^t]*{,/**} wklx,
> +  deny /sys/devices/virt[^u]*{,/**} wklx,
> +  deny /sys/devices/virtu[^a]*{,/**} wklx,
> +  deny /sys/devices/virtua[^l]*{,/**} wklx,
> +  deny /sys/devices/virtual/[^n]*{,/**} wklx,
> +  deny /sys/devices/virtual/n[^e]*{,/**} wklx,
> +  deny /sys/devices/virtual/ne[^t]*{,/**} wklx,
> +  deny /sys/devices/virtual/net?*{,/**} wklx,
> +  deny /sys/devices/virtual?*{,/**} wklx,
> +  deny /sys/devices?*{,/**} wklx,
> +  deny /sys/f[^s]*{,/**} wklx,
> +  deny /sys/fs/[^c]*{,/**} wklx,
> +  deny /sys/fs/c[^g]*{,/**} wklx,
> +  deny /sys/fs/cg[^r]*{,/**} wklx,
> +  deny /sys/fs/cgr[^o]*{,/**} wklx,
> +  deny /sys/fs/cgro[^u]*{,/**} wklx,
> +  deny /sys/fs/cgrou[^p]*{,/**} wklx,
> +  deny /sys/fs/cgroup?*{,/**} wklx,
> +  deny /sys/fs?*{,/**} wklx,
> diff --git a/config/apparmor/container-rules.base b/config/apparmor/container-rules.base
> new file mode 100644
> index 0000000..e16d874
> --- /dev/null
> +++ b/config/apparmor/container-rules.base
> @@ -0,0 +1,10 @@
> +# Run lxc-generate-aa-rules.py on this file after any modification, to generate
> +# the container-rules file which is appended to container-base.in to create the
> +# final abstractions/container-base.
> +
> +block /sys
> +allow /sys/fs/cgroup/**
> +allow /sys/devices/virtual/net/**
> +allow /sys/class/net/**
> +block /proc/sys/kernel
> +allow /proc/sys/kernel/shm*
> diff --git a/config/apparmor/lxc-generate-aa-rules.py b/config/apparmor/lxc-generate-aa-rules.py
> new file mode 100755
> index 0000000..619b3bc
> --- /dev/null
> +++ b/config/apparmor/lxc-generate-aa-rules.py
> @@ -0,0 +1,135 @@
> +#!/usr/bin/python3
> +
> +import sys
> +
> +blocks = []
> +
> +#
> +# blocks is an array of paths under which we want to block by
> +# default.
> +#
> +#  blocks[0] = ['path' = '/sys', 'children' = [A,B] ]
> +#  blocks[1] = ['path' = '/proc/sys', 'children' = [ E ] ]
> +#  A = [ 'path' = 'fs', children = [C] ]
> +#  C = [ 'path' = 'cgroup', children = [F] ]
> +#  B = [ 'path' = 'class', children = [D] ]
> +#  D = [ 'path' = 'net', children = [F] ]
> +#  E = [ 'path' = 'shm*' ]
> +#  F = [ 'path' = '**' ]
> +
> +
> +def add_block(path):
> +    for b in blocks:
> +        if b['path'] == path:
> +            # duplicate
> +            return
> +    blocks.append({'path': path.strip(), 'children': []})
> +
> +
> +def child_get(prev, path):
> +    for p in prev:
> +        if p['path'] == path:
> +            return p
> +    return None
> +
> +
> +def add_allow(path):
> +    # find which block we belong to
> +    found = None
> +    for b in blocks:
> +        l = len(b['path'])
> +        if len(path) <= l:
> +            continue
> +        if path[0:l] == b['path']:
> +            found = b
> +            break
> +    if found is None:
> +        print("allow with no previous block at %s" % path)
> +        sys.exit(1)
> +    p = path[l:].strip()
> +    while p[:1] == "/":
> +        p = p[1:]
> +    prev = b['children']
> +    for s in p.split('/'):
> +        n = {'path': s.strip(), 'children': []}
> +        tmp = child_get(prev, n['path'])
> +        if tmp is not None:
> +            prev = tmp
> +        else:
> +            prev.append(n)
> +            prev = n['children']
> +
> +config = "config"
> +if len(sys.argv) > 1:
> +    config = sys.argv[1]
> +with open(config) as f:
> +    for x in f.readlines():
> +        x.strip()
> +        if x[:1] == '#':
> +            continue
> +        try:
> +            (cmd, path) = x.split(' ')
> +        except:  # blank line
> +            continue
> +        if cmd == "block":
> +            add_block(path)
> +        elif cmd == "allow":
> +            add_allow(path)
> +        else:
> +            print("Unknown command: %s" % cmd)
> +            sys.exit(1)
> +
> +denies = []
> +
> +
> +def collect_chars(children, ref, index):
> +    r = ""
> +    for c in children:
> +        if index >= len(c['path']):
> +            continue
> +        if ref[0:index] != c['path'][0:index]:
> +            continue
> +        if c['path'][index] not in r:
> +            r = r + c['path'][index]
> +    return r
> +
> +
> +def append_deny(s):
> +    s = "%s wklx," % s
> +    if s not in denies:
> +        denies.append(s)
> +
> +
> +def gen_denies(pathsofar, children):
> +    for c in children:
> +        for char in range(len(c['path'])):
> +            if char == len(c['path'])-1 and c['path'][char] == '*':
> +                continue
> +            if char == len(c['path'])-2:
> +                if c['path'][char:char+2] == '**':
> +                    continue
> +            x = collect_chars(children, c['path'], char)
> +            newdeny = "deny %s/%s[^%s]*{,/**}" % (pathsofar,
> +                                                  c['path'][0:char], x)
> +            append_deny(newdeny)
> +        if c['path'] != '**' and c['path'][len(c['path'])-1] != '*':
> +            newdeny = "deny %s/%s?*{,/**}" % (pathsofar, c['path'])
> +            append_deny(newdeny)
> +        elif c['path'] != '**':
> +            newdeny = "deny %s/%s/**" % (pathsofar, c['path'])
> +            append_deny(newdeny)
> +        if len(c['children']) != 0:
> +            newpath = "%s/%s" % (pathsofar, c['path'])
> +            gen_denies(newpath, c['children'])
> +
> +for b in blocks:
> +    gen_denies(b['path'], b['children'])
> +
> +denies.sort()
> +
> +genby = "  # generated by: lxc-generate-aa-rules.py"
> +for a in sys.argv[1:]:
> +   genby += " %s" % a
> +print(genby)
> +for d in denies:
> +    print("  %s" % d)
> diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
> index 9ca68ba..6b4fceb 100644
> --- a/src/tests/Makefile.am
> +++ b/src/tests/Makefile.am
> @@ -22,6 +22,7 @@ lxc_test_reboot_SOURCES = reboot.c
>  lxc_test_list_SOURCES = list.c
>  lxc_test_attach_SOURCES = attach.c
>  lxc_test_device_add_remove_SOURCES = device_add_remove.c
> +lxc_test_apparmor_SOURCES = aa.c
>  
>  AM_CFLAGS=-I$(top_srcdir)/src \
>  	-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
> @@ -44,7 +45,8 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
>  	lxc-test-shutdowntest lxc-test-get_item lxc-test-getkeys lxc-test-lxcpath \
>  	lxc-test-cgpath lxc-test-clonetest lxc-test-console \
>  	lxc-test-snapshot lxc-test-concurrent lxc-test-may-control \
> -	lxc-test-reboot lxc-test-list lxc-test-attach lxc-test-device-add-remove
> +	lxc-test-reboot lxc-test-list lxc-test-attach lxc-test-device-add-remove \
> +	lxc-test-apparmor
>  
>  bin_SCRIPTS = lxc-test-autostart
>  
> diff --git a/src/tests/aa.c b/src/tests/aa.c
> new file mode 100644
> index 0000000..a8ff691
> --- /dev/null
> +++ b/src/tests/aa.c
> @@ -0,0 +1,190 @@
> +/* liblxcapi
> + *
> + * Copyright © 2014 Serge Hallyn <serge.hallyn at ubuntu.com>.
> + * Copyright © 2014 Canonical Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2, as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +/* Test apparmor rules */
> +#include <lxc/lxccontainer.h>
> +#include "lxc/utils.h"
> +
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <string.h>
> +
> +#define MYNAME "test-aa"
> +
> +static void try_to_remove(void)
> +{
> +	struct lxc_container *c;
> +	c = lxc_container_new(MYNAME, NULL);
> +	if (c) {
> +		if (c->is_defined(c))
> +			c->destroy(c);
> +		lxc_container_put(c);
> +	}
> +}
> +
> +static int test_attach_write_file(void* payload)
> +{
> +	char *fnam = payload;
> +	FILE *f;
> +
> +	f = fopen(fnam, "w");
> +	if (f) {
> +		printf("yes\n");
> +		fclose(f);
> +		return 1;
> +	}
> +	printf("no\n");
> +	return 0;
> +}
> +
> +/*
> + * try opening a file attached to a container.  Return 0 on open fail.  Return
> + * 1 if the file open succeeded.  Return -1 if attach itself failed - perhas an
> + * older kernel.
> + */
> +static int do_test_file_open(struct lxc_container *c, char *fnam)
> +{
> +	int fret = -1;
> +	int ret;
> +	pid_t pid;
> +	int pipefd[2];
> +	char result[1024];
> +	lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
> +
> +	ret = pipe(pipefd);
> +	if (ret < 0) {
> +		fprintf(stderr, "pipe failed %d", ret);
> +		return fret;
> +	}
> +	attach_options.stdout_fd = pipefd[1];
> +	attach_options.attach_flags &= ~(LXC_ATTACH_LSM_EXEC|LXC_ATTACH_DROP_CAPABILITIES);
> +	attach_options.attach_flags |= LXC_ATTACH_LSM_NOW;
> +	ret = c->attach(c, test_attach_write_file, fnam, &attach_options, &pid);
> +	if (ret < 0) {
> +		fprintf(stderr, "attach failed");
> +		goto err1;
> +	}
> +
> +	ret = read(pipefd[0], result, sizeof(result)-1);
> +	if (ret < 0) {
> +		fprintf(stderr, "read failed %d", ret);
> +		goto err2;
> +	}
> +
> +	fret = 1;
> +	if (strncmp(result, "no", 2) == 0)
> +		fret = 0;
> +
> +err2:
> +	wait_for_pid(pid);
> +err1:
> +	close(pipefd[0]);
> +	close(pipefd[1]);
> +	return fret;
> +}
> +
> +char *files_to_allow[] = { "/sys/class/net/lo/ifalias",
> +		"/proc/sys/kernel/shmmax",
> +		NULL };
> +
> +char *files_to_deny[] = { "/proc/mem", "/proc/kmem",
> +		"/sys/kernel/uevent_helper",
> +		"/proc/sys/fs/file-nr",
> +		"/sys/kernel/mm/ksm/pages_to_scan",
> +		"/proc/sys/kernel/sysrq",
> +		NULL };
> +
> +static bool test_aa_policy(struct lxc_container *c)
> +{
> +	int i, ret;
> +
> +	for (i = 0; files_to_deny[i]; i++) {
> +		ret = do_test_file_open(c, files_to_deny[i]);
> +		if (ret < 0) {
> +			fprintf(stderr, "attach failed; skipping test");
> +			return true;
> +		}
> +		if (ret > 0) {
> +			fprintf(stderr, "failed - opened %s\n",
> +					files_to_deny[i]);
> +			return false;
> +		}
> +		fprintf(stderr, "passed with %s\n", files_to_deny[i]);
> +	}
> +
> +	for (i = 0; files_to_allow[i]; i++) {
> +		ret = do_test_file_open(c, files_to_allow[i]);
> +		if (ret < 0) {
> +			fprintf(stderr, "attach failed; skipping test");
> +			return true;
> +		}
> +		if (ret == 0) {
> +			fprintf(stderr, "failed - could not open %s\n",
> +					files_to_allow[i]);
> +			return false;
> +		}
> +		fprintf(stderr, "passed with %s\n", files_to_allow[i]);
> +	}
> +
> +	return true;
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	struct lxc_container *c;
> +	try_to_remove();
> +	c = lxc_container_new(MYNAME, NULL);
> +	if (!c) {
> +		fprintf(stderr, "%s: %d: failed to load first container\n", __FILE__, __LINE__);
> +		exit(1);
> +	}
> +
> +	if (c->is_defined(c)) {
> +		fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME);
> +		goto err;
> +	}
> +	if (!c->set_config_item(c, "lxc.network.type", "empty")) {
> +		fprintf(stderr, "%s: %d: failed to set network type\n", __FILE__, __LINE__);
> +		goto err;
> +	}
> +	c->save_config(c, NULL);
> +	if (!c->createl(c, "download", NULL, NULL, 0, "-d", "ubuntu", "-r", "trusty", "-a", "amd64", NULL)) {
> +		fprintf(stderr, "%s: %d: failed to create container\n", __FILE__, __LINE__);
> +		goto err;
> +	}
> +	c->want_daemonize(c, true);
> +	if (!c->startl(c, 0, NULL)) {
> +		fprintf(stderr, "Error starting container");
> +		goto err;
> +	}
> +
> +	if (!test_aa_policy(c)) {
> +		c->stop(c);
> +		goto err;
> +	}
> +
> +	c->stop(c);
> +
> +	try_to_remove();
> +	exit(0);
> +
> +err:
> +	try_to_remove();
> +	exit(1);
> +}
> -- 
> 1.9.1
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20140401/75f1f512/attachment-0001.pgp>


More information about the lxc-devel mailing list