├── config ├── etc │ ├── default.conf.unknown │ ├── default.conf.libvirt │ ├── default.conf.lxcbr │ └── meson.build ├── selinux │ ├── lxc.if │ └── meson.build ├── init │ ├── module │ │ ├── module.prop.in │ │ ├── boot-completed.sh.in │ │ ├── uninstall.sh.in │ │ ├── meson.build │ │ └── customize.sh.in │ ├── systemd │ │ ├── lxc-monitord.service.in │ │ ├── lxc-net.service.in │ │ ├── lxc@.service.in │ │ ├── lxc.service.in │ │ ├── lxc-apparmor-load │ │ └── meson.build │ ├── sysvinit │ │ ├── meson.build │ │ ├── lxc-net.in │ │ └── lxc-containers.in │ └── common │ │ └── meson.build ├── apparmor │ ├── usr.bin.lxc-copy │ ├── usr.bin.lxc-start │ ├── lxc-containers │ ├── README │ ├── profiles │ │ ├── lxc-default │ │ ├── lxc-default-with-mounting │ │ ├── lxc-default-with-nesting │ │ ├── lxc-default-cgns │ │ └── meson.build │ ├── container-rules.base │ ├── abstractions │ │ ├── meson.build │ │ └── start-container.in │ └── meson.build ├── templates │ ├── oci.common.conf.in │ ├── common.seccomp │ ├── common.conf.d │ │ ├── meson.build │ │ └── README │ ├── nesting.conf.in │ ├── userns.conf.in │ ├── meson.build │ └── common.conf.in ├── yum │ ├── meson.build │ └── lxc-patch.py ├── sysconfig │ ├── meson.build │ └── lxc.in └── bash │ └── meson.build ├── .gitignore ├── doc ├── examples │ ├── lxc-no-netns.conf.in │ ├── lxc-empty-netns.conf.in │ ├── lxc-macvlan.conf.in │ ├── lxc-phys.conf.in │ ├── lxc-vlan.conf.in │ ├── seccomp-v2-denylist.conf │ ├── lxc-veth.conf.in │ ├── seccomp-v2.conf │ ├── lxc-complex.conf.in │ └── meson.build ├── rootfs │ ├── README │ └── meson.build ├── lxc.system.conf ├── FAQ.txt ├── ja │ ├── FAQ.txt │ ├── lxc-checkconfig.sgml.in │ ├── meson.build │ ├── lxc-unfreeze.sgml.in │ └── lxc-freeze.sgml.in ├── ko │ ├── FAQ.txt │ ├── meson.build │ ├── lxc-checkconfig.sgml.in │ ├── lxc-unfreeze.sgml.in │ └── lxc-freeze.sgml.in ├── lxc.container.conf ├── lxc-checkconfig.sgml.in ├── lxc-unfreeze.sgml.in ├── lxc-freeze.sgml.in ├── lxc-config.sgml.in ├── meson.build └── see_also.sgml.in ├── AUTHORS ├── .github ├── dependabot.yml ├── workflows │ ├── sync.yml │ ├── commits.yml │ ├── fuzzing.yml │ ├── code-test.yml │ └── coverity.yml └── ISSUE_TEMPLATE.md ├── src ├── include │ ├── strchrnul.h │ ├── hasmntopt.h │ ├── fexecve.h │ ├── strlcpy.h │ ├── strlcat.h │ ├── pthread_ext.h │ ├── strlcpy.c │ ├── getgrgid_r.h │ ├── strlcat.c │ ├── hasmntopt.c │ ├── pthread_setcancelstate.c │ ├── fexecve.c │ ├── meson.build │ ├── bpf_common.h │ └── netns_ifaddrs.h ├── lxc │ ├── tools │ │ ├── include │ │ │ ├── getsubopt.h │ │ │ ├── meson.build │ │ │ └── getsubopt.c │ │ ├── lxc_config.c │ │ ├── meson.build │ │ ├── lxc_freeze.c │ │ └── lxc_unfreeze.c │ ├── rexec.h │ ├── lxc.functions.in │ ├── version.h.in │ ├── error.h │ ├── criu.h │ ├── attach.h │ ├── pam │ │ └── meson.build │ ├── storage │ │ ├── rsync.h │ │ ├── dir.h │ │ ├── rbd.h │ │ ├── loop.h │ │ ├── nbd.h │ │ ├── zfs.h │ │ ├── lvm.h │ │ ├── storage_utils.h │ │ └── overlay.h │ ├── uuid.h │ ├── state.h │ ├── lsm │ │ ├── lsm.c │ │ ├── lsm.h │ │ └── nop.c │ ├── cgroups │ │ ├── cgroup_utils.h │ │ └── cgroup2_devices.h │ ├── idmap_utils.h │ ├── parse.h │ ├── namespace.h │ ├── error_utils.h │ ├── error.c │ ├── execute.c │ ├── initutils.h │ ├── sync.h │ ├── rtnl.c │ ├── api_extensions.h │ ├── mainloop.h │ ├── ringbuf.h │ ├── freezer.c │ └── monitor.h └── tests │ ├── lxc-test-createconfig │ ├── basic.c │ ├── may_control.c │ ├── lxc-test-procsys │ ├── fuzz-lxc-config-read.c │ ├── lxc-test-exit-code │ ├── fuzz-lxc-cgroup-init.c │ ├── lxc-test-checkpoint-restore │ ├── lxc-test-no-new-privs │ ├── fuzz-lxc-define-load.c │ ├── lxc-test-snapdeps │ ├── lxctest.h │ ├── lxc-test-apparmor-generated │ ├── arch_parse.c │ ├── lxc-test-rootfs │ ├── lxcpath.c │ ├── config_jump_table.c │ ├── createtest.c │ ├── destroytest.c │ ├── lxc-test-autostart │ ├── shutdowntest.c │ ├── list.c │ ├── device_add_remove.c │ ├── criu_check_feature.c │ └── saveconfig.c ├── coccinelle ├── while-true.cocci ├── exit.cocci └── run-coccinelle.sh ├── COPYING ├── Makefile ├── hooks ├── clonehostname ├── squid-deb-proxy-client ├── mountecryptfsroot └── meson.build ├── MAINTAINERS ├── templates └── meson.build └── aarch64-android-api30.txt /config/etc/default.conf.unknown: -------------------------------------------------------------------------------- 1 | lxc.net.0.type = empty 2 | -------------------------------------------------------------------------------- /config/selinux/lxc.if: -------------------------------------------------------------------------------- 1 | ## Policy for LXC containers 2 | -------------------------------------------------------------------------------- /config/etc/default.conf.libvirt: -------------------------------------------------------------------------------- 1 | lxc.net.0.type = veth 2 | lxc.net.0.link = virbr0 3 | lxc.net.0.flags = up 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Temporarily files. 2 | *~ 3 | *.swp 4 | *.orig 5 | *.rej 6 | 7 | # Release tarballs. 8 | lxc-*.tar.gz* 9 | -------------------------------------------------------------------------------- /doc/examples/lxc-no-netns.conf.in: -------------------------------------------------------------------------------- 1 | # Container with non-virtualized network 2 | lxc.net.0.type = none 3 | lxc.uts.name = delta 4 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | The list of authors and contributors can be retrieved from the git 2 | commit history and in some cases, the file headers. 3 | -------------------------------------------------------------------------------- /config/etc/default.conf.lxcbr: -------------------------------------------------------------------------------- 1 | lxc.net.0.type = veth 2 | lxc.net.0.link = lxcbr0 3 | lxc.net.0.flags = up 4 | lxc.net.0.hwaddr = 10:66:6a:xx:xx:xx 5 | -------------------------------------------------------------------------------- /config/init/module/module.prop.in: -------------------------------------------------------------------------------- 1 | id=lxc 2 | name=LXC-Daemon 3 | version=1.0.0 4 | versionCode=10001 5 | author=@Container-On-Android 6 | description=description -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | -------------------------------------------------------------------------------- /doc/examples/lxc-empty-netns.conf.in: -------------------------------------------------------------------------------- 1 | # Container with new network without network devices 2 | lxc.uts.name = omega 3 | lxc.net.0.type = empty 4 | lxc.net.0.flags = up 5 | -------------------------------------------------------------------------------- /src/include/strchrnul.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "../lxc/compiler.h" 4 | 5 | __hidden extern char *strchrnul(const char *s, int c_in); 6 | -------------------------------------------------------------------------------- /config/apparmor/usr.bin.lxc-copy: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /usr/bin/lxc-copy flags=(attach_disconnected) { 4 | #include 5 | } 6 | -------------------------------------------------------------------------------- /config/apparmor/usr.bin.lxc-start: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /usr/bin/lxc-start flags=(attach_disconnected) { 4 | #include 5 | } 6 | -------------------------------------------------------------------------------- /coccinelle/while-true.cocci: -------------------------------------------------------------------------------- 1 | @@ 2 | statement s; 3 | @@ 4 | - while (true) 5 | + for (;;) 6 | s 7 | @@ 8 | statement s; 9 | @@ 10 | - while (1) 11 | + for (;;) 12 | s 13 | -------------------------------------------------------------------------------- /config/templates/oci.common.conf.in: -------------------------------------------------------------------------------- 1 | # Uncomment the following if you want to use DHCP for OCI containers 2 | #lxc.hook.start-host = @LXCHOOKDIR@/dhclient 3 | #lxc.hook.stop = @LXCHOOKDIR@/dhclient 4 | -------------------------------------------------------------------------------- /src/lxc/tools/include/getsubopt.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef _GETSUBOPT_H 4 | #define _GETSUBOPT_H 5 | int getsubopt (char **optionp, char *const *tokens, char **valuep); 6 | #endif 7 | -------------------------------------------------------------------------------- /doc/rootfs/README: -------------------------------------------------------------------------------- 1 | This directory must exist, even though it may be empty. 2 | It is used to temporary mount the rootfs of lxc in a private 3 | mount namespace only visible by the processes running in the 4 | container. 5 | -------------------------------------------------------------------------------- /src/lxc/tools/include/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if srcconf.get('HAVE_GETSUBOPT') == 0 4 | include_sources += files( 5 | 'getsubopt.c', 6 | 'getsubopt.h') 7 | endif 8 | -------------------------------------------------------------------------------- /config/apparmor/lxc-containers: -------------------------------------------------------------------------------- 1 | # This file exists only to ensure that all per-container policies 2 | # listed under /etc/apparmor.d/lxc get loaded at boot. Please do 3 | # not edit this file. 4 | 5 | #include 6 | 7 | #include 8 | -------------------------------------------------------------------------------- /doc/rootfs/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | rootfs_readme = configure_file( 4 | configuration: dummy_config_data, 5 | input: 'README', 6 | output: 'README', 7 | install: true, 8 | install_dir: lxcrootfsmount) 9 | -------------------------------------------------------------------------------- /coccinelle/exit.cocci: -------------------------------------------------------------------------------- 1 | @@ 2 | @@ 3 | - exit(0); 4 | + exit(EXIT_SUCCESS); 5 | @@ 6 | @@ 7 | - _exit(0); 8 | + _exit(EXIT_SUCCESS); 9 | @@ 10 | @@ 11 | - exit(1); 12 | + exit(EXIT_FAILURE); 13 | @@ 14 | @@ 15 | - _exit(1); 16 | + _exit(EXIT_FAILURE); 17 | -------------------------------------------------------------------------------- /config/init/module/boot-completed.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export LD_LIBRARY_PATH=/system/lib64:/system/lib:@LIBDIR@:/data/sysroot/lib64:/data/sysroot/lib 4 | 5 | # lxc-autostart 6 | mkdir -p @LOCALSTATEDIR@/lock 7 | @LIBEXECDIR@/lxc/lxc-containers start 8 | -------------------------------------------------------------------------------- /config/yum/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | lxc_patch = configure_file( 4 | configuration: dummy_config_data, 5 | input: 'lxc-patch.py', 6 | output: 'lxc-patch.py', 7 | install: true, 8 | install_dir: lxcdatadir) 9 | -------------------------------------------------------------------------------- /config/etc/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | lxc_system_config = configure_file( 4 | configuration: dummy_config_data, 5 | input: 'default.conf.lxcbr', 6 | output: 'default.conf', 7 | install: true, 8 | install_dir: lxcconfdir) 9 | -------------------------------------------------------------------------------- /config/templates/common.seccomp: -------------------------------------------------------------------------------- 1 | 2 2 | denylist 3 | reject_force_umount # comment this to allow umount -f; not recommended 4 | [all] 5 | kexec_load errno 1 6 | open_by_handle_at errno 1 7 | init_module errno 1 8 | finit_module errno 1 9 | delete_module errno 1 10 | -------------------------------------------------------------------------------- /src/lxc/rexec.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_REXEC_H 4 | #define __LXC_REXEC_H 5 | 6 | #include "config.h" 7 | 8 | #include "compiler.h" 9 | 10 | __hidden extern int lxc_rexec(const char *memfd_name); 11 | 12 | #endif /* __LXC_REXEC_H */ 13 | -------------------------------------------------------------------------------- /config/templates/common.conf.d/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | lxc_conf_common_readme = configure_file( 4 | configuration: dummy_config_data, 5 | input: 'README', 6 | output: 'README', 7 | install: true, 8 | install_dir: lxctemplateconfcommondir) 9 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | All source files have SPDX headers that declare what license applies. 2 | The applicable licenses are included in the code repository. 3 | 4 | For other files such as examples, config files, ... they can be assumed 5 | to be licensed the same way that the LXC library is, so under LGPLv2.1+. 6 | -------------------------------------------------------------------------------- /config/sysconfig/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if distrosysconfdir != '' 4 | configure_file( 5 | configuration: conf, 6 | input: 'lxc.in', 7 | output: 'lxc', 8 | install: true, 9 | install_dir: distrosysconfdir) 10 | endif 11 | -------------------------------------------------------------------------------- /config/init/systemd/lxc-monitord.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=LXC Container Monitoring Daemon 3 | After=syslog.service network.target 4 | Documentation=man:lxc 5 | 6 | [Service] 7 | Type=simple 8 | ExecStart=@LIBEXECDIR@/lxc/lxc-monitord --daemon 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /config/init/module/uninstall.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export LD_LIBRARY_PATH=/system/lib64:/system/lib:@LIBDIR@:/data/sysroot/lib64:/data/sysroot/lib 4 | 5 | for container in $(lxc-ls); do 6 | echo "stopping: $container" 7 | lxc-stop -n "$container" 2>/dev/null || lxc-stop -n "$container" -k 8 | done 9 | 10 | rm -rf @PREFIXDIR@ -------------------------------------------------------------------------------- /config/apparmor/README: -------------------------------------------------------------------------------- 1 | The abstractions/container-base file installed is automatically 2 | generated. Its two source files are container-rules.base and 3 | abstractions/container-base.in. If container-rules.base is updated, 4 | generate a new container-rules file using 5 | 6 | ./lxc-generate-aa-rules.py container-rules.base > container-rules 7 | -------------------------------------------------------------------------------- /doc/examples/lxc-macvlan.conf.in: -------------------------------------------------------------------------------- 1 | # Container with network virtualized using the macvlan device driver 2 | lxc.uts.name = alpha 3 | lxc.net.0.type = macvlan 4 | lxc.net.0.flags = up 5 | lxc.net.0.link = eth0 6 | lxc.net.0.hwaddr = 4a:49:43:49:79:bd 7 | lxc.net.0.ipv4.address = 10.2.3.4/24 8 | lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3596 9 | -------------------------------------------------------------------------------- /config/templates/common.conf.d/README: -------------------------------------------------------------------------------- 1 | This directory can be used by packages and users to dump LXC 2 | configuration snippets which will then be used by all containers using 3 | the common.conf configuration file (directly or indirectly). 4 | 5 | Configuration files must end with the .conf suffix and LXC will include 6 | those in alphabetical order. 7 | -------------------------------------------------------------------------------- /src/include/hasmntopt.h: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ * 4 | * 5 | * This function has been copied from musl. 6 | */ 7 | 8 | #ifndef _HASMNTOPT_H 9 | #define _HASMNTOPT_H 10 | 11 | #include "../lxc/compiler.h" 12 | 13 | __hidden extern char* hasmntopt(const struct mntent* mnt, const char* opt); 14 | 15 | #endif -------------------------------------------------------------------------------- /src/include/fexecve.h: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ 4 | * 5 | */ 6 | 7 | #ifndef _LXC_FEXECVE_H 8 | #define _LXC_FEXECVE_H 9 | 10 | #include "../lxc/compiler.h" 11 | #include 12 | 13 | __hidden extern int fexecve(int fd, char *const argv[], char *const envp[]); 14 | 15 | #endif /* _LXC_FEXECVE_H */ 16 | -------------------------------------------------------------------------------- /src/include/strlcpy.h: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ * 4 | * 5 | * This function has been copied from musl. 6 | */ 7 | 8 | #ifndef _STRLCPY_H 9 | #define _STRLCPY_H 10 | 11 | #include "../lxc/compiler.h" 12 | #include 13 | 14 | __hidden extern size_t strlcpy(char *, const char *, size_t); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /config/templates/nesting.conf.in: -------------------------------------------------------------------------------- 1 | # Use a profile which allows nesting 2 | lxc.apparmor.profile = lxc-container-default-with-nesting 3 | 4 | # Add uncovered mounts of proc and sys, else unprivileged users 5 | # cannot remount those 6 | 7 | lxc.mount.entry = proc dev/.lxc/proc proc create=dir,optional 0 0 8 | lxc.mount.entry = sys dev/.lxc/sys sysfs create=dir,optional 0 0 9 | -------------------------------------------------------------------------------- /doc/examples/lxc-phys.conf.in: -------------------------------------------------------------------------------- 1 | # Container with network virtualized using a physical network device with name 2 | # 'eth0' 3 | lxc.uts.name = gamma 4 | lxc.net.0.type = phys 5 | lxc.net.0.flags = up 6 | lxc.net.0.link = eth0 7 | lxc.net.0.hwaddr = 4a:49:43:49:79:ff 8 | lxc.net.0.ipv4.address = 10.2.3.6/24 9 | lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3297 10 | -------------------------------------------------------------------------------- /doc/examples/lxc-vlan.conf.in: -------------------------------------------------------------------------------- 1 | # Container with network virtualized using the vlan device driver 2 | lxc.uts.name = alpha 3 | lxc.net.0.type = vlan 4 | lxc.net.0.vlan.id = 1234 5 | lxc.net.0.flags = up 6 | lxc.net.0.link = eth0 7 | lxc.net.0.hwaddr = 4a:49:43:49:79:bd 8 | lxc.net.0.ipv4.address = 10.2.3.4/24 9 | lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3596 10 | -------------------------------------------------------------------------------- /src/include/strlcat.h: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ * 4 | * 5 | * This function has been copied from musl. 6 | */ 7 | 8 | #ifndef _STRLCAT_H 9 | #define _STRLCAT_H 10 | 11 | #include "../lxc/compiler.h" 12 | #include 13 | 14 | __hidden extern size_t strlcat(char *src, const char *append, size_t len); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/include/pthread_ext.h: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ * 4 | * 5 | */ 6 | 7 | #ifndef _PTHREAD_EXT_H 8 | #define _PTHREAD_EXT_H 9 | 10 | #include "../lxc/compiler.h" 11 | 12 | #ifndef PTHREAD_CANCELED 13 | #define PTHREAD_CANCELED ((void *)-1) 14 | #endif 15 | 16 | __hidden extern int pthread_setcancelstate(int, int *); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | .PHONY: all 4 | all: meson 5 | ninja -C build 6 | 7 | .PHONY: meson 8 | meson: 9 | [ -d build ] || meson setup build/ 10 | 11 | .PHONY: dist 12 | dist: meson 13 | meson dist -C build/ --formats=gztar 14 | cp build/meson-dist/*.tar.gz . 15 | 16 | .PHONY: install 17 | install: 18 | DESTDIR=$(DESTDIR) ninja -C build install 19 | -------------------------------------------------------------------------------- /doc/examples/seccomp-v2-denylist.conf: -------------------------------------------------------------------------------- 1 | 2 2 | denylist 3 | # v2 allows comments after the second line, with '#' in first column, 4 | # denylist will allow syscalls by default 5 | # if 'errno 0' was not appended to 'mknod' below, then the task would 6 | # simply be killed when it tried to mknod. 'errno 0' means do not allow 7 | # the container to mknod, but immediately return 0. 8 | mknod errno 0 9 | -------------------------------------------------------------------------------- /src/lxc/lxc.functions.in: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | # This file contains helpers for the various lxc shell scripts 4 | 5 | globalconf=@LXC_GLOBAL_CONF@ 6 | bindir=@BINDIR@ 7 | templatedir=@LXCTEMPLATEDIR@ 8 | lxcinitdir=@LXCINITDIR@ 9 | 10 | lxc_path=$(lxc-config lxc.lxcpath) 11 | lxc_vg=$(lxc-config lxc.bdev.lvm.vg) 12 | lxc_zfsroot=$(lxc-config lxc.bdev.zfs.root) 13 | -------------------------------------------------------------------------------- /doc/examples/lxc-veth.conf.in: -------------------------------------------------------------------------------- 1 | # Container with network virtualized using a pre-configured bridge named br0 and 2 | # veth pair virtual network devices 3 | lxc.uts.name = beta 4 | lxc.net.0.type = veth 5 | lxc.net.0.flags = up 6 | lxc.net.0.link = br0 7 | lxc.net.0.hwaddr = 4a:49:43:49:79:bf 8 | lxc.net.0.ipv4.address = 10.2.3.5/24 9 | lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3597 10 | -------------------------------------------------------------------------------- /config/init/systemd/lxc-net.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=LXC network bridge setup 3 | After=network-online.target 4 | Before=lxc.service 5 | Documentation=man:lxc 6 | ConditionVirtualization=!lxc 7 | 8 | [Service] 9 | Type=oneshot 10 | RemainAfterExit=yes 11 | ExecStart=@LIBEXECDIR@/lxc/lxc-net start 12 | ExecStop=@LIBEXECDIR@/lxc/lxc-net stop 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /src/lxc/version.h.in: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_VERSION_H 4 | #define __LXC_VERSION_H 5 | 6 | #define LXC_DEVEL @LXC_DEVEL@ 7 | #define LXC_VERSION_MAJOR @LXC_VERSION_MAJOR@ 8 | #define LXC_VERSION_MINOR @LXC_VERSION_MINOR@ 9 | #define LXC_VERSION_MICRO @LXC_VERSION_MICRO@ 10 | #define LXC_VERSION_ABI "@LXC_ABI@" 11 | #define LXC_VERSION "@LXC_VERSION@" 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/lxc/error.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_ERROR_H 4 | #define __LXC_ERROR_H 5 | 6 | #define LXC_CLONE_ERROR "Failed to clone a new set of namespaces" 7 | #define LXC_UNPRIV_EOPNOTSUPP "the requested function %s is not currently supported with unprivileged containers" 8 | 9 | #include "compiler.h" 10 | 11 | __hidden extern int lxc_error_set_and_log(int pid, int status); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/include/strlcpy.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ * 4 | * 5 | * This function has been copied from musl. 6 | */ 7 | 8 | #include 9 | 10 | size_t strlcpy(char *dest, const char *src, size_t size) 11 | { 12 | size_t ret = strlen(src); 13 | 14 | if (size) { 15 | size_t len = (ret >= size) ? size - 1 : ret; 16 | memcpy(dest, src, len); 17 | dest[len] = '\0'; 18 | } 19 | 20 | return ret; 21 | } 22 | -------------------------------------------------------------------------------- /config/selinux/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | lxc_selinux_if = configure_file( 4 | configuration: dummy_config_data, 5 | input: 'lxc.if', 6 | output: 'lxc.if', 7 | install: libselinux.found(), 8 | install_dir: lxcselinuxdir) 9 | 10 | lxc_selinux_te = configure_file( 11 | configuration: dummy_config_data, 12 | input: 'lxc.te', 13 | output: 'lxc.te', 14 | install: libselinux.found(), 15 | install_dir: lxcselinuxdir) 16 | -------------------------------------------------------------------------------- /src/include/getgrgid_r.h: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ 4 | * 5 | * This function has been copied from musl. 6 | */ 7 | 8 | #ifndef _GETGRGID_R_H 9 | #define _GETGRGID_R_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../lxc/compiler.h" 16 | 17 | __hidden extern int getgrgid_r(gid_t gid, struct group *gr, char *buf, size_t size, 18 | struct group **res); 19 | 20 | #endif /* _GETGRGID_R_H */ 21 | -------------------------------------------------------------------------------- /hooks/clonehostname: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # SPDX-License-Identifier: GPL-2.0-only 4 | # 5 | # Update the hostname in the cloned container's scripts 6 | 7 | # Note that /etc/hostname is updated by lxc itself 8 | for file in \ 9 | $LXC_ROOTFS_MOUNT/etc/sysconfig/network \ 10 | $LXC_ROOTFS_MOUNT/etc/sysconfig/network-scripts/ifcfg-* \ 11 | $LXC_ROOTFS_MOUNT/etc/hosts ; 12 | do 13 | if [ -f $file ]; then 14 | sed -i "s|$LXC_SRC_NAME|$LXC_NAME|" $file 15 | fi 16 | done 17 | 18 | exit 0 19 | -------------------------------------------------------------------------------- /config/init/systemd/lxc@.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=LXC Container: %i 3 | # This pulls in apparmor, dev-setup, lxc-net 4 | After=lxc.service 5 | Wants=lxc.service 6 | Documentation=man:lxc-start man:lxc 7 | 8 | [Service] 9 | Type=simple 10 | KillMode=mixed 11 | TimeoutStopSec=120s 12 | ExecStart=@BINDIR@/lxc-start -F -n %i 13 | ExecStop=@BINDIR@/lxc-stop -n %i 14 | # Environment=BOOTUP=serial 15 | # Environment=CONSOLETYPE=serial 16 | StateDirectory=lxc 17 | Delegate=yes 18 | 19 | [Install] 20 | WantedBy=multi-user.target 21 | -------------------------------------------------------------------------------- /doc/lxc.system.conf: -------------------------------------------------------------------------------- 1 | # LVM: volume group to use for new containers 2 | lxc.bdev.lvm.vg = lxc 3 | 4 | # LVM: thin pool to use for new containers 5 | lxc.bdev.lvm.thin_pool = lxc 6 | 7 | # ZFS: Root path 8 | lxc.bdev.zfs.root = lxc 9 | 10 | # Path to the containers 11 | lxc.lxcpath = /var/lib/lxc/ 12 | 13 | # Path to the default configuration file 14 | lxc.default_config = /etc/lxc/default.conf 15 | 16 | # Pattern to use for the cgroup path 17 | lxc.cgroup.pattern = lxc/%n 18 | 19 | # List of cgroups to use 20 | lxc.cgroup.use = 21 | -------------------------------------------------------------------------------- /config/apparmor/profiles/lxc-default: -------------------------------------------------------------------------------- 1 | # Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which 2 | # will source all profiles under /etc/apparmor.d/lxc 3 | 4 | profile lxc-container-default flags=(attach_disconnected,mediate_deleted) { 5 | #include 6 | 7 | # the container may never be allowed to mount devpts. If it does, it 8 | # will remount the host's devpts. We could allow it to do it with 9 | # the newinstance option (but, right now, we don't). 10 | deny mount fstype=devpts, 11 | } 12 | -------------------------------------------------------------------------------- /config/init/sysvinit/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if 'sysvinit' in init_script 4 | configure_file( 5 | configuration: conf, 6 | input: 'lxc-containers.in', 7 | output: 'lxc-containers', 8 | install: true, 9 | install_dir: join_paths(sysconfdir, 'init.d')) 10 | 11 | configure_file( 12 | configuration: conf, 13 | input: 'lxc-net.in', 14 | output: 'lxc-net', 15 | install: true, 16 | install_dir: join_paths(sysconfdir, 'init.d')) 17 | endif 18 | -------------------------------------------------------------------------------- /config/apparmor/container-rules.base: -------------------------------------------------------------------------------- 1 | # Run lxc-generate-aa-rules.py on this file after any modification, to generate 2 | # the container-rules file which is appended to container-base.in to create the 3 | # final abstractions/container-base. 4 | 5 | block /sys 6 | allow /sys/fs/cgroup/** 7 | allow /sys/devices/virtual/net/** 8 | allow /sys/class/net/** 9 | block /proc/sys 10 | allow /proc/sys/kernel/shm* 11 | allow /proc/sys/kernel/sem* 12 | allow /proc/sys/kernel/msg* 13 | allow /proc/sys/kernel/hostname 14 | allow /proc/sys/kernel/domainname 15 | allow /proc/sys/net/** 16 | -------------------------------------------------------------------------------- /src/lxc/criu.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_CRIU_H 4 | #define __LXC_CRIU_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | 10 | #include "lxc.h" 11 | 12 | __hidden extern bool __criu_pre_dump(struct lxc_container *c, struct migrate_opts *opts); 13 | __hidden extern bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts); 14 | __hidden extern bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts); 15 | __hidden extern bool __criu_check_feature(uint64_t *features_to_check); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/include/strlcat.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ * 4 | * 5 | * This function has been copied from musl. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #if !HAVE_STRLCPY 13 | #include "strlcpy.h" 14 | #endif 15 | 16 | size_t strlcat(char *src, const char *append, size_t len) 17 | { 18 | size_t src_len; 19 | 20 | src_len = strnlen(src, len); 21 | if (src_len == len) 22 | return src_len + strlen(append); 23 | 24 | return src_len + strlcpy(src + src_len, append, len - src_len); 25 | } 26 | -------------------------------------------------------------------------------- /MAINTAINERS: -------------------------------------------------------------------------------- 1 | Before submitting your patches, check they are signed-off-by 2 | conforming with the DCO contained in the ./CONTRIBUTING file. 3 | 4 | Maintainer 5 | ---------- 6 | 7 | Committers : Serge Hallyn, Stéphane Graber, Christian Brauner and Wolfgang Bumiller 8 | Mail patches to : lxc-devel@lists.linuxcontainers.org 9 | Send pull requests at : https://github.com/lxc/lxc 10 | Mailing lists : lxc-devel@lists.linuxcontainers.org, lxc-users@lists.linuxcontainers.org 11 | Web page : https://linuxcontainers.org/lxc 12 | Git location : https://github.com/lxc/lxc 13 | -------------------------------------------------------------------------------- /config/apparmor/profiles/lxc-default-with-mounting: -------------------------------------------------------------------------------- 1 | # Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which 2 | # will source all profiles under /etc/apparmor.d/lxc 3 | 4 | profile lxc-container-default-with-mounting flags=(attach_disconnected,mediate_deleted) { 5 | #include 6 | 7 | # allow standard blockdevtypes. 8 | # The concern here is in-kernel superblock parsers bringing down the 9 | # host with bad data. However, we continue to disallow proc, sys, securityfs, 10 | # etc to nonstandard locations. 11 | mount fstype=ext*, 12 | mount fstype=xfs, 13 | mount fstype=btrfs, 14 | } 15 | -------------------------------------------------------------------------------- /config/init/common/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | lxc_containers = configure_file( 4 | configuration: conf, 5 | input: 'lxc-containers.in', 6 | output: 'lxc-containers', 7 | install: true, 8 | install_dir: lxclibexec) 9 | 10 | lxc_net = configure_file( 11 | configuration: conf, 12 | input: 'lxc-net.in', 13 | output: 'lxc-net', 14 | install: true, 15 | install_dir: lxclibexec) 16 | 17 | lxc_net_builtin = configure_file( 18 | configuration: conf, 19 | input: 'lxc-net-builtin.in', 20 | output: 'lxc-net-builtin', 21 | install: true, 22 | install_dir: lxclibexec) 23 | -------------------------------------------------------------------------------- /src/tests/lxc-test-createconfig: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | 5 | # lxc: linux Container library 6 | # 7 | # This is a test script for the lxc-user-nic program 8 | 9 | set -e 10 | 11 | s=$(mktemp -d /tmp/lxctest-XXXXXX) 12 | f="$s/in.conf" 13 | 14 | cleanup() { 15 | lxc-destroy -n lxctestc || true 16 | rm -rf $s 17 | } 18 | 19 | trap cleanup EXIT 20 | 21 | cat > $f << EOF 22 | lxc.net.0.type = veth 23 | lxc.net.0.hwaddr = 10:66:6a:xx:xx:xx 24 | EOF 25 | lxc-create -t busybox -f $f -n lxctestc 26 | grep -q "xx:xx" /var/lib/lxc/lxctestc/config && { echo "hwaddr not expanded"; exit 1; } 27 | echo "Success" 28 | -------------------------------------------------------------------------------- /.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: Sync Fork 2 | 3 | on: 4 | schedule: 5 | - cron: '20 4 * * 5' # every Friday 12:20 (UTC/GMT+08:00 Shanghai) 6 | workflow_dispatch: # on button click 7 | 8 | jobs: 9 | sync: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: tgymnich/fork-sync@v2.0.10 15 | with: 16 | owner: Container-On-Android 17 | base: main 18 | head: main 19 | pr_title: "Merge upstream branch 'main'" 20 | pr_message: "Merge branch 'lxc:main' into main" 21 | auto_merge: false 22 | merge_method: rebase 23 | ignore_fail: true 24 | -------------------------------------------------------------------------------- /src/include/hasmntopt.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ * 4 | * 5 | * This function has been copied from musl. 6 | */ 7 | 8 | #include 9 | 10 | struct mntent { 11 | char* mnt_fsname; 12 | char* mnt_dir; 13 | char* mnt_type; 14 | char* mnt_opts; 15 | int mnt_freq; 16 | int mnt_passno; 17 | }; 18 | 19 | char *hasmntopt(const struct mntent *mnt, const char *opt) 20 | { 21 | size_t l = strlen(opt); 22 | char *p = mnt->mnt_opts; 23 | for (;;) { 24 | if (!strncmp(p, opt, l) && (!p[l] || p[l]==',' || p[l]=='=')) 25 | return p; 26 | p = strchr(p, ','); 27 | if (!p) return 0; 28 | p++; 29 | } 30 | } -------------------------------------------------------------------------------- /config/init/systemd/lxc.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=LXC Container Initialization and Autoboot Code 3 | After=network.target lxc-net.service remote-fs.target 4 | Wants=lxc-net.service 5 | Documentation=man:lxc-autostart man:lxc 6 | 7 | [Service] 8 | Type=oneshot 9 | RemainAfterExit=yes 10 | ExecStartPre=@LIBEXECDIR@/lxc/lxc-apparmor-load 11 | ExecStart=@LIBEXECDIR@/lxc/lxc-containers start 12 | ExecStop=@LIBEXECDIR@/lxc/lxc-containers stop 13 | ExecReload=@LIBEXECDIR@/lxc/lxc-apparmor-load 14 | # Environment=BOOTUP=serial 15 | # Environment=CONSOLETYPE=serial 16 | StateDirectory=lxc 17 | Delegate=yes 18 | 19 | [Install] 20 | WantedBy=multi-user.target 21 | -------------------------------------------------------------------------------- /src/lxc/attach.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_ATTACH_H 4 | #define __LXC_ATTACH_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "lxc.h" 12 | 13 | #include "compiler.h" 14 | #include "namespace.h" 15 | 16 | struct lxc_conf; 17 | struct lxc_container; 18 | 19 | __hidden extern int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, 20 | void *exec_payload, lxc_attach_options_t *options, 21 | pid_t *attached_process); 22 | 23 | __hidden extern int lxc_attach_remount_sys_proc(void); 24 | 25 | #endif /* __LXC_ATTACH_H */ 26 | -------------------------------------------------------------------------------- /config/apparmor/profiles/lxc-default-with-nesting: -------------------------------------------------------------------------------- 1 | # Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which 2 | # will source all profiles under /etc/apparmor.d/lxc 3 | 4 | profile lxc-container-default-with-nesting flags=(attach_disconnected,mediate_deleted) { 5 | #include 6 | #include 7 | 8 | deny /dev/.lxc/proc/** rw, 9 | deny /dev/.lxc/sys/** rw, 10 | mount fstype=proc -> /var/cache/lxc/**, 11 | mount fstype=sysfs -> /var/cache/lxc/**, 12 | mount options=(rw,bind), 13 | mount fstype=cgroup -> /sys/fs/cgroup/**, 14 | mount fstype=cgroup2 -> /sys/fs/cgroup/**, 15 | } 16 | -------------------------------------------------------------------------------- /config/apparmor/abstractions/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if libapparmor.found() 4 | configure_file( 5 | command: ['cat', '@INPUT@'], 6 | capture: true, 7 | input: ['container-base.in', '../container-rules'], 8 | output: 'container-base', 9 | install: true, 10 | install_dir: join_paths(sysconfdir, 'apparmor.d', 'abstractions', 'lxc')) 11 | 12 | configure_file( 13 | configuration: conf, 14 | input: 'start-container.in', 15 | output: 'start-container', 16 | install: true, 17 | install_dir: join_paths(sysconfdir, 'apparmor.d', 'abstractions', 'lxc')) 18 | endif 19 | -------------------------------------------------------------------------------- /config/apparmor/profiles/lxc-default-cgns: -------------------------------------------------------------------------------- 1 | # Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which 2 | # will source all profiles under /etc/apparmor.d/lxc 3 | 4 | profile lxc-container-default-cgns flags=(attach_disconnected,mediate_deleted) { 5 | #include 6 | 7 | # the container may never be allowed to mount devpts. If it does, it 8 | # will remount the host's devpts. We could allow it to do it with 9 | # the newinstance option (but, right now, we don't). 10 | deny mount fstype=devpts, 11 | mount fstype=cgroup -> /sys/fs/cgroup/**, 12 | mount fstype=cgroup2 -> /sys/fs/cgroup/**, 13 | mount fstype=overlay, 14 | } 15 | -------------------------------------------------------------------------------- /src/lxc/pam/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | pam_cgfs_sources = files( 4 | 'pam_cgfs.c', 5 | '../file_utils.c', 6 | '../file_utils.h', 7 | '../macro.h', 8 | '../memory_utils.h', 9 | '../open_utils.h', 10 | '../string_utils.c', 11 | '../string_utils.h') + include_sources 12 | 13 | if want_pam_cgroup 14 | pam_cgfs = shared_module( 15 | 'pam_cgfs', 16 | include_directories: liblxc_includes, 17 | sources: pam_cgfs_sources, 18 | dependencies: [pkgconfig_libs], 19 | name_prefix: '', 20 | install_mode: 'rw-r--r--', # 644 21 | install: true, 22 | install_dir: pam_security) 23 | endif 24 | -------------------------------------------------------------------------------- /config/templates/userns.conf.in: -------------------------------------------------------------------------------- 1 | # CAP_SYS_ADMIN in init-user-ns is required for cgroup.devices 2 | # 3 | # Default legacy cgroup configuration 4 | # 5 | lxc.cgroup.devices.deny = 6 | lxc.cgroup.devices.allow = 7 | 8 | # Default unified cgroup configuration 9 | # 10 | lxc.cgroup2.devices.deny = 11 | lxc.cgroup2.devices.allow = 12 | 13 | # Start with a full set of capabilities in user namespaces. 14 | lxc.cap.drop = 15 | lxc.cap.keep = 16 | 17 | # We can't move bind-mounts, so don't use /dev/lxc/ 18 | lxc.tty.dir = 19 | 20 | # Setup the default mounts 21 | lxc.mount.auto = sys:rw 22 | 23 | # Lastly, include all the configs from @LXCTEMPLATECONFIG@/userns.conf.d/ 24 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf.d/ 25 | -------------------------------------------------------------------------------- /src/lxc/storage/rsync.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_RSYNC_H 4 | #define __LXC_RSYNC_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | 10 | #include "compiler.h" 11 | 12 | struct rsync_data { 13 | struct lxc_storage *orig; 14 | struct lxc_storage *new; 15 | }; 16 | 17 | struct rsync_data_char { 18 | char *src; 19 | char *dest; 20 | }; 21 | 22 | /* new helpers */ 23 | __hidden extern int lxc_rsync_exec_wrapper(void *data); 24 | __hidden extern int lxc_storage_rsync_exec_wrapper(void *data); 25 | __hidden extern int lxc_rsync_exec(const char *src, const char *dest); 26 | __hidden extern int lxc_rsync(struct rsync_data *data); 27 | 28 | #endif /* __LXC_RSYNC_H */ 29 | -------------------------------------------------------------------------------- /src/tests/basic.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "lxctest.h" 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | int ret; 19 | struct lxc_container *c; 20 | 21 | c = lxc_container_new("init-pid", NULL); 22 | if (!c) 23 | exit(EXIT_FAILURE); 24 | 25 | ret = c->init_pid(c); 26 | c->destroy(c); 27 | lxc_container_put(c); 28 | /* Return value needs to be -1. Any other negative error code is to be 29 | * considered invalid. 30 | */ 31 | if (ret != -1) 32 | exit(EXIT_FAILURE); 33 | 34 | exit(EXIT_SUCCESS); 35 | } 36 | -------------------------------------------------------------------------------- /config/init/systemd/lxc-apparmor-load: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # lxc-apparmor-load: Load AppArmor profiles, if supported by the system 3 | 4 | set -eu 5 | 6 | # don't load profiles if mount mediation is not supported 7 | SYSF=/sys/kernel/security/apparmor/features/mount/mask 8 | if [ -f $SYSF ]; then 9 | if [ -x /lib/apparmor/profile-load ]; then 10 | /lib/apparmor/profile-load usr.bin.lxc-copy 11 | /lib/apparmor/profile-load usr.bin.lxc-start 12 | /lib/apparmor/profile-load lxc-containers 13 | elif [ -x /lib/init/apparmor-profile-load ]; then 14 | /lib/init/apparmor-profile-load usr.bin.lxc-copy 15 | /lib/init/apparmor-profile-load usr.bin.lxc-start 16 | /lib/init/apparmor-profile-load lxc-containers 17 | fi 18 | fi 19 | -------------------------------------------------------------------------------- /src/lxc/uuid.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_UUID_H 4 | #define __LXC_UUID_H 5 | 6 | #ifndef _GNU_SOURCE 7 | #define _GNU_SOURCE 1 8 | #endif 9 | #define __STDC_FORMAT_MACROS 10 | #include 11 | 12 | #include "compiler.h" 13 | 14 | typedef union lxc_id128 lxc_id128_t; 15 | 16 | union lxc_id128 { 17 | uint8_t bytes[16]; 18 | uint64_t qwords[2]; 19 | }; 20 | 21 | __hidden extern int lxc_id128_randomize(lxc_id128_t *ret); 22 | __hidden extern int lxc_id128_write(const char *p, lxc_id128_t id); 23 | __hidden extern int lxc_id128_write_fd(int fd, lxc_id128_t id); 24 | __hidden extern char *id128_to_uuid_string(lxc_id128_t id, char s[37]); 25 | 26 | #endif /* __LXC_UUID_H */ 27 | -------------------------------------------------------------------------------- /src/include/pthread_setcancelstate.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ * 4 | * 5 | * This is not a standard implementation. 6 | * It only protects getgrgid_r(). 7 | */ 8 | 9 | #include 10 | #include "pthread_ext.h" 11 | 12 | static const int signals[] = { 13 | SIGINT, 14 | SIGTERM, 15 | SIGQUIT, 16 | }; 17 | 18 | int pthread_setcancelstate(int state, int *oldstate) 19 | { 20 | sigset_t signal_set; 21 | sigset_t old_mask; 22 | sigemptyset(&signal_set); 23 | 24 | for (size_t i = 0; i < sizeof(signals)/sizeof(signals[0]); i++) 25 | sigaddset(&signal_set, signals[i]); 26 | 27 | int operation = (state == 1) ? SIG_UNBLOCK : SIG_BLOCK; 28 | return pthread_sigmask(operation, &signal_set, &old_mask); 29 | } 30 | -------------------------------------------------------------------------------- /doc/examples/seccomp-v2.conf: -------------------------------------------------------------------------------- 1 | 2 2 | allowlist trap 3 | # 'allowlist' would normally mean kill a task doing any syscall which is not 4 | # allowlisted below. By appending 'trap' to the line, we will cause a SIGSYS 5 | # to be sent to the task instead. 'errno 0' would mean don't allow the system 6 | # call but immediately return 0. 'errno 22' would mean return EINVAL immediately. 7 | [x86_64] 8 | open 9 | close 10 | read 11 | write 12 | mount 13 | umount2 14 | # Since we are listing system calls by name, we can also ask to have them resolved 15 | # for another arch, i.e. for 32/64-bit versions. 16 | [x86] 17 | open 18 | close 19 | read 20 | write 21 | mount 22 | umount2 23 | # Do note that this policy does not allowlist enough system calls to allow a 24 | # system container to boot. 25 | -------------------------------------------------------------------------------- /src/tests/may_control.c: -------------------------------------------------------------------------------- 1 | /* control.c 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | static void usage(const char *me) 14 | { 15 | printf("Usage: %s name [lxcpath]\n", me); 16 | exit(EXIT_SUCCESS); 17 | } 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | const char *lxcpath = NULL, *name; 22 | bool may = false; 23 | struct lxc_container *c; 24 | 25 | if (argc < 2) 26 | usage(argv[0]); 27 | 28 | name = argv[1]; 29 | 30 | if (argc == 3) 31 | lxcpath = argv[2]; 32 | 33 | c = lxc_container_new(name, lxcpath); 34 | if (c) 35 | may = c->may_control(c); 36 | 37 | printf("You may%s control %s\n", may ? "" : " not", name); 38 | exit(may ? 0 : 1); 39 | } 40 | -------------------------------------------------------------------------------- /config/init/module/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | if 'module' in init_script 4 | configured_files = [] 5 | 6 | foreach module_files: [ 7 | 'boot-completed.sh.in', 8 | 'customize.sh.in', 9 | 'module.prop.in', 10 | 'service.sh.in', 11 | 'uninstall.sh.in', 12 | ] 13 | configured_file = configure_file( 14 | input: module_files, 15 | output: '@BASENAME@', 16 | configuration: conf, 17 | ) 18 | configured_files += configured_file 19 | endforeach 20 | 21 | configure_file( 22 | command: [zip, '-rj', '@OUTPUT@', '@INPUT@'], 23 | input: configured_files, 24 | output: 'lxc-module.zip', 25 | install: true, 26 | install_dir: project_source_root) 27 | 28 | endif 29 | -------------------------------------------------------------------------------- /config/apparmor/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if libapparmor.found() 4 | configure_file( 5 | configuration: dummy_config_data, 6 | input: 'lxc-containers', 7 | output: 'lxc-containers', 8 | install: true, 9 | install_dir: join_paths(sysconfdir, 'apparmor.d')) 10 | 11 | configure_file( 12 | configuration: dummy_config_data, 13 | input: 'usr.bin.lxc-start', 14 | output: 'usr.bin.lxc-start', 15 | install: true, 16 | install_dir: join_paths(sysconfdir, 'apparmor.d')) 17 | 18 | configure_file( 19 | configuration: dummy_config_data, 20 | input: 'usr.bin.lxc-copy', 21 | output: 'usr.bin.lxc-copy', 22 | install: true, 23 | install_dir: join_paths(sysconfdir, 'apparmor.d')) 24 | endif 25 | -------------------------------------------------------------------------------- /doc/examples/lxc-complex.conf.in: -------------------------------------------------------------------------------- 1 | # Container with network a complex network mixing macvlan, veth and 2 | # physical network devices 3 | lxc.uts.name = complex 4 | lxc.net.0.type = veth 5 | lxc.net.0.flags = up 6 | lxc.net.0.link = br0 7 | lxc.net.0.hwaddr = 4a:49:43:49:79:bf 8 | lxc.net.0.ipv4.address = 10.2.3.5/24 9 | lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3597 10 | 11 | lxc.net.0.type = macvlan 12 | lxc.net.0.flags = up 13 | lxc.net.0.link = eth0 14 | lxc.net.0.hwaddr = 4a:49:43:49:79:bd 15 | lxc.net.0.ipv4.address = 10.2.3.4/24 16 | lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3596 17 | 18 | lxc.net.0.type = phys 19 | lxc.net.0.flags = up 20 | lxc.net.0.link = random0 21 | lxc.net.0.hwaddr = 4a:49:43:49:79:ff 22 | lxc.net.0.ipv4.address = 10.2.3.6/24 23 | lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3297 24 | -------------------------------------------------------------------------------- /templates/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | template_scripts = configure_file( 4 | configuration: conf, 5 | input: 'lxc-busybox.in', 6 | output: 'lxc-busybox', 7 | install: true, 8 | install_dir: lxctemplatedir) 9 | 10 | template_scripts = configure_file( 11 | configuration: conf, 12 | input: 'lxc-download.in', 13 | output: 'lxc-download', 14 | install: true, 15 | install_dir: lxctemplatedir) 16 | 17 | template_scripts = configure_file( 18 | configuration: conf, 19 | input: 'lxc-local.in', 20 | output: 'lxc-local', 21 | install: true, 22 | install_dir: lxctemplatedir) 23 | 24 | template_scripts = configure_file( 25 | configuration: conf, 26 | input: 'lxc-oci.in', 27 | output: 'lxc-oci', 28 | install: true, 29 | install_dir: lxctemplatedir) 30 | -------------------------------------------------------------------------------- /coccinelle/run-coccinelle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | top="$(git rev-parse --show-toplevel)" 4 | files="$(git ls-files ':/*.[ch]')" 5 | args= 6 | 7 | case "$1" in 8 | -i) 9 | args="$args --in-place" 10 | shift 11 | ;; 12 | esac 13 | 14 | if ! parallel -h >/dev/null; then 15 | echo 'Please install GNU parallel (package "parallel")' 16 | exit 1 17 | fi 18 | 19 | for SCRIPT in ${@-$top/coccinelle/*.cocci} ; do 20 | echo "--x-- Processing $SCRIPT --x--" 21 | TMPFILE=$(mktemp) 22 | echo "+ spatch --sp-file $SCRIPT $args ..." 23 | parallel --halt now,fail=1 --keep-order --noswap --max-args=20 \ 24 | spatch --sp-file $SCRIPT $args ::: $files \ 25 | 2>"$TMPFILE" || cat "$TMPFILE" 26 | echo -e "--x-- Processed $SCRIPT --x--\n" 27 | done 28 | -------------------------------------------------------------------------------- /src/lxc/state.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_STATE_H 4 | #define __LXC_STATE_H 5 | 6 | #include "config.h" 7 | 8 | #include "compiler.h" 9 | 10 | #define MAX_STATE_LENGTH (8 + 1) 11 | 12 | typedef enum { 13 | STOPPED, 14 | STARTING, 15 | RUNNING, 16 | STOPPING, 17 | ABORTING, 18 | FREEZING, 19 | FROZEN, 20 | THAWED, 21 | MAX_STATE, 22 | } lxc_state_t; 23 | 24 | enum { 25 | REBOOT_NONE, 26 | REBOOT_REQ, 27 | REBOOT_INIT 28 | }; 29 | 30 | __hidden extern lxc_state_t lxc_getstate(const char *name, const char *lxcpath, int timeout); 31 | 32 | __hidden extern lxc_state_t lxc_str2state(const char *state); 33 | __hidden extern const char *lxc_state2str(lxc_state_t state); 34 | __hidden extern int lxc_wait(const char *lxcname, const char *states, int timeout, 35 | const char *lxcpath); 36 | 37 | #endif /* __LXC_STATE_H */ 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | The template below is mostly useful for bug reports and support questions. 2 | Feel free to remove anything which doesn't apply to you and add more information where it makes sense. 3 | 4 | # Required information 5 | 6 | * Distribution: 7 | * Distribution version: 8 | * The output of 9 | * `lxc-start --version` 10 | * `lxc-checkconfig` 11 | * `uname -a` 12 | * `cat /proc/self/cgroup` 13 | * `cat /proc/1/mounts` 14 | 15 | # Issue description 16 | 17 | A brief description of what failed or what could be improved. 18 | 19 | # Steps to reproduce 20 | 21 | 1. Step one 22 | 2. Step two 23 | 3. Step three 24 | 25 | # Information to attach 26 | 27 | - [ ] any relevant kernel output (`dmesg`) 28 | - [ ] container log (The file from running `lxc-start -n -l TRACE -o `) 29 | - [ ] the containers configuration file 30 | -------------------------------------------------------------------------------- /src/include/fexecve.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ 4 | * 5 | */ 6 | 7 | #ifndef _GNU_SOURCE 8 | #define _GNU_SOURCE 1 9 | #endif 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include "config.h" 17 | #include "macro.h" 18 | #include "process_utils.h" 19 | 20 | int fexecve(int fd, char *const argv[], char *const envp[]) 21 | { 22 | char procfd[LXC_PROC_PID_FD_LEN]; 23 | int ret; 24 | 25 | if (fd < 0 || !argv || !envp) { 26 | errno = EINVAL; 27 | return -1; 28 | } 29 | 30 | execveat(fd, "", argv, envp, AT_EMPTY_PATH); 31 | if (errno != ENOSYS) 32 | return -1; 33 | 34 | ret = snprintf(procfd, sizeof(procfd), "/proc/self/fd/%d", fd); 35 | if (ret < 0 || (size_t)ret >= sizeof(procfd)) { 36 | errno = ENAMETOOLONG; 37 | return -1; 38 | } 39 | 40 | execve(procfd, argv, envp); 41 | return -1; 42 | } 43 | -------------------------------------------------------------------------------- /src/tests/lxc-test-procsys: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | 5 | # lxc: linux Container library 6 | 7 | # Ensure that when /proc and/or /sys do not exist in the container, 8 | # it is started successfully anyway. 9 | 10 | set -ex 11 | FAIL() { 12 | echo -n "Failed " >&2 13 | echo "$*" >&2 14 | lxc-destroy -n lxc-test-procsys -f 15 | exit 1 16 | } 17 | 18 | lxc-destroy -n lxc-test-procsys -f || : 19 | lxc-create -t busybox -n lxc-test-procsys 20 | rmdir /var/lib/lxc/lxc-test-procsys/rootfs/{proc,sys} 21 | 22 | lxc-start -n lxc-test-procsys 23 | lxc-wait -n lxc-test-procsys -s RUNNING || FAIL "waiting for busybox container to run" 24 | 25 | lxc-attach -n lxc-test-procsys -- sh -c 'test -f /proc/version' || FAIL "/proc/version not found" 26 | lxc-attach -n lxc-test-procsys -- sh -c 'test -d /sys/fs' || FAIL "/sys/fs not found" 27 | 28 | lxc-destroy -n lxc-test-procsys -f 29 | exit 0 30 | -------------------------------------------------------------------------------- /config/bash/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | bash_completion = configure_file( 4 | configuration: conf, 5 | input: '_lxc.in', 6 | output: '_lxc', 7 | install: true, 8 | install_dir: bashcompletiondir) 9 | 10 | 11 | foreach cmd: [ 12 | 'lxc-attach', 13 | 'lxc-autostart', 14 | 'lxc-cgroup', 15 | 'lxc-checkpoint', 16 | 'lxc-config', 17 | 'lxc-console', 18 | 'lxc-copy', 19 | 'lxc-create', 20 | 'lxc-destroy', 21 | 'lxc-device', 22 | 'lxc-execute', 23 | 'lxc-freeze', 24 | 'lxc-info', 25 | 'lxc-ls', 26 | 'lxc-monitor', 27 | 'lxc-snapshot', 28 | 'lxc-start', 29 | 'lxc-stop', 30 | 'lxc-top', 31 | 'lxc-unfreeze', 32 | 'lxc-unshare', 33 | 'lxc-usernsexec', 34 | 'lxc-wait', 35 | ] 36 | install_symlink(cmd, 37 | pointing_to: '_lxc', 38 | install_dir: bashcompletiondir) 39 | endforeach 40 | -------------------------------------------------------------------------------- /aarch64-android-api30.txt: -------------------------------------------------------------------------------- 1 | [binaries] 2 | c = 'android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang' 3 | cpp = 'android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang++' 4 | ar = 'android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar' 5 | as = 'android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-as' 6 | ld = 'android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ld' 7 | strip = 'android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip' 8 | ranlib = 'android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib' 9 | pkgconfig = '/usr/bin/pkg-config' 10 | cmake = '/usr/bin/cmake' 11 | 12 | [host_machine] 13 | system = 'linux' 14 | cpu_family = 'x86_64' 15 | cpu = 'x86_64' 16 | endian = 'little' 17 | 18 | [target_machine] 19 | system = 'linux' 20 | cpu_family = 'aarch64' 21 | cpu = 'aarch64' 22 | endian = 'little' 23 | -------------------------------------------------------------------------------- /src/lxc/lsm/lsm.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "compiler.h" 12 | #include "conf.h" 13 | #include "log.h" 14 | #include "lsm.h" 15 | 16 | lxc_log_define(lsm, lxc); 17 | 18 | __hidden extern struct lsm_ops *lsm_apparmor_ops_init(void); 19 | __hidden extern struct lsm_ops *lsm_selinux_ops_init(void); 20 | __hidden extern struct lsm_ops *lsm_nop_ops_init(void); 21 | 22 | struct lsm_ops *lsm_init_static(void) 23 | { 24 | struct lsm_ops *ops = NULL; 25 | 26 | #if HAVE_APPARMOR 27 | ops = lsm_apparmor_ops_init(); 28 | #endif 29 | 30 | #if HAVE_SELINUX 31 | if (!ops) 32 | ops = lsm_selinux_ops_init(); 33 | #endif 34 | 35 | if (!ops) 36 | ops = lsm_nop_ops_init(); 37 | 38 | INFO("Initialized LSM security driver %s", ops->name); 39 | return ops; 40 | } 41 | -------------------------------------------------------------------------------- /src/lxc/cgroups/cgroup_utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_CGROUP_UTILS_H 4 | #define __LXC_CGROUP_UTILS_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "compiler.h" 12 | #include "file_utils.h" 13 | 14 | __hidden extern bool unified_cgroup_fd(int fd); 15 | 16 | static inline bool cgns_supported(void) 17 | { 18 | static int supported = -1; 19 | 20 | if (supported == -1) 21 | supported = file_exists("/proc/self/ns/cgroup"); 22 | 23 | return supported == 1; 24 | } 25 | 26 | __hidden extern int cgroup_tree_prune(int dfd, const char *path); 27 | 28 | /* 29 | * This function can only be called on information parsed from 30 | * /proc//cgroup or on absolute paths and it will verify the latter and 31 | * return NULL if a relative path is passed. 32 | */ 33 | __hidden extern char *prune_init_scope(char *path); 34 | 35 | #endif /* __LXC_CGROUP_UTILS_H */ 36 | -------------------------------------------------------------------------------- /src/tests/fuzz-lxc-config-read.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: LGPL-2.1+ 3 | */ 4 | 5 | #include "config.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "conf.h" 11 | #include "confile.h" 12 | #include "lxctest.h" 13 | #include "utils.h" 14 | 15 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 16 | int fd = -1; 17 | char tmpf[] = "/tmp/fuzz-lxc-config-read-XXXXXX"; 18 | struct lxc_conf *conf = NULL; 19 | 20 | /* 21 | * 100Kb should probably be enough to trigger all the issues 22 | * we're interested in without any timeouts 23 | */ 24 | if (size > 102400) 25 | return 0; 26 | 27 | fd = lxc_make_tmpfile(tmpf, false); 28 | lxc_test_assert_abort(fd >= 0); 29 | lxc_write_nointr(fd, data, size); 30 | close(fd); 31 | 32 | conf = lxc_conf_init(); 33 | lxc_test_assert_abort(conf); 34 | lxc_config_read(tmpf, conf, false); 35 | lxc_conf_free(conf); 36 | 37 | (void) unlink(tmpf); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /doc/FAQ.txt: -------------------------------------------------------------------------------- 1 | 2 | Troubleshooting: 3 | =============== 4 | 5 | 6 | Error: 7 | ------ 8 | 9 | error while loading shared libraries reported after sudo make install 10 | and when trying to run lxc-execute. 11 | 12 | "lxc-execute -n foo -f /usr/local/etc/lxc/lxc-macvlan.conf /bin/bash" 13 | 14 | /usr/local/bin/lxc-execute: error while loading shared libraries: 15 | liblxc-0.5.0.so: cannot open shared object file: No such file or 16 | directory 17 | 18 | Answer: 19 | ------- 20 | update the ld cache by running ldconfig. 21 | 22 | 23 | 24 | Error: 25 | ------ 26 | 27 | error when starting a container. 28 | 29 | "lxc-start Invalid argument" 30 | 31 | "lxc-execute -n foo -f /usr/local/etc/lxc/lxc-macvlan.conf /bin/bash" 32 | "[syserr] lxc_start:96: Invalid argument - failed to fork into a new 33 | namespace" 34 | 35 | Answer: 36 | ------- 37 | 38 | read the lxc man page about kernel version prereq :) most probably 39 | your kernel is not configured to support the container options you 40 | want to use. 41 | -------------------------------------------------------------------------------- /doc/ja/FAQ.txt: -------------------------------------------------------------------------------- 1 | 2 | Troubleshooting: 3 | =============== 4 | 5 | 6 | Error: 7 | ------ 8 | 9 | error while loading shared libraries reported after sudo make install 10 | and when trying to run lxc-execute. 11 | 12 | "lxc-execute -n foo -f /usr/local/etc/lxc/lxc-macvlan.conf /bin/bash" 13 | 14 | /usr/local/bin/lxc-execute: error while loading shared libraries: 15 | liblxc-0.5.0.so: cannot open shared object file: No such file or 16 | directory 17 | 18 | Answer: 19 | ------- 20 | update the ld cache by running ldconfig. 21 | 22 | 23 | 24 | Error: 25 | ------ 26 | 27 | error when starting a container. 28 | 29 | "lxc-start Invalid argument" 30 | 31 | "lxc-execute -n foo -f /usr/local/etc/lxc/lxc-macvlan.conf /bin/bash" 32 | "[syserr] lxc_start:96: Invalid argument - failed to fork into a new 33 | namespace" 34 | 35 | Answer: 36 | ------- 37 | 38 | read the lxc man page about kernel version prereq :) most probably 39 | your kernel is not configured to support the container options you 40 | want to use. 41 | -------------------------------------------------------------------------------- /doc/ko/FAQ.txt: -------------------------------------------------------------------------------- 1 | 2 | Troubleshooting: 3 | =============== 4 | 5 | 6 | Error: 7 | ------ 8 | 9 | error while loading shared libraries reported after sudo make install 10 | and when trying to run lxc-execute. 11 | 12 | "lxc-execute -n foo -f /usr/local/etc/lxc/lxc-macvlan.conf /bin/bash" 13 | 14 | /usr/local/bin/lxc-execute: error while loading shared libraries: 15 | liblxc-0.5.0.so: cannot open shared object file: No such file or 16 | directory 17 | 18 | Answer: 19 | ------- 20 | update the ld cache by running ldconfig. 21 | 22 | 23 | 24 | Error: 25 | ------ 26 | 27 | error when starting a container. 28 | 29 | "lxc-start Invalid argument" 30 | 31 | "lxc-execute -n foo -f /usr/local/etc/lxc/lxc-macvlan.conf /bin/bash" 32 | "[syserr] lxc_start:96: Invalid argument - failed to fork into a new 33 | namespace" 34 | 35 | Answer: 36 | ------- 37 | 38 | read the lxc man page about kernel version prereq :) most probably 39 | your kernel is not configured to support the container options you 40 | want to use. 41 | -------------------------------------------------------------------------------- /src/lxc/storage/dir.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_DIR_H 4 | #define __LXC_DIR_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "compiler.h" 12 | 13 | struct lxc_storage; 14 | 15 | struct bdev_specs; 16 | 17 | struct lxc_conf; 18 | 19 | __hidden extern int dir_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, 20 | const char *oldname, const char *cname, const char *oldpath, 21 | const char *lxcpath, int snap, uint64_t newsize, 22 | struct lxc_conf *conf); 23 | __hidden extern int dir_create(struct lxc_storage *bdev, const char *dest, const char *n, 24 | struct bdev_specs *specs, const struct lxc_conf *conf); 25 | __hidden extern int dir_destroy(struct lxc_storage *orig); 26 | __hidden extern bool dir_detect(const char *path); 27 | __hidden extern int dir_mount(struct lxc_storage *bdev); 28 | __hidden extern int dir_umount(struct lxc_storage *bdev); 29 | 30 | #endif /* __LXC_DIR_H */ 31 | -------------------------------------------------------------------------------- /src/lxc/storage/rbd.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_RDB_H 4 | #define __LXC_RDB_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "compiler.h" 12 | 13 | struct lxc_storage; 14 | 15 | struct bdev_specs; 16 | 17 | struct lxc_conf; 18 | 19 | __hidden extern int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, 20 | const char *oldname, const char *cname, const char *oldpath, 21 | const char *lxcpath, int snap, uint64_t newsize, 22 | struct lxc_conf *conf); 23 | __hidden extern int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n, 24 | struct bdev_specs *specs, const struct lxc_conf *conf); 25 | __hidden extern int rbd_destroy(struct lxc_storage *orig); 26 | __hidden extern bool rbd_detect(const char *path); 27 | __hidden extern int rbd_mount(struct lxc_storage *bdev); 28 | __hidden extern int rbd_umount(struct lxc_storage *bdev); 29 | 30 | #endif /* __LXC_RDB_H */ 31 | -------------------------------------------------------------------------------- /src/lxc/storage/loop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_LOOP_H 4 | #define __LXC_LOOP_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "compiler.h" 12 | 13 | struct lxc_storage; 14 | 15 | struct bdev_specs; 16 | 17 | struct lxc_conf; 18 | 19 | __hidden extern int loop_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, 20 | const char *oldname, const char *cname, const char *oldpath, 21 | const char *lxcpath, int snap, uint64_t newsize, 22 | struct lxc_conf *conf); 23 | __hidden extern int loop_create(struct lxc_storage *bdev, const char *dest, const char *n, 24 | struct bdev_specs *specs, const struct lxc_conf *conf); 25 | __hidden extern int loop_destroy(struct lxc_storage *orig); 26 | __hidden extern bool loop_detect(const char *path); 27 | __hidden extern int loop_mount(struct lxc_storage *bdev); 28 | __hidden extern int loop_umount(struct lxc_storage *bdev); 29 | 30 | #endif /* __LXC_LOOP_H */ 31 | -------------------------------------------------------------------------------- /config/sysconfig/lxc.in: -------------------------------------------------------------------------------- 1 | # LXC_AUTO - whether or not to start containers at boot 2 | LXC_AUTO="true" 3 | 4 | # BOOTGROUPS - What groups should start on bootup? 5 | # Comma separated list of groups. 6 | # Leading comma, trailing comma or embedded double 7 | # comma indicates when the NULL group should be run. 8 | # Example (default): boot the onboot group first then the NULL group 9 | BOOTGROUPS="onboot," 10 | 11 | # SHUTDOWNDELAY - Wait time for a container to shut down. 12 | # Container shutdown can result in lengthy system 13 | # shutdown times. Even 5 seconds per container can be 14 | # too long. 15 | SHUTDOWNDELAY=5 16 | 17 | # OPTIONS can be used for anything else. 18 | # If you want to boot everything then 19 | # options can be "-a" or "-a -A". 20 | OPTIONS= 21 | 22 | # STOPOPTS are stop options. The can be used for anything else to stop. 23 | # If you want to kill containers fast, use -k 24 | STOPOPTS="-a -A -s" 25 | 26 | USE_LXC_BRIDGE="false" 27 | 28 | [ ! -f @LXC_DISTRO_SYSCONF@/lxc-net ] || . @LXC_DISTRO_SYSCONF@/lxc-net 29 | -------------------------------------------------------------------------------- /src/lxc/idmap_utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_IDMAP_UTILS_H 4 | #define __LXC_IDMAP_UTILS_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "compiler.h" 17 | #include "conf.h" 18 | 19 | __hidden extern int lxc_map_ids(struct list_head *idmap, pid_t pid); 20 | __hidden extern int find_unmapped_nsid(const struct lxc_conf *conf, enum idtype idtype); 21 | __hidden extern int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype); 22 | __hidden extern struct id_map *mapped_hostid_add(const struct lxc_conf *conf, uid_t id, 23 | enum idtype type); 24 | __hidden extern struct id_map *mapped_nsid_add(const struct lxc_conf *conf, unsigned id, 25 | enum idtype idtype); 26 | 27 | __hidden extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, size_t buf_size) 28 | __access_r(3, 4); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/tests/lxc-test-exit-code: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | 5 | # lxc: linux Container library 6 | 7 | set -e 8 | 9 | FAIL() { 10 | echo -n "Failed " >&2 11 | echo "$*" >&2 12 | lxc-destroy -n busy -f 13 | exit 1 14 | } 15 | 16 | # Create a container 17 | lxc-create -t busybox -n busy || FAIL "creating busybox container" 18 | 19 | # Run lxc-execute to make sure it fails when the command fails, and 20 | # succeed when the command succeeds. 21 | lxc-execute -n busy -- sh -c 'exit 1' && FAIL "should be failing" || true 22 | lxc-execute -n busy -- sh -c 'exit 0' || FAIL "should be succeeding" 23 | 24 | # Now, start the container and wait for it to be in running state. 25 | lxc-start -n busy -d || FAIL "starting busybox container" 26 | lxc-wait -n busy -s RUNNING || FAIL "waiting for busybox container to run" 27 | 28 | # And run the same tests on lxc-attach. 29 | lxc-attach -n busy -- sh -c 'exit 1' && FAIL "should be failing" || true 30 | lxc-attach -n busy -- sh -c 'exit 0' || FAIL "should be succeeding" 31 | 32 | lxc-destroy -n busy -f 33 | 34 | exit 0 35 | -------------------------------------------------------------------------------- /src/lxc/parse.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_PARSE_H 4 | #define __LXC_PARSE_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "compiler.h" 12 | 13 | typedef int (*lxc_dir_cb)(const char *name, const char *directory, 14 | const char *file, void *data); 15 | 16 | typedef int (*lxc_file_cb)(char *buffer, void *data); 17 | 18 | __hidden __hot extern int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data); 19 | 20 | __hidden __hot extern int lxc_file_for_each_line_mmap(const char *file, lxc_file_cb callback, 21 | void *data); 22 | 23 | /* mmap() wrapper. lxc_strmmap() will take care to \0-terminate files so that 24 | * normal string-handling functions can be used on the buffer. */ 25 | __hidden extern void *lxc_strmmap(void *addr, size_t length, int prot, int flags, int fd, 26 | off_t offset); 27 | /* munmap() wrapper. Use it to free memory mmap()ed with lxc_strmmap(). */ 28 | __hidden extern int lxc_strmunmap(void *addr, size_t length); 29 | 30 | #endif /* __LXC_PARSE_H */ 31 | -------------------------------------------------------------------------------- /config/templates/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | lxc_conf_common_seccomp = configure_file( 4 | configuration: conf, 5 | input: 'common.seccomp', 6 | output: 'common.seccomp', 7 | install: true, 8 | install_dir: lxctemplateconfdir) 9 | 10 | lxc_conf_common_main = configure_file( 11 | configuration: conf, 12 | input: 'common.conf.in', 13 | output: 'common.conf', 14 | install: true, 15 | install_dir: lxctemplateconfdir) 16 | 17 | lxc_conf_common_nesting = configure_file( 18 | configuration: conf, 19 | input: 'nesting.conf.in', 20 | output: 'nesting.conf', 21 | install: true, 22 | install_dir: lxctemplateconfdir) 23 | 24 | lxc_conf_common_oci = configure_file( 25 | configuration: conf, 26 | input: 'oci.common.conf.in', 27 | output: 'oci.common.conf', 28 | install: true, 29 | install_dir: lxctemplateconfdir) 30 | 31 | lxc_conf_common_userns = configure_file( 32 | configuration: conf, 33 | input: 'userns.conf.in', 34 | output: 'userns.conf', 35 | install: true, 36 | install_dir: lxctemplateconfdir) 37 | -------------------------------------------------------------------------------- /.github/workflows/commits.yml: -------------------------------------------------------------------------------- 1 | name: Commits 2 | on: 3 | - pull_request 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | dco-check: 10 | permissions: 11 | pull-requests: read # for tim-actions/get-pr-commits to get list of commits from the PR 12 | name: Signed-off-by (DCO) 13 | runs-on: ubuntu-24.04 14 | steps: 15 | - name: Get PR Commits 16 | id: 'get-pr-commits' 17 | uses: tim-actions/get-pr-commits@master 18 | with: 19 | token: ${{ secrets.GITHUB_TOKEN }} 20 | 21 | - name: Check that all commits are signed-off 22 | uses: tim-actions/dco@master 23 | with: 24 | commits: ${{ steps.get-pr-commits.outputs.commits }} 25 | 26 | target-branch: 27 | permissions: 28 | contents: none 29 | name: Branch target 30 | runs-on: ubuntu-24.04 31 | steps: 32 | - name: Check branch target 33 | env: 34 | TARGET: ${{ github.event.pull_request.base.ref }} 35 | run: | 36 | set -x 37 | [ "${TARGET}" = "main" ] && exit 0 38 | 39 | echo "Invalid branch target: ${TARGET}" 40 | exit 1 41 | -------------------------------------------------------------------------------- /src/lxc/namespace.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_NAMESPACE_H 4 | #define __LXC_NAMESPACE_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "compiler.h" 13 | 14 | typedef enum lxc_namespace_t { 15 | LXC_NS_USER = 0, 16 | LXC_NS_MNT = 1, 17 | LXC_NS_PID = 2, 18 | LXC_NS_UTS = 3, 19 | LXC_NS_IPC = 4, 20 | LXC_NS_NET = 5, 21 | LXC_NS_CGROUP = 6, 22 | LXC_NS_TIME = 7, 23 | LXC_NS_MAX = 8 24 | } lxc_namespace_t; 25 | 26 | __hidden extern const struct ns_info { 27 | #define MAX_NS_PROC_NAME 6 28 | const char proc_name[MAX_NS_PROC_NAME + 1]; 29 | const char *proc_path; 30 | int clone_flag; 31 | const char *flag_name; 32 | const char *env_name; 33 | } ns_info[LXC_NS_MAX]; 34 | 35 | __hidden extern int lxc_namespace_2_cloneflag(const char *namespace); 36 | __hidden extern int lxc_namespace_2_ns_idx(const char *namespace); 37 | __hidden extern int lxc_namespace_2_std_identifiers(char *namespaces); 38 | __hidden extern int lxc_fill_namespace_flags(char *flaglist, int *flags); 39 | 40 | #endif /* __LXC_NAMESPACE_H */ 41 | -------------------------------------------------------------------------------- /config/apparmor/profiles/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if libapparmor.found() 4 | configure_file( 5 | configuration: dummy_config_data, 6 | input: 'lxc-default', 7 | output: 'lxc-default', 8 | install: true, 9 | install_dir: join_paths(sysconfdir, 'apparmor.d', 'lxc')) 10 | 11 | configure_file( 12 | configuration: dummy_config_data, 13 | input: 'lxc-default-cgns', 14 | output: 'lxc-default-cgns', 15 | install: true, 16 | install_dir: join_paths(sysconfdir, 'apparmor.d', 'lxc')) 17 | 18 | configure_file( 19 | configuration: dummy_config_data, 20 | input: 'lxc-default-with-mounting', 21 | output: 'lxc-default-with-mounting', 22 | install: true, 23 | install_dir: join_paths(sysconfdir, 'apparmor.d', 'lxc')) 24 | 25 | configure_file( 26 | configuration: dummy_config_data, 27 | input: 'lxc-default-with-nesting', 28 | output: 'lxc-default-with-nesting', 29 | install: true, 30 | install_dir: join_paths(sysconfdir, 'apparmor.d', 'lxc')) 31 | endif 32 | -------------------------------------------------------------------------------- /src/lxc/error_utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_ERROR_UTILS_H 4 | #define __LXC_ERROR_UTILS_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | 10 | #include "macro.h" 11 | 12 | #define MAX_ERRNO 4095 13 | 14 | #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) 15 | 16 | static inline void *ERR_PTR(long error) 17 | { 18 | return (void *)error; 19 | } 20 | 21 | static inline long PTR_ERR(const void *ptr) 22 | { 23 | return (long)ptr; 24 | } 25 | 26 | static inline long IS_ERR(const void *ptr) 27 | { 28 | return IS_ERR_VALUE((unsigned long)ptr); 29 | } 30 | 31 | static inline long IS_ERR_OR_NULL(const void *ptr) 32 | { 33 | return !ptr || IS_ERR_VALUE((unsigned long)ptr); 34 | } 35 | 36 | static inline void *ERR_CAST(const void *ptr) 37 | { 38 | return (void *)ptr; 39 | } 40 | 41 | static inline int PTR_RET(const void *ptr) 42 | { 43 | if (IS_ERR(ptr)) 44 | return PTR_ERR(ptr); 45 | else 46 | return 0; 47 | } 48 | 49 | static inline bool ERRNO_IS_NOT_SUPPORTED(int r) { 50 | int x = abs(r); 51 | return x == EOPNOTSUPP || x == ENOSYS; 52 | } 53 | 54 | #endif /* __LXC_ERROR_UTILS_H */ 55 | -------------------------------------------------------------------------------- /src/lxc/error.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "error.h" 10 | #include "log.h" 11 | #include "process_utils.h" 12 | 13 | lxc_log_define(error, lxc); 14 | 15 | /*---------------------------------------------------------------------------*/ 16 | /* lxc_error_set_and_log 17 | * function is here to convert 18 | * the reported status to an exit code as detailed here: 19 | * 20 | * 0-126 exit code of the application 21 | * 128+n signal n received by the application 22 | * 255 lxc error 23 | */ 24 | int lxc_error_set_and_log(int pid, int status) 25 | { 26 | int ret = 0; 27 | 28 | if (WIFEXITED(status)) { 29 | ret = WEXITSTATUS(status); 30 | if (ret) 31 | INFO("Child <%d> ended on error (%d)", pid, ret); 32 | } else if (WIFSIGNALED(status)) { 33 | int signal_nr = WTERMSIG(status); 34 | INFO("Child <%d> ended on signal %s(%d)", pid, signal_name(signal_nr), signal_nr); 35 | ret = 128 + signal_nr; 36 | } else { 37 | ERROR("Invalid exit status (%d)", status); 38 | } 39 | 40 | return ret; 41 | } 42 | -------------------------------------------------------------------------------- /src/lxc/storage/nbd.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_NBD_H 4 | #define __LXC_NBD_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "compiler.h" 12 | 13 | struct lxc_storage; 14 | 15 | struct bdev_specs; 16 | 17 | struct lxc_conf; 18 | 19 | __hidden extern int nbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, 20 | const char *oldname, const char *cname, const char *oldpath, 21 | const char *lxcpath, int snap, uint64_t newsize, 22 | struct lxc_conf *conf); 23 | __hidden extern int nbd_create(struct lxc_storage *bdev, const char *dest, const char *n, 24 | struct bdev_specs *specs, const struct lxc_conf *conf); 25 | __hidden extern int nbd_destroy(struct lxc_storage *orig); 26 | __hidden extern bool nbd_detect(const char *path); 27 | __hidden extern int nbd_mount(struct lxc_storage *bdev); 28 | __hidden extern int nbd_umount(struct lxc_storage *bdev); 29 | __hidden extern bool attach_nbd(char *src, struct lxc_conf *conf); 30 | __hidden extern void detach_nbd_idx(int idx); 31 | __hidden extern bool requires_nbd(const char *path); 32 | 33 | #endif /* __LXC_NBD_H */ 34 | -------------------------------------------------------------------------------- /config/yum/lxc-patch.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | # 3 | # Yum plugin to re-patch container rootfs after a yum update is done 4 | 5 | import os 6 | from fnmatch import fnmatch 7 | from yum.plugins import TYPE_INTERACTIVE 8 | 9 | requires_api_version = '2.0' 10 | plugin_type = (TYPE_INTERACTIVE,) 11 | 12 | def posttrans_hook(conduit): 13 | pkgs = [] 14 | patch_required = False 15 | 16 | # If we aren't root, we can't have updated anything 17 | if os.geteuid(): 18 | return 19 | 20 | # See what packages have files that were patched 21 | confpkgs = conduit.confString('main', 'packages') 22 | if not confpkgs: 23 | return 24 | 25 | tmp = confpkgs.split(",") 26 | for confpkg in tmp: 27 | pkgs.append(confpkg.strip()) 28 | 29 | conduit.info(2, "lxc-patch: checking if updated pkgs need patching...") 30 | ts = conduit.getTsInfo() 31 | for tsmem in ts.getMembers(): 32 | for pkg in pkgs: 33 | if fnmatch(pkg, tsmem.po.name): 34 | patch_required = True 35 | if patch_required: 36 | conduit.info(2, "lxc-patch: patching container...") 37 | os.spawnlp(os.P_WAIT, "lxc-patch", "lxc-patch", "--patch", "/") 38 | -------------------------------------------------------------------------------- /src/include/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | include_sources = files( 4 | 'bpf.h', 5 | 'bpf_common.h') 6 | 7 | netns_ifaddrs_sources = files( 8 | 'netns_ifaddrs.c', 9 | 'netns_ifaddrs.h') 10 | 11 | if srcconf.get('HAVE_FEXECVE') == 0 12 | include_sources += files( 13 | 'fexecve.c', 14 | 'fexecve.h') 15 | endif 16 | 17 | 18 | if srcconf.get('HAVE_GETGRGID_R') == 0 19 | include_sources += files( 20 | 'getgrgid_r.c', 21 | 'getgrgid_r.h') 22 | endif 23 | 24 | if srcconf.get('HAVE_STRLCPY') == 0 25 | include_sources += files( 26 | 'strlcpy.c', 27 | 'strlcpy.h') 28 | endif 29 | 30 | if srcconf.get('HAVE_STRLCAT') == 0 31 | include_sources += files( 32 | 'strlcat.c', 33 | 'strlcat.h') 34 | endif 35 | 36 | if srcconf.get('HAVE_STRCHRNUL') == 0 37 | include_sources += files( 38 | 'strchrnul.c', 39 | 'strchrnul.h') 40 | endif 41 | 42 | if srcconf.get('HAVE_HASMNTOPT') == 0 43 | include_sources += files( 44 | 'hasmntopt.c', 45 | 'hasmntopt.h') 46 | endif 47 | 48 | if srcconf.get('HAVE_PTHREAD_SETCANCELSTATE') == 0 49 | include_sources += files( 50 | 'pthread_setcancelstate.c', 51 | 'pthread_ext.h') 52 | endif 53 | -------------------------------------------------------------------------------- /src/tests/fuzz-lxc-cgroup-init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: LGPL-2.1+ 3 | */ 4 | 5 | #include "config.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "cgroups/cgroup.h" 11 | #include "conf.h" 12 | #include "confile.h" 13 | #include "lxctest.h" 14 | #include "utils.h" 15 | 16 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 17 | int fd = -1; 18 | char tmpf[] = "/tmp/fuzz-lxc-cgroup-init-XXXXXX"; 19 | struct lxc_conf *conf = NULL; 20 | int ret; 21 | struct cgroup_ops *ops; 22 | 23 | /* 24 | * 100Kb should probably be enough to trigger all the issues 25 | * we're interested in without any timeouts 26 | */ 27 | if (size > 102400) 28 | return 0; 29 | 30 | fd = lxc_make_tmpfile(tmpf, false); 31 | lxc_test_assert_abort(fd >= 0); 32 | lxc_write_nointr(fd, data, size); 33 | close(fd); 34 | 35 | conf = lxc_conf_init(); 36 | lxc_test_assert_abort(conf); 37 | 38 | /* Test cgroup_init() with valid config. */ 39 | ops = cgroup_init(conf); 40 | cgroup_exit(ops); 41 | 42 | ret = lxc_config_read(tmpf, conf, false); 43 | if (ret == 0) { 44 | /* Test cgroup_init() with likely garbage config. */ 45 | ops = cgroup_init(conf); 46 | cgroup_exit(ops); 47 | } 48 | lxc_conf_free(conf); 49 | 50 | (void) unlink(tmpf); 51 | 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/lxc/storage/zfs.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_ZFS_H 4 | #define __LXC_ZFS_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "compiler.h" 13 | 14 | struct lxc_storage; 15 | 16 | struct bdev_specs; 17 | 18 | struct lxc_conf; 19 | 20 | __hidden extern int zfs_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, 21 | const char *oldname, const char *cname, const char *oldpath, 22 | const char *lxcpath, int snap, uint64_t newsize, 23 | struct lxc_conf *conf); 24 | __hidden extern int zfs_create(struct lxc_storage *bdev, const char *dest, const char *n, 25 | struct bdev_specs *specs, const struct lxc_conf *conf); 26 | __hidden extern int zfs_destroy(struct lxc_storage *orig); 27 | __hidden extern bool zfs_detect(const char *path); 28 | __hidden extern int zfs_mount(struct lxc_storage *bdev); 29 | __hidden extern int zfs_umount(struct lxc_storage *bdev); 30 | __hidden extern bool zfs_copy(struct lxc_conf *conf, struct lxc_storage *orig, 31 | struct lxc_storage *new, uint64_t newsize); 32 | __hidden extern bool zfs_snapshot(struct lxc_conf *conf, struct lxc_storage *orig, 33 | struct lxc_storage *new, uint64_t newsize); 34 | 35 | #endif /* __LXC_ZFS_H */ 36 | -------------------------------------------------------------------------------- /.github/workflows/fuzzing.yml: -------------------------------------------------------------------------------- 1 | name: Fuzzing 2 | on: 3 | push: 4 | branches: 5 | 6 | permissions: 7 | contents: read 8 | 9 | jobs: 10 | fuzzing: 11 | name: OSS-Fuzz 12 | runs-on: ubuntu-24.04 13 | if: github.repository == 'lxc/lxc' 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | sanitizer: 18 | - address 19 | - undefined 20 | - memory 21 | steps: 22 | - name: Build Fuzzers (${{ matrix.sanitizer }}) 23 | id: build 24 | uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master 25 | with: 26 | oss-fuzz-project-name: 'lxc' 27 | dry-run: false 28 | allowed-broken-targets-percentage: 0 29 | sanitizer: ${{ matrix.sanitizer }} 30 | 31 | - name: Run Fuzzers (${{ matrix.sanitizer }}) 32 | uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master 33 | with: 34 | oss-fuzz-project-name: 'lxc' 35 | fuzz-seconds: 360 36 | dry-run: false 37 | sanitizer: ${{ matrix.sanitizer }} 38 | 39 | - name: Upload Crash 40 | uses: actions/upload-artifact@v6 41 | if: failure() && steps.build.outcome == 'success' 42 | with: 43 | name: ${{ matrix.sanitizer }}-artifacts 44 | path: ./out/artifacts 45 | -------------------------------------------------------------------------------- /hooks/squid-deb-proxy-client: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # SPDX-License-Identifier: GPL-2.0-only 4 | # 5 | # Make the cloned container aware of squid-deb-proxy settings at start. 6 | 7 | # When starting a container, inject the squid-deb-proxy-client proxy 8 | # address in the container's apt configuration. 9 | # This script should be added to templates as a pre-start script, such as: 10 | #lxc.hook.pre-start=/usr/share/lxc/hooks/squid-deb-proxy-client 11 | 12 | discovery_script=/usr/share/squid-deb-proxy-client/apt-avahi-discover 13 | proxy_file=/etc/apt/apt.conf.d/50squid-deb-proxy 14 | container_proxy_file=$LXC_ROOTFS_PATH$proxy_file 15 | 16 | if [ -f $proxy_file ]; then 17 | # The host has a proxy file - let's propagate the config to the guest. 18 | cat $proxy_file > $container_proxy_file 19 | exit 0 20 | fi 21 | 22 | if [ ! -f $discovery_script ]; then 23 | # There is no squid-deb-proxy-client package installed. Do nothing. 24 | exit 0 25 | fi 26 | 27 | proxy_line=$($discovery_script) #XXX: Could be multiline? 28 | 29 | if [ -n "$proxy_line" ]; then 30 | doc="# Detected at container start from the host's squid-deb-proxy-client" 31 | echo "Acquire::http::proxy \"$proxy_line\"; $doc" > $container_proxy_file 32 | else 33 | if [ -f $proxy_file ]; then 34 | rm $proxy_file 35 | fi 36 | fi 37 | exit 0 38 | -------------------------------------------------------------------------------- /src/lxc/lsm/lsm.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_LSM_H 4 | #define __LXC_LSM_H 5 | 6 | #include "config.h" 7 | 8 | struct lxc_conf; 9 | 10 | #include 11 | 12 | #include "compiler.h" 13 | #include "macro.h" 14 | #include "utils.h" 15 | 16 | struct lsm_ops { 17 | const char *name; 18 | 19 | /* AppArmor specific fields. */ 20 | int aa_enabled; 21 | int aa_parser_available; 22 | int aa_supports_unix; 23 | int aa_can_stack; 24 | int aa_is_stacked; 25 | int aa_admin; 26 | int aa_mount_features_enabled; 27 | 28 | int (*enabled)(struct lsm_ops *ops); 29 | char *(*process_label_get)(struct lsm_ops *ops, pid_t pid); 30 | int (*process_label_set)(struct lsm_ops *ops, const char *label, struct lxc_conf *conf, bool on_exec); 31 | int (*keyring_label_set)(struct lsm_ops *ops, const char *label); 32 | int (*prepare)(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath); 33 | void (*cleanup)(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath); 34 | int (*process_label_fd_get)(struct lsm_ops *ops, pid_t pid, bool on_exec); 35 | char *(*process_label_get_at)(struct lsm_ops *ops, int fd_pid); 36 | int (*process_label_set_at)(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec); 37 | }; 38 | 39 | __hidden extern struct lsm_ops *lsm_init_static(void); 40 | 41 | #endif /* __LXC_LSM_H */ 42 | -------------------------------------------------------------------------------- /config/init/systemd/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | lxc_apparmor_load = configure_file( 4 | configuration: dummy_config_data, 5 | input: 'lxc-apparmor-load', 6 | output: 'lxc-apparmor-load', 7 | install: true, 8 | install_dir: lxclibexec) 9 | 10 | if 'systemd' in init_script 11 | systemd_system_unit_dir = get_option('systemd-unitdir') 12 | if systemd_system_unit_dir == '' 13 | systemd = dependency('systemd') 14 | systemd_system_unit_dir = systemd.get_variable('systemdsystemunitdir') 15 | endif 16 | 17 | configure_file( 18 | configuration: conf, 19 | input: 'lxc-monitord.service.in', 20 | output: 'lxc-monitord.service', 21 | install: true, 22 | install_dir: systemd_system_unit_dir) 23 | 24 | configure_file( 25 | configuration: conf, 26 | input: 'lxc-net.service.in', 27 | output: 'lxc-net.service', 28 | install: true, 29 | install_dir: systemd_system_unit_dir) 30 | 31 | configure_file( 32 | configuration: conf, 33 | input: 'lxc.service.in', 34 | output: 'lxc.service', 35 | install: true, 36 | install_dir: systemd_system_unit_dir) 37 | 38 | configure_file( 39 | configuration: conf, 40 | input: 'lxc@.service.in', 41 | output: 'lxc@.service', 42 | install: true, 43 | install_dir: systemd_system_unit_dir) 44 | endif 45 | -------------------------------------------------------------------------------- /src/lxc/execute.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "conf.h" 13 | #include "log.h" 14 | #include "start.h" 15 | #include "process_utils.h" 16 | #include "utils.h" 17 | #include "initutils.h" 18 | 19 | lxc_log_define(execute, start); 20 | 21 | static int execute_start(struct lxc_handler *handler, void* data) 22 | { 23 | int argc = 0; 24 | struct execute_args *my_args = data; 25 | 26 | while (my_args->argv[argc++]); 27 | 28 | lxc_container_init(argc, my_args->argv, my_args->quiet); 29 | } 30 | 31 | static int execute_post_start(struct lxc_handler *handler, void* data) 32 | { 33 | struct execute_args *my_args = data; 34 | NOTICE("'%s' started with pid '%d'", my_args->argv[0], handler->pid); 35 | return 0; 36 | } 37 | 38 | static struct lxc_operations execute_start_ops = { 39 | .start = execute_start, 40 | .post_start = execute_post_start 41 | }; 42 | 43 | int lxc_execute(const char *name, char *const argv[], int quiet, 44 | struct lxc_handler *handler, const char *lxcpath, 45 | bool daemonize, int *error_num) 46 | { 47 | struct execute_args args = {.argv = argv, .quiet = quiet}; 48 | 49 | TRACE("Doing lxc_execute"); 50 | handler->conf->is_execute = true; 51 | return __lxc_start(handler, &execute_start_ops, &args, lxcpath, 52 | daemonize, error_num); 53 | } 54 | -------------------------------------------------------------------------------- /src/lxc/initutils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_INITUTILS_H 4 | #define __LXC_INITUTILS_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "compiler.h" 22 | #include "string_utils.h" 23 | 24 | #define DEFAULT_VG "lxc" 25 | #define DEFAULT_THIN_POOL "lxc" 26 | #define DEFAULT_ZFSROOT "lxc" 27 | #define DEFAULT_RBDPOOL "lxc" 28 | #define DEFAULT_RBDUSER NULL 29 | 30 | #ifndef PR_SET_MM 31 | #define PR_SET_MM 35 32 | #endif 33 | 34 | #ifndef PR_SET_MM_MAP 35 | #define PR_SET_MM_MAP 14 36 | 37 | struct prctl_mm_map { 38 | uint64_t start_code; 39 | uint64_t end_code; 40 | uint64_t start_data; 41 | uint64_t end_data; 42 | uint64_t start_brk; 43 | uint64_t brk; 44 | uint64_t start_stack; 45 | uint64_t arg_start; 46 | uint64_t arg_end; 47 | uint64_t env_start; 48 | uint64_t env_end; 49 | uint64_t *auxv; 50 | uint32_t auxv_size; 51 | uint32_t exe_fd; 52 | }; 53 | #endif 54 | 55 | __hidden extern const char *lxc_global_config_value(const char *option_name); 56 | 57 | __hidden extern int setproctitle(char *title); 58 | 59 | __hidden __noreturn int lxc_container_init(int argc, char *const *argv, bool quiet); 60 | 61 | #endif /* __LXC_INITUTILS_H */ 62 | -------------------------------------------------------------------------------- /config/init/sysvinit/lxc-net.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh - 2 | # 3 | # lxc-net Start/Stop LXC Networking 4 | # 5 | # chkconfig: 345 98 01 6 | # description: Starts/Stops LXC Network Bridge 7 | # 8 | ### BEGIN INIT INFO 9 | # Provides: lxc-net 10 | # Required-Start: $syslog $remote_fs 11 | # Required-Stop: $syslog $remote_fs 12 | # Should-Start: 13 | # Should-Stop: 14 | # Default-Start: 2 3 4 5 15 | # Default-Stop: 0 1 6 16 | # Short-Description: Bring up/down LXC Network Bridge 17 | # Description: Bring up/down LXC Network Bridge 18 | ### END INIT INFO 19 | 20 | # To be replaced by LSB functions, if they can be found 21 | # Defined here for distributions that don't have log_daemon_msg 22 | log_daemon_msg () { 23 | echo $@ 24 | } 25 | 26 | # Try to source LSB init functions to define LSB log_* functions. 27 | test ! -r /lib/lsb/init-functions || 28 | . /lib/lsb/init-functions 29 | 30 | start() { 31 | log_daemon_msg "Starting LXC network bridge: " 32 | @LIBEXECDIR@/lxc/lxc-net start 33 | } 34 | 35 | stop() { 36 | log_daemon_msg "Stopping LXC network bridge: " 37 | @LIBEXECDIR@/lxc/lxc-net stop 38 | } 39 | 40 | # See how we were called. 41 | case "$1" in 42 | start) 43 | start 44 | ;; 45 | 46 | stop) 47 | stop 48 | ;; 49 | 50 | restart|reload|force-reload) 51 | $0 stop 52 | $0 start 53 | ;; 54 | 55 | *) 56 | echo "Usage: $0 {start|stop|restart|reload|force-reload}" 57 | exit 2 58 | ;; 59 | esac 60 | 61 | exit $? 62 | -------------------------------------------------------------------------------- /doc/lxc.container.conf: -------------------------------------------------------------------------------- 1 | # the fstab mount file 2 | lxc.mount.fstab = ./fstab 3 | 4 | # the hostname to be set into the container 5 | lxc.utsname = virtnode 6 | 7 | # The network has several of kind of configuration: 8 | # 9 | # * veth : the network will use the veth virtual device, the specified 10 | # link must be a bridge 11 | # * macvlan : the network will use the macvlan device, the specified link 12 | # should be an existing interface, usually it is eth0 13 | # * phys : the network will use a physical network device, the specified 14 | # link should be an existing interface 15 | lxc.net.0.type = macvlan 16 | 17 | # specify the flags to be used for the network, actually only is allowed 18 | # which mean the network should be set up when created. If the network is set 19 | # up, the loopback is automatically set up too. 20 | lxc.net.0.flags = up 21 | 22 | # specify the physical network device which will communicate with the 23 | # outside world 24 | lxc.net.0.link = eth0 25 | 26 | # NIC ethernet mac address 27 | lxc.net.0.hwaddr = 4a:49:43:49:79:bd 28 | 29 | # specify the ipv4 address of the container. Several lines are allowed and 30 | # will mean several addresses will be assigned to the interface 31 | lxc.net.0.ipv4.address = 1.2.3.5/24 32 | 33 | # specify the ipv6 address of the container. Several lines are allowed and 34 | # will mean several addresses will be assigned to the interface 35 | lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3596 36 | 37 | -------------------------------------------------------------------------------- /src/lxc/storage/lvm.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_LVM_H 4 | #define __LXC_LVM_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "compiler.h" 12 | 13 | struct lxc_storage; 14 | 15 | struct bdev_specs; 16 | 17 | struct lxc_conf; 18 | 19 | __hidden extern bool lvm_detect(const char *path); 20 | __hidden extern int lvm_mount(struct lxc_storage *bdev); 21 | __hidden extern int lvm_umount(struct lxc_storage *bdev); 22 | __hidden extern int lvm_compare_lv_attr(const char *path, int pos, const char expected); 23 | __hidden extern int lvm_is_thin_volume(const char *path); 24 | __hidden extern int lvm_is_thin_pool(const char *path); 25 | __hidden extern int lvm_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, 26 | const char *oldname, const char *cname, const char *oldpath, 27 | const char *lxcpath, int snap, uint64_t newsize, 28 | struct lxc_conf *conf); 29 | __hidden extern int lvm_destroy(struct lxc_storage *orig); 30 | __hidden extern int lvm_create(struct lxc_storage *bdev, const char *dest, const char *n, 31 | struct bdev_specs *specs, const struct lxc_conf *conf); 32 | __hidden extern bool lvm_create_clone(struct lxc_conf *conf, struct lxc_storage *orig, 33 | struct lxc_storage *new, uint64_t newsize); 34 | __hidden extern bool lvm_create_snapshot(struct lxc_conf *conf, struct lxc_storage *orig, 35 | struct lxc_storage *new, uint64_t newsize); 36 | 37 | #endif /* __LXC_LVM_H */ 38 | -------------------------------------------------------------------------------- /src/tests/lxc-test-checkpoint-restore: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | 5 | # Do an end to end checkpoint and restore with criu. 6 | 7 | set -e 8 | 9 | FAIL() { 10 | echo -n "Failed " >&2 11 | echo "$*" >&2 12 | exit 1 13 | } 14 | 15 | cleanup() { 16 | set +e 17 | lxc-stop -n $name -k 18 | lxc-destroy -f -n $name 19 | } 20 | 21 | if [ "$(id -u)" != "0" ]; then 22 | echo "ERROR: Must run as root." 23 | exit 1 24 | fi 25 | 26 | verlte() { 27 | ! [ "$1" = "$(printf "$1\n$2" | sort -V | tail -n1)" ] 28 | } 29 | 30 | criu_version="$(criu --version | head -n1 | cut -d' ' -f 2)" 31 | 32 | if verlte "$criu_version" "1.3.1"; then 33 | echo "SKIP: skipping test because no (or wrong) criu installed." 34 | exit 0 35 | fi 36 | 37 | name=lxc-test-criu 38 | trap cleanup EXIT HUP INT TERM 39 | lxc-create -t busybox -n $name || FAIL "creating container" 40 | 41 | cat >> "$(lxc-config lxc.lxcpath)/$name/config" < /etc/lxc/default.conf << EOF 27 | lxc.net.0.type = veth 28 | lxc.net.0.link = lxcbr0 29 | EOF 30 | fi 31 | 32 | lxc-create -t busybox -n c1 33 | echo "lxc.no_new_privs = 1" >> /var/lib/lxc/c1/config 34 | 35 | lxc-start -n c1 36 | p1=$(lxc-info -n c1 -p -H) 37 | [ "$p1" != "-1" ] || { echo "Failed to start container c1"; false; } 38 | 39 | lxc-attach -n c1 --clear-env -- mkdir -p /home/ubuntu 40 | lxc-attach -n c1 --clear-env -- /bin/sh -c "cat <> /etc/passwd 41 | ubuntu:x:1000:1000:ubuntu:/home/ubuntu:/bin/sh 42 | EOF" 43 | 44 | # Check that lxc-attach obeys PR_SET_NO_NEW_PRIVS when it is set. 45 | ! lxc-attach -n c1 --clear-env --uid 1000 --gid 1000 -- ping -c 1 127.0.0.1 || { echo "Managed to ping localhost"; false; } 46 | lxc-stop -n c1 -k 47 | 48 | # Check that lxc-attach obeys PR_SET_NO_NEW_PRIVS when it is not set. 49 | sed -i 's/lxc.no_new_privs = 1/lxc.no_new_privs = 0/' /var/lib/lxc/c1/config 50 | lxc-start -n c1 51 | lxc-attach -n c1 --clear-env --uid 1000 --gid 1000 -- ping -c 1 127.0.0.1 || { echo "Managed to ping localhost"; false; } 52 | lxc-stop -n c1 -k 53 | 54 | DONE=1 55 | -------------------------------------------------------------------------------- /src/lxc/sync.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_SYNC_H 4 | #define __LXC_SYNC_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | 10 | #include "compiler.h" 11 | 12 | struct lxc_handler; 13 | 14 | enum /* generic */ { 15 | SYNC_ERROR = -1 /* Used to report errors from another process */ 16 | }; 17 | 18 | enum /* start */ { 19 | START_SYNC_STARTUP = 0, 20 | START_SYNC_CONFIGURE = 1, 21 | START_SYNC_POST_CONFIGURE = 2, 22 | START_SYNC_IDMAPPED_MOUNTS = 3, 23 | START_SYNC_CGROUP_LIMITS = 4, 24 | START_SYNC_FDS = 5, 25 | START_SYNC_READY_START = 6, 26 | START_SYNC_RESTART = 7, 27 | START_SYNC_POST_RESTART = 8, 28 | }; 29 | 30 | enum /* attach */ { 31 | ATTACH_SYNC_CGROUP = 0, 32 | }; 33 | 34 | __hidden extern bool lxc_sync_init(struct lxc_handler *handler); 35 | __hidden extern void lxc_sync_fini(struct lxc_handler *); 36 | __hidden extern void lxc_sync_fini_parent(struct lxc_handler *); 37 | __hidden extern void lxc_sync_fini_child(struct lxc_handler *); 38 | __hidden extern bool lxc_sync_wake_child(struct lxc_handler *, int); 39 | __hidden extern bool lxc_sync_wait_child(struct lxc_handler *, int); 40 | __hidden extern bool lxc_sync_wake_parent(struct lxc_handler *, int); 41 | __hidden extern bool lxc_sync_wait_parent(struct lxc_handler *, int); 42 | __hidden extern bool lxc_sync_barrier_parent(struct lxc_handler *, int); 43 | __hidden extern bool lxc_sync_barrier_child(struct lxc_handler *, int); 44 | __hidden extern bool sync_wait(int fd, int sequence); 45 | __hidden extern bool sync_wake(int fd, int sequence); 46 | 47 | #endif /* __LXC_SYNC_H */ 48 | -------------------------------------------------------------------------------- /config/init/sysvinit/lxc-containers.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # lxc Start/Stop LXC autoboot containers 4 | # 5 | # chkconfig: 345 99 01 6 | # description: Starts/Stops all LXC containers configured for autostart. 7 | # 8 | ### BEGIN INIT INFO 9 | # Provides: lxc 10 | # Required-Start: $syslog $remote_fs 11 | # Required-Stop: $syslog $remote_fs 12 | # Should-Start: cgroupfs-mount 13 | # Should-Stop: cgroupfs-mount 14 | # Default-Start: 2 3 4 5 15 | # Default-Stop: 0 1 6 16 | # Short-Description: Bring up/down LXC autostart containers 17 | # Description: Bring up/down LXC autostart containers 18 | ### END INIT INFO 19 | 20 | # To be replaced by LSB functions, if they can be found 21 | # Defined here for distributions that don't have log_daemon_msg 22 | log_daemon_msg () { 23 | echo $@ 24 | } 25 | 26 | # Try to source LSB init functions to define LSB log_* functions. 27 | test ! -r /lib/lsb/init-functions || 28 | . /lib/lsb/init-functions 29 | 30 | start() { 31 | # Setup host /dev for autodev containers. 32 | log_daemon_msg "Starting LXC autoboot containers: " 33 | @LIBEXECDIR@/lxc/lxc-containers start 34 | } 35 | 36 | stop() { 37 | log_daemon_msg "Stopping LXC containers: " 38 | @LIBEXECDIR@/lxc/lxc-containers stop 39 | } 40 | 41 | # See how we were called. 42 | case "$1" in 43 | start) 44 | start 45 | ;; 46 | 47 | stop) 48 | stop 49 | ;; 50 | 51 | restart|reload|force-reload) 52 | $0 stop 53 | $0 start 54 | ;; 55 | 56 | *) 57 | echo "Usage: $0 {start|stop|restart|reload|force-reload}" 58 | exit 2 59 | ;; 60 | esac 61 | 62 | exit $? 63 | -------------------------------------------------------------------------------- /src/include/bpf_common.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | #ifndef _UAPI__LINUX_BPF_COMMON_H__ 3 | #define _UAPI__LINUX_BPF_COMMON_H__ 4 | 5 | /* Instruction classes */ 6 | #define BPF_CLASS(code) ((code) & 0x07) 7 | #define BPF_LD 0x00 8 | #define BPF_LDX 0x01 9 | #define BPF_ST 0x02 10 | #define BPF_STX 0x03 11 | #define BPF_ALU 0x04 12 | #define BPF_JMP 0x05 13 | #define BPF_RET 0x06 14 | #define BPF_MISC 0x07 15 | 16 | /* ld/ldx fields */ 17 | #define BPF_SIZE(code) ((code) & 0x18) 18 | #define BPF_W 0x00 /* 32-bit */ 19 | #define BPF_H 0x08 /* 16-bit */ 20 | #define BPF_B 0x10 /* 8-bit */ 21 | /* eBPF BPF_DW 0x18 64-bit */ 22 | #define BPF_MODE(code) ((code) & 0xe0) 23 | #define BPF_IMM 0x00 24 | #define BPF_ABS 0x20 25 | #define BPF_IND 0x40 26 | #define BPF_MEM 0x60 27 | #define BPF_LEN 0x80 28 | #define BPF_MSH 0xa0 29 | 30 | /* alu/jmp fields */ 31 | #define BPF_OP(code) ((code) & 0xf0) 32 | #define BPF_ADD 0x00 33 | #define BPF_SUB 0x10 34 | #define BPF_MUL 0x20 35 | #define BPF_DIV 0x30 36 | #define BPF_OR 0x40 37 | #define BPF_AND 0x50 38 | #define BPF_LSH 0x60 39 | #define BPF_RSH 0x70 40 | #define BPF_NEG 0x80 41 | #define BPF_MOD 0x90 42 | #define BPF_XOR 0xa0 43 | 44 | #define BPF_JA 0x00 45 | #define BPF_JEQ 0x10 46 | #define BPF_JGT 0x20 47 | #define BPF_JGE 0x30 48 | #define BPF_JSET 0x40 49 | #define BPF_SRC(code) ((code) & 0x08) 50 | #define BPF_K 0x00 51 | #define BPF_X 0x08 52 | 53 | #ifndef BPF_MAXINSNS 54 | #define BPF_MAXINSNS 4096 55 | #endif 56 | 57 | #endif /* _UAPI__LINUX_BPF_COMMON_H__ */ 58 | -------------------------------------------------------------------------------- /src/lxc/rtnl.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "nl.h" 15 | #include "rtnl.h" 16 | 17 | int rtnetlink_open(struct rtnl_handler *handler) 18 | { 19 | return netlink_open(&handler->nlh, NETLINK_ROUTE); 20 | } 21 | 22 | void rtnetlink_close(struct rtnl_handler *handler) 23 | { 24 | netlink_close(&handler->nlh); 25 | } 26 | 27 | #pragma GCC diagnostic push 28 | #pragma GCC diagnostic ignored "-Wcast-align" 29 | 30 | int rtnetlink_rcv(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg) 31 | { 32 | return netlink_rcv(&handler->nlh, (struct nlmsg *)&rtnlmsg->nlmsghdr); 33 | } 34 | 35 | int rtnetlink_send(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg) 36 | { 37 | 38 | return netlink_send(&handler->nlh, (struct nlmsg *)&rtnlmsg->nlmsghdr); 39 | } 40 | 41 | int rtnetlink_transaction(struct rtnl_handler *handler, struct rtnlmsg *request, 42 | struct rtnlmsg *answer) 43 | { 44 | return netlink_transaction(&handler->nlh, 45 | (struct nlmsg *)&request->nlmsghdr, 46 | (struct nlmsg *)&answer->nlmsghdr); 47 | } 48 | 49 | #pragma GCC diagnostic pop 50 | 51 | struct rtnlmsg *rtnlmsg_alloc(size_t size) 52 | { 53 | /* 54 | size_t len; 55 | 56 | len = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct rtnlmsghdr))) + size; 57 | return (struct rtnlmsg *)nlmsg_alloc(len); 58 | */ 59 | 60 | return NULL; 61 | } 62 | 63 | void rtnlmsg_free(struct rtnlmsg *rtnlmsg) { free(rtnlmsg); } 64 | -------------------------------------------------------------------------------- /src/lxc/api_extensions.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_API_EXTENSIONS_H 4 | #define __LXC_API_EXTENSIONS_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | /* 12 | * api_extensions is the list of all API extensions in the order they were 13 | * added. 14 | 15 | The following kind of changes come with a new extensions: 16 | 17 | - New public functions 18 | - New configuration key 19 | - New valid values for a configuration key 20 | */ 21 | static char *api_extensions[] = { 22 | "lxc_log", 23 | "lxc_config_item_is_supported", 24 | "console_log", 25 | "reboot2", 26 | "mount_injection", 27 | "cgroup_relative", 28 | "mount_injection_file", 29 | "seccomp_allow_nesting", 30 | #ifdef HAVE_DECL_SECCOMP_NOTIFY_FD 31 | "seccomp_notify", 32 | #endif /* HAVE_DECL_SECCOMP_NOTIFY_FD */ 33 | "network_veth_routes", 34 | "network_ipvlan", 35 | "network_l2proxy", 36 | "network_gateway_device_route", 37 | "network_phys_macvlan_mtu", 38 | "network_veth_router", 39 | "cgroup2_devices", 40 | "cgroup2", 41 | "pidfd", 42 | "cgroup_advanced_isolation", 43 | "network_bridge_vlan", 44 | "time_namespace", 45 | "seccomp_allow_deny_syntax", 46 | "devpts_fd", 47 | #ifdef HAVE_DECL_SECCOMP_NOTIFY_FD 48 | "seccomp_notify_fd_active", 49 | "seccomp_proxy_send_notify_fd", 50 | #endif /* HAVE_DECL_SECCOMP_NOTIFY_FD */ 51 | "idmapped_mounts", 52 | "idmapped_mounts_v2", 53 | "core_scheduling", 54 | "cgroup2_auto_mounting", 55 | "environment_runtime_hooks", 56 | }; 57 | 58 | static size_t nr_api_extensions = sizeof(api_extensions) / sizeof(*api_extensions); 59 | 60 | #endif /* __LXC_API_EXTENSIONS_H */ 61 | -------------------------------------------------------------------------------- /src/tests/fuzz-lxc-define-load.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: LGPL-2.1+ 3 | */ 4 | 5 | #include "config.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "conf.h" 11 | #include "confile.h" 12 | #include "lxctest.h" 13 | #include "utils.h" 14 | 15 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 16 | __do_free char *new_str = NULL; 17 | struct lxc_container *c = NULL; 18 | struct lxc_list defines; 19 | struct lxc_list *it; 20 | __do_close int devnull_fd = -EBADF; 21 | 22 | if (size > 102400) 23 | return 0; 24 | 25 | c = lxc_container_new("FUZZ", NULL); 26 | lxc_test_assert_abort(c); 27 | 28 | new_str = (char *)malloc(size+1); 29 | lxc_test_assert_abort(new_str); 30 | memcpy(new_str, data, size); 31 | new_str[size] = '\0'; 32 | 33 | lxc_list_init(&defines); 34 | 35 | if (lxc_config_define_add(&defines, new_str) < 0) 36 | goto out; 37 | 38 | if (!lxc_config_define_load(&defines, c)) 39 | goto out; 40 | 41 | devnull_fd = open_devnull(); 42 | lxc_test_assert_abort(devnull_fd >= 0); 43 | 44 | lxc_list_for_each(it, &defines) { 45 | __do_free char *val = NULL; 46 | struct new_config_item *config_item = it->elem; 47 | int len; 48 | 49 | len = c->get_config_item(c, config_item->key, NULL, 0); 50 | if (len < 0) 51 | continue; 52 | 53 | val = (char *)malloc(len + 1); 54 | lxc_test_assert_abort(val); 55 | 56 | if (c->get_config_item(c, config_item->key, val, len + 1) != len) 57 | continue; 58 | 59 | if (len > 0) 60 | dprintf(devnull_fd, "[%s/%s]\n", config_item->key, val); 61 | } 62 | 63 | out: 64 | lxc_container_put(c); 65 | lxc_config_define_free(&defines); 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /src/tests/lxc-test-snapdeps: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | 5 | # lxc: linux Container library 6 | # 7 | # This is a test for dependency between snapshots 8 | # 9 | # When container c2 is created as an overlayfs clone of c1, then 10 | # we record it as such, because c1 cannot be deleted until c2 is 11 | # deleted. Once c2 is deleted, c1 should be delete-able. 12 | 13 | # This test assumes an Ubuntu host 14 | 15 | set -e 16 | 17 | modprobe -v overlay || true 18 | if ! grep -q overlay /proc/filesystems; then 19 | echo "Not running this test as overlay is not available" 20 | exit 0 21 | fi 22 | 23 | cleanup() { 24 | for i in $(seq 1 20); do 25 | lxc-destroy -n snapdeptest$i > /dev/null 2>&1 || true 26 | done 27 | lxc-destroy -n snapdeptest > /dev/null 2>&1 || true 28 | } 29 | 30 | verify_deps() { 31 | n=$1 32 | m=$(wc -l /var/lib/lxc/snapdeptest/lxc_snapshots | awk '{ print $1 }') 33 | [ $((n*2)) -eq $m ] 34 | } 35 | 36 | cleanup 37 | 38 | trap cleanup EXIT SIGHUP SIGINT SIGTERM 39 | 40 | lxc-create -t busybox -n snapdeptest 41 | lxc-copy -s -n snapdeptest -N snapdeptest1 42 | fail=0 43 | lxc-destroy -n snapdeptest || fail=1 44 | if [ $fail -eq 0 ]; then 45 | echo "FAIL: clone did not prevent deletion" 46 | false 47 | fi 48 | 49 | for i in $(seq 2 20); do 50 | lxc-copy -s -n snapdeptest -N snapdeptest$i 51 | done 52 | 53 | verify_deps 20 54 | 55 | lxc-destroy -n snapdeptest1 56 | 57 | verify_deps 19 58 | 59 | lxc-destroy -n snapdeptest20 60 | 61 | verify_deps 18 62 | 63 | for i in $(seq 2 19); do 64 | lxc-destroy -n snapdeptest$i 65 | done 66 | 67 | lxc-destroy -n snapdeptest 68 | 69 | echo "Snapshot clone dependency test passed" 70 | exit 0 71 | -------------------------------------------------------------------------------- /src/tests/lxctest.h: -------------------------------------------------------------------------------- 1 | /* lxc: linux Container library 2 | * 3 | * SPDX-License-Identifier: LGPL-2.1+ 4 | * 5 | */ 6 | 7 | #ifndef __LXC_TEST_H_ 8 | #define __LXC_TEST_H_ 9 | 10 | #include "config.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define lxc_debug_stream(stream, format, ...) \ 17 | do { \ 18 | fprintf(stream, "%s: %d: %s: " format "\n", __FILE__, \ 19 | __LINE__, __func__, ##__VA_ARGS__); \ 20 | } while (false) 21 | 22 | #define lxc_error(format, ...) lxc_debug_stream(stderr, format, ##__VA_ARGS__) 23 | #define lxc_debug(format, ...) lxc_debug_stream(stdout, format, ##__VA_ARGS__) 24 | 25 | #define lxc_test_assert_stringify(expression, stringify_expression) \ 26 | do { \ 27 | if (!(expression)) { \ 28 | fprintf(stderr, "%s: %s: %d: %s\n", __FILE__, \ 29 | __func__, __LINE__, stringify_expression); \ 30 | abort(); \ 31 | } \ 32 | } while (false) 33 | 34 | #define lxc_test_assert_abort(expression) lxc_test_assert_stringify(expression, #expression) 35 | 36 | #define test_error_ret(__ret__, format, ...) \ 37 | ({ \ 38 | typeof(__ret__) __internal_ret__ = (__ret__); \ 39 | fprintf(stderr, format, ##__VA_ARGS__); \ 40 | __internal_ret__; \ 41 | }) 42 | 43 | #endif /* __LXC_TEST_H */ 44 | -------------------------------------------------------------------------------- /src/include/netns_ifaddrs.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef _LXC_NETNS_IFADDRS_H 4 | #define _LXC_NETNS_IFADDRS_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "../lxc/compiler.h" 18 | #include "../lxc/memory_utils.h" 19 | 20 | struct netns_ifaddrs { 21 | struct netns_ifaddrs *ifa_next; 22 | 23 | /* Can - but shouldn't be - NULL. */ 24 | char *ifa_name; 25 | 26 | /* This field is not present struct ifaddrs. */ 27 | int ifa_ifindex; 28 | 29 | unsigned ifa_flags; 30 | 31 | /* This field is not present struct ifaddrs. */ 32 | int ifa_mtu; 33 | 34 | /* This field is not present struct ifaddrs. */ 35 | int ifa_prefixlen; 36 | 37 | struct sockaddr *ifa_addr; 38 | struct sockaddr *ifa_netmask; 39 | union { 40 | struct sockaddr *ifu_broadaddr; 41 | struct sockaddr *ifu_dstaddr; 42 | } ifa_ifu; 43 | 44 | /* These fields are not present struct ifaddrs. */ 45 | int ifa_stats_type; 46 | #if HAVE_STRUCT_RTNL_LINK_STATS64 47 | struct rtnl_link_stats64 ifa_stats; 48 | #else 49 | struct rtnl_link_stats ifa_stats; 50 | #endif 51 | }; 52 | 53 | #define __ifa_broadaddr ifa_ifu.ifu_broadaddr 54 | #define __ifa_dstaddr ifa_ifu.ifu_dstaddr 55 | 56 | __hidden extern void netns_freeifaddrs(struct netns_ifaddrs *); 57 | define_cleanup_function(struct netns_ifaddrs *, netns_freeifaddrs); 58 | __hidden extern int netns_getifaddrs(struct netns_ifaddrs **ifap, __s32 netns_id, 59 | bool *netnsid_aware); 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | 65 | #endif /* _LXC_NETNS_IFADDRS_H */ 66 | -------------------------------------------------------------------------------- /src/tests/lxc-test-apparmor-generated: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | 5 | # lxc: linux Container library 6 | 7 | # This is a test script for generated apparmor profiles 8 | 9 | if ! command -v apparmor_parser >/dev/null 2>&1; then 10 | echo 'SKIP: test for generated apparmor profiles: apparmor_parser missing' 11 | exit 0 12 | fi 13 | 14 | DONE=0 15 | LOGFILE="/tmp/lxc-test-$$.log" 16 | cleanup() { 17 | lxc-destroy -n $CONTAINER_NAME >/dev/null 2>&1 || true 18 | 19 | if [ $DONE -eq 0 ]; then 20 | [ -f "$LOGFILE" ] && cat "$LOGFILE" >&2 21 | rm -f "$LOGFILE" 22 | echo "FAIL" 23 | exit 1 24 | fi 25 | rm -f "$LOGFILE" 26 | echo "PASS" 27 | } 28 | 29 | trap cleanup EXIT HUP INT TERM 30 | set -eu 31 | 32 | # Create a container 33 | CONTAINER_NAME=lxc-test-apparmor-generated 34 | 35 | lxc-create -t busybox -n $CONTAINER_NAME -B dir 36 | CONTAINER_PATH=$(dirname $(lxc-info -n $CONTAINER_NAME -c lxc.rootfs.path -H) | sed -e 's/dir://') 37 | cp $CONTAINER_PATH/config $CONTAINER_PATH/config.bak 38 | 39 | # Set the profile to be auto-generated 40 | echo "lxc.apparmor.profile = generated" >> $CONTAINER_PATH/config 41 | 42 | # Start it 43 | lxc-start -n $CONTAINER_NAME -lDEBUG -o "$LOGFILE" 44 | lxc-wait -n $CONTAINER_NAME -t 5 -s RUNNING || (echo "Container didn't start" && exit 1) 45 | pid=$(lxc-info -p -H -n $CONTAINER_NAME) 46 | profile=$(cat /proc/$pid/attr/current) 47 | expected_profile="lxc-${CONTAINER_NAME}_//&:lxc-${CONTAINER_NAME}_<-var-lib-lxc>:unconfined (enforce)" 48 | lxc-stop -n $CONTAINER_NAME -k 49 | if [ "x$profile" != "x$expected_profile" ]; then 50 | echo "FAIL: container was in profile $profile" >&2 51 | echo "expected profile: $expected_profile" >&2 52 | exit 1 53 | fi 54 | 55 | DONE=1 56 | -------------------------------------------------------------------------------- /src/lxc/storage/storage_utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_STORAGE_UTILS_H 4 | #define __LXC_STORAGE_UTILS_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "compiler.h" 14 | #include "conf.h" 15 | #include "macro.h" 16 | 17 | #define LXC_OVERLAY_PRIVATE_DIR "overlay" 18 | #define LXC_OVERLAY_DELTA_DIR "delta" 19 | #define LXC_OVERLAY_WORK_DIR "work" 20 | #define LXC_OVERLAY_DELTA_PATH LXC_OVERLAY_PRIVATE_DIR "/" LXC_OVERLAY_DELTA_DIR 21 | #define LXC_OVERLAY_WORK_PATH LXC_OVERLAY_PRIVATE_DIR "/" LXC_OVERLAY_WORK_DIR 22 | #define LXC_OVERLAY_PATH_LEN \ 23 | (STRLITERALLEN(LXC_OVERLAY_PRIVATE_DIR) + STRLITERALLEN("/") + 256 + 1) 24 | 25 | struct lxc_storage; 26 | struct lxc_conf; 27 | 28 | __hidden extern bool attach_block_device(struct lxc_conf *conf); 29 | __hidden extern void detach_block_device(struct lxc_conf *conf); 30 | __hidden extern int blk_getsize(struct lxc_storage *bdev, uint64_t *size); 31 | __hidden extern int detect_fs(struct lxc_storage *bdev, char *type, int len); 32 | __hidden extern int do_mkfs_exec_wrapper(void *args); 33 | __hidden extern int is_blktype(struct lxc_storage *b); 34 | __hidden extern int mount_unknown_fs(const char *rootfs, const char *target, const char *options); 35 | __hidden extern int find_fstype_cb(char *buffer, void *data); 36 | __hidden extern const char *linkderef(const char *path, char *dest); 37 | __hidden extern bool unpriv_snap_allowed(struct lxc_storage *b, const char *t, bool snap, 38 | bool maybesnap); 39 | extern bool lxc_is_valid_storage_type(const char *type); 40 | __hidden extern int storage_destroy_wrapper(void *data); 41 | 42 | #endif /* __LXC_STORAGE_UTILS_H */ 43 | -------------------------------------------------------------------------------- /src/lxc/tools/include/getsubopt.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | 4 | #include 5 | #include 6 | 7 | #include "config.h" 8 | 9 | #if !HAVE_STRCHRNUL 10 | #include "strchrnul.h" 11 | #endif 12 | 13 | /* Parse comma separated suboption from *OPTIONP and match against 14 | strings in TOKENS. If found return index and set *VALUEP to 15 | optional value introduced by an equal sign. If the suboption is 16 | not part of TOKENS return in *VALUEP beginning of unknown 17 | suboption. On exit *OPTIONP is set to the beginning of the next 18 | token or at the terminating NUL character. */ 19 | int 20 | getsubopt (char **optionp, char *const *tokens, char **valuep) 21 | { 22 | char *endp, *vstart; 23 | int cnt; 24 | 25 | if (**optionp == '\0') 26 | return -1; 27 | 28 | /* Find end of next token. */ 29 | endp = strchrnul (*optionp, ','); 30 | 31 | /* Find start of value. */ 32 | vstart = memchr (*optionp, '=', endp - *optionp); 33 | if (vstart == NULL) 34 | vstart = endp; 35 | 36 | /* Try to match the characters between *OPTIONP and VSTART against 37 | one of the TOKENS. */ 38 | for (cnt = 0; tokens[cnt] != NULL; ++cnt) 39 | if (strncmp (*optionp, tokens[cnt], vstart - *optionp) == 0 40 | && tokens[cnt][vstart - *optionp] == '\0') 41 | { 42 | /* We found the current option in TOKENS. */ 43 | *valuep = vstart != endp ? vstart + 1 : NULL; 44 | 45 | if (*endp != '\0') 46 | *endp++ = '\0'; 47 | *optionp = endp; 48 | 49 | return cnt; 50 | } 51 | 52 | /* The current suboption does not match any option. */ 53 | *valuep = *optionp; 54 | 55 | if (*endp != '\0') 56 | *endp++ = '\0'; 57 | *optionp = endp; 58 | 59 | return -1; 60 | } 61 | -------------------------------------------------------------------------------- /src/tests/arch_parse.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "lxc/lxccontainer.h" 18 | 19 | #include "lxctest.h" 20 | #include "../lxc/lxc.h" 21 | #include "../lxc/memory_utils.h" 22 | 23 | #if !HAVE_STRLCPY 24 | #include "strlcpy.h" 25 | #endif 26 | 27 | static const char *const arches[] = { 28 | "arm", "armel", "armhf", "armv7l", "athlon", "i386", "i486", 29 | "i586", "i686", "linux32", "mips", "mipsel", "ppc", "powerpc", 30 | "x86", "aarch64", "amd64", "arm64", "linux64", "loongarch64", "loong64", 31 | "mips64", "mips64el", "ppc64", "ppc64el", "ppc64le", "powerpc64", "riscv64", 32 | "s390x", "x86_64", 33 | }; 34 | 35 | static bool parse_valid_architectures(void) 36 | { 37 | __put_lxc_container struct lxc_container *c = NULL; 38 | 39 | c = lxc_container_new("parse-arch", NULL); 40 | if (!c) 41 | return test_error_ret(false, "Failed to create container \"parse_arch\""); 42 | 43 | for (size_t i = 0; i < ARRAY_SIZE(arches); i++) { 44 | const char *arch = arches[i]; 45 | 46 | if (!c->set_config_item(c, "lxc.arch", arch)) 47 | return test_error_ret(false, "Failed to set \"lxc.arch=%s\"", arch); 48 | 49 | if (!c->clear_config_item(c, "lxc.arch")) 50 | return test_error_ret(false, "Failed to clear \"lxc.arch=%s\"", arch); 51 | } 52 | 53 | return true; 54 | } 55 | 56 | int main(int argc, char *argv[]) 57 | { 58 | if (!parse_valid_architectures()) 59 | exit(EXIT_FAILURE); 60 | 61 | exit(EXIT_SUCCESS); 62 | } 63 | -------------------------------------------------------------------------------- /doc/lxc-checkconfig.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | ]> 7 | 8 | 9 | 10 | @LXC_GENERATE_DATE@ 11 | 12 | 13 | lxc-checkconfig 14 | 1 15 | 16 | 17 | 18 | lxc-checkconfig 19 | 20 | 21 | check the current kernel for lxc support 22 | 23 | 24 | 25 | 26 | 27 | lxc-checkconfig 28 | 29 | 30 | 31 | 32 | Description 33 | 34 | lxc-checkconfig check the current kernel for 35 | lxc support 36 | 37 | 38 | 39 | 40 | Examples 41 | 42 | 43 | lxc-checkconfig 44 | 45 | 46 | check the current kernel. 47 | CONFIG can be set in the environment to an alternate location. 48 | 49 | 50 | 51 | 52 | 53 | 54 | &seealso; 55 | 56 | 57 | 73 | -------------------------------------------------------------------------------- /src/tests/lxc-test-rootfs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | 5 | # lxc: linux Container library 6 | 7 | set -ex 8 | 9 | cleanup() { 10 | set +e 11 | lxc-destroy -n lxc-test-rootfs -f 12 | sed -i '/^root:910000:10000/d' /etc/subuid /etc/subgid 13 | if [ $PHASE != "done" ]; then 14 | echo "rootfs test failed at $PHASE" 15 | exit 1 16 | fi 17 | echo "rootfs test passed" 18 | exit 0 19 | } 20 | 21 | PHASE=setup 22 | trap cleanup EXIT 23 | 24 | lxc-destroy -n lxc-test-rootfs -f || true 25 | lxc-create -t busybox -n lxc-test-rootfs 26 | 27 | PHASE=ro_rootfs 28 | echo "Starting phase $PHASE" 29 | config=/var/lib/lxc/lxc-test-rootfs/config 30 | sed -i '/lxc.rootfs.options/d' $config 31 | echo "lxc.rootfs.options = ro" >> $config 32 | 33 | lxc-start -n lxc-test-rootfs 34 | pid=$(lxc-info -n lxc-test-rootfs -p -H) 35 | ro=0 36 | mkdir /proc/$pid/root/rotest || ro=1 37 | [ $ro -ne 0 ] 38 | 39 | lxc-stop -n lxc-test-rootfs -k 40 | PHASE=rw_rootfs 41 | echo "Starting phase $PHASE" 42 | sed -i '/lxc.rootfs.options/d' $config 43 | echo "lxc.rootfs.options = rw" >> $config 44 | lxc-start -n lxc-test-rootfs 45 | pid=$(lxc-info -n lxc-test-rootfs -p -H) 46 | ro=0 47 | mkdir /proc/$pid/root/rwtest || ro=1 48 | [ $ro -ne 1 ] 49 | rmdir /proc/$pid/root/rwtest 50 | ro=0 51 | 52 | lxc-stop -n lxc-test-rootfs -k 53 | PHASE=idmapped_rootfs 54 | echo "Starting phase $PHASE" 55 | usermod -v 910000-919999 -w 910000-919999 root 56 | sed -i '/lxc.rootfs.options/d' $config 57 | echo "lxc.idmap = u 0 910000 9999" >> $config 58 | echo "lxc.idmap = g 0 910000 9999" >> $config 59 | echo "lxc.rootfs.options = idmap=container" >> $config 60 | lxc-start -n lxc-test-rootfs 61 | pid=$(lxc-info -n lxc-test-rootfs -p -H) 62 | ro=0 63 | lxc-attach -n lxc-test-rootfs -- mkdir /rwtest || ro=1 64 | [ $ro -ne 1 ] 65 | rmdir /proc/$pid/root/rwtest 66 | ro=0 67 | 68 | PHASE=done 69 | -------------------------------------------------------------------------------- /src/lxc/tools/lxc_config.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | 8 | #include "lxc.h" 9 | 10 | struct lxc_config_items { 11 | char *name; 12 | }; 13 | 14 | static struct lxc_config_items items[] = 15 | { 16 | { .name = "lxc.default_config", }, 17 | { .name = "lxc.lxcpath", }, 18 | { .name = "lxc.bdev.lvm.vg", }, 19 | { .name = "lxc.bdev.lvm.thin_pool", }, 20 | { .name = "lxc.bdev.zfs.root", }, 21 | { .name = "lxc.cgroup.use", }, 22 | { .name = "lxc.cgroup.pattern", }, 23 | { .name = NULL, }, 24 | }; 25 | 26 | static void usage(char *me) 27 | { 28 | printf("Usage: %s -l: list all available configuration items\n", me); 29 | printf(" %s item: print configuration item\n", me); 30 | exit(EXIT_SUCCESS); 31 | } 32 | 33 | static void list_config_items(void) 34 | { 35 | struct lxc_config_items *i; 36 | 37 | for (i = &items[0]; i->name; i++) 38 | printf("%s\n", i->name); 39 | 40 | exit(EXIT_SUCCESS); 41 | } 42 | 43 | int __attribute__((weak, alias("lxc_config_main"))) main(int argc, char *argv[]); 44 | int lxc_config_main(int argc, char *argv[]) 45 | { 46 | struct lxc_config_items *i; 47 | const char *value; 48 | 49 | if (argc < 2 || strncmp(argv[1], "-h", strlen(argv[1])) == 0 || 50 | strncmp(argv[1], "--help", strlen(argv[1])) == 0) 51 | usage(argv[0]); 52 | 53 | if (strncmp(argv[1], "-l", strlen(argv[1])) == 0) 54 | list_config_items(); 55 | 56 | for (i = &items[0]; i->name; i++) { 57 | if (strncmp(argv[1], i->name, strlen(argv[1])) == 0) { 58 | value = lxc_get_global_config_item(i->name); 59 | if (value) 60 | printf("%s\n", value); 61 | else 62 | printf("%s is not set.\n", argv[1]); 63 | 64 | exit(EXIT_SUCCESS); 65 | } 66 | } 67 | 68 | printf("Unknown configuration item: %s\n", argv[1]); 69 | exit(EXIT_FAILURE); 70 | } 71 | -------------------------------------------------------------------------------- /config/init/module/customize.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ui_print "- [I] Checking env..." 4 | 5 | if [ -n $KSU ]; then 6 | ui_print "- [D] Su manager is KernelSU." 7 | fi 8 | 9 | if [ $ARCH = "arm64" ]; then 10 | continue 11 | else 12 | abort "- [E] Unsupported arch: $ARCH." 13 | fi 14 | 15 | if [ $API -ge 30 ]; then 16 | continue 17 | else 18 | ui_print "- [W] Func memfd_create() required API 30(R)." 19 | fi 20 | 21 | ui_print "- [D] Fetching download link..." 22 | 23 | DOWNLOAD_URLS=$(curl -s https://api.github.com/repos/Container-On-Android/lxc/releases/latest | grep browser_download_url | cut -d'"' -f4 | grep -E 'gz$') 24 | 25 | URL_LXC=$(echo "$DOWNLOAD_URLS" | sed -n '1p') 26 | URL_SYSROOT=$(echo "$DOWNLOAD_URLS" | sed -n '2p') 27 | 28 | if [ -z $URL_LXC ] && [ -z $URL_SHARE ]; then 29 | abort "- [E] Error: URL_LXC: $URL_LXC URL_SHARE: $URL_SHARE." 30 | else 31 | ui_print "- [D] Fetch ok..." 32 | fi 33 | 34 | ui_print "- [I] Downloading lxc..." 35 | 36 | wget -q $URL_LXC -O /data/local/tmp/lxc.tar.gz 37 | 38 | if [ $? -eq 0 ]; then 39 | ui_print "- [I] Download lxc ok..." 40 | else 41 | rm /data/local/tmp/lxc.tar.gz 42 | abort "- [E] Failed to download lxc. ($URL_LXC)" 43 | fi 44 | 45 | ui_print "- [I] Downloading lxc-sysroot..." 46 | 47 | wget -q $URL_SYSROOT -O /data/local/tmp/lxc-sysroot.tar.gz 48 | 49 | if [ $? -eq 0 ]; then 50 | ui_print "- [D] Download lxc-sysroot ok..." 51 | else 52 | rm /data/local/tmp/lxc-sysroot.tar.gz 53 | abort "- [E] Failed to download lxc-sysroot. ($URL_SYSROOT)" 54 | fi 55 | 56 | ui_print "- [I] Installing lxc..." 57 | mkdir -p @PREFIXDIR@ 58 | mkdir -p /data/sysroot 59 | tar zxf /data/local/tmp/lxc.tar.gz -C @PREFIXDIR@ 60 | tar zxf /data/local/tmp/lxc-sysroot.tar.gz -C /data/sysroot 61 | ui_print "- [I] OK!" 62 | 63 | ui_print "- [I] Clean!" 64 | rm /data/local/tmp/lxc.tar.gz 65 | rm /data/local/tmp/lxc-sysroot.tar.gz -------------------------------------------------------------------------------- /src/tests/lxcpath.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "memory_utils.h" 21 | 22 | #define MYNAME "lxctest1" 23 | 24 | #define TSTERR(x) do { \ 25 | fprintf(stderr, "%d: %s\n", __LINE__, x); \ 26 | } while (0) 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | struct lxc_container *c; 31 | const char *p1; 32 | __do_free char *p2 = NULL; 33 | int retval = -1; 34 | 35 | c = lxc_container_new(MYNAME, NULL); 36 | if (!c) { 37 | TSTERR("create using default path"); 38 | goto err; 39 | } 40 | 41 | p1 = c->get_config_path(c); 42 | p2 = c->config_file_name(c); 43 | if (!p1 || !p2 || strncmp(p1, p2, strlen(p1))) { 44 | TSTERR("Bad result for path names"); 45 | goto err; 46 | } 47 | 48 | #define CPATH "/boo" 49 | #define FPATH "/boo/lxctest1/config" 50 | if (!c->set_config_path(c, "/boo")) { 51 | TSTERR("Error setting custom path"); 52 | goto err; 53 | } 54 | 55 | p1 = c->get_config_path(c); 56 | free(p2); 57 | p2 = c->config_file_name(c); 58 | if (strcmp(p1, CPATH) || strcmp(p2, FPATH)) { 59 | TSTERR("Bad result for path names after set_config_path()"); 60 | goto err; 61 | } 62 | lxc_container_put(c); 63 | 64 | c = lxc_container_new(MYNAME, CPATH); 65 | if (!c) { 66 | TSTERR("create using custom path"); 67 | goto err; 68 | } 69 | 70 | p1 = c->get_config_path(c); 71 | free(p2); 72 | p2 = c->config_file_name(c); 73 | if (strcmp(p1, CPATH) || strcmp(p2, FPATH)) { 74 | TSTERR("Bad result for path names after create with custom path"); 75 | goto err; 76 | } 77 | 78 | retval = 0; 79 | 80 | err: 81 | lxc_container_put(c); 82 | return retval; 83 | } 84 | -------------------------------------------------------------------------------- /src/tests/config_jump_table.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "confile.h" 23 | #include "state.h" 24 | #include "lxctest.h" 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | int fulllen = 0, inlen = 0, ret = EXIT_FAILURE; 29 | char *key, *keys, *saveptr = NULL; 30 | 31 | fulllen = lxc_list_config_items(NULL, inlen); 32 | 33 | keys = malloc(sizeof(char) * fulllen + 1); 34 | if (!keys) { 35 | lxc_error("%s\n", "failed to allocate memory"); 36 | exit(ret); 37 | } 38 | 39 | if (lxc_list_config_items(keys, fulllen) != fulllen) { 40 | lxc_error("%s\n", "failed to retrieve configuration keys"); 41 | goto on_error; 42 | } 43 | 44 | for (key = strtok_r(keys, "\n", &saveptr); key != NULL; 45 | key = strtok_r(NULL, "\n", &saveptr)) { 46 | struct lxc_config_t *config; 47 | 48 | config = lxc_get_config(key); 49 | if (!config) { 50 | lxc_error("configuration key \"%s\" not implemented in " 51 | "jump table", 52 | key); 53 | goto on_error; 54 | } 55 | 56 | if (!config->set) { 57 | lxc_error("configuration key \"%s\" has no set method " 58 | "in jump table", 59 | key); 60 | goto on_error; 61 | } 62 | 63 | if (!config->get) { 64 | lxc_error("configuration key \"%s\" has no get method " 65 | "in jump table", 66 | key); 67 | goto on_error; 68 | } 69 | 70 | if (!config->clr) { 71 | lxc_error("configuration key \"%s\" has no clr (clear) " 72 | "method in jump table", 73 | key); 74 | goto on_error; 75 | } 76 | } 77 | 78 | ret = EXIT_SUCCESS; 79 | 80 | on_error: 81 | free(keys); 82 | 83 | exit(ret); 84 | } 85 | -------------------------------------------------------------------------------- /src/lxc/lsm/nop.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | 7 | #include "lsm/lsm.h" 8 | 9 | static char *nop_process_label_get(struct lsm_ops *ops, pid_t pid) 10 | { 11 | return NULL; 12 | } 13 | 14 | static char *nop_process_label_get_at(struct lsm_ops *ops, int fd_pid) 15 | { 16 | return NULL; 17 | } 18 | 19 | static int nop_process_label_set(struct lsm_ops *ops, const char *label, struct lxc_conf *conf, 20 | bool on_exec) 21 | { 22 | return 0; 23 | } 24 | 25 | static int nop_enabled(struct lsm_ops *ops) 26 | { 27 | return 0; 28 | } 29 | 30 | static int nop_keyring_label_set(struct lsm_ops *ops, const char *label) 31 | { 32 | return 0; 33 | } 34 | 35 | static int nop_prepare(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) 36 | { 37 | return 0; 38 | } 39 | 40 | static void nop_cleanup(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) 41 | { 42 | } 43 | 44 | static int nop_process_label_fd_get(struct lsm_ops *ops, pid_t pid, bool on_exec) 45 | { 46 | return 0; 47 | } 48 | 49 | static int nop_process_label_set_at(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec) 50 | { 51 | return 0; 52 | } 53 | 54 | static struct lsm_ops nop_ops = { 55 | .name = "nop", 56 | .aa_admin = -1, 57 | .aa_can_stack = -1, 58 | .aa_enabled = -1, 59 | .aa_is_stacked = -1, 60 | .aa_mount_features_enabled = -1, 61 | .aa_parser_available = -1, 62 | .aa_supports_unix = -1, 63 | .cleanup = nop_cleanup, 64 | .enabled = nop_enabled, 65 | .keyring_label_set = nop_keyring_label_set, 66 | .prepare = nop_prepare, 67 | .process_label_fd_get = nop_process_label_fd_get, 68 | .process_label_get = nop_process_label_get, 69 | .process_label_set = nop_process_label_set, 70 | .process_label_get_at = nop_process_label_get_at, 71 | .process_label_set_at = nop_process_label_set_at, 72 | }; 73 | 74 | struct lsm_ops *lsm_nop_ops_init(void) 75 | { 76 | return &nop_ops; 77 | } 78 | -------------------------------------------------------------------------------- /config/apparmor/abstractions/start-container.in: -------------------------------------------------------------------------------- 1 | network, 2 | capability, 3 | file, 4 | 5 | # The following 3 entries are only supported by recent apparmor versions. 6 | # Comment them if the apparmor parser doesn't recognize them. 7 | dbus, 8 | signal, 9 | ptrace, 10 | 11 | # currently blocked by apparmor bug 12 | mount -> /usr/lib*/*/lxc/{**,}, 13 | mount -> /usr/lib*/lxc/{**,}, 14 | mount -> @LXCROOTFSMOUNT@/{,**}, 15 | mount fstype=devpts -> /dev/pts/, 16 | mount options=bind /dev/pts/ptmx/ -> /dev/ptmx/, 17 | mount options=bind /dev/pts/** -> /dev/**, 18 | mount options=(rw, make-slave) -> /{,**}, 19 | mount options=(rw, make-rslave) -> /{,**}, 20 | mount options=(rw, make-shared) -> /{,**}, 21 | mount options=(rw, make-rshared) -> /{,**}, 22 | mount fstype=debugfs, 23 | mount fstype=fuse.*, 24 | # allow pre-mount hooks to stage mounts under /var/lib/lxc// 25 | mount -> /var/lib/lxc/{**,}, 26 | 27 | mount /dev/.lxc-boot-id -> /proc/sys/kernel/random/boot_id, 28 | mount options=(ro, nosuid, nodev, noexec, remount, bind) -> /proc/sys/kernel/random/boot_id, 29 | 30 | # required for some pre-mount hooks 31 | mount fstype=overlayfs, 32 | mount fstype=aufs, 33 | mount fstype=ecryptfs, 34 | 35 | # all umounts are under the original root's /mnt, but right now we 36 | # can't allow those umounts after pivot_root. So allow all umounts 37 | # right now. They'll be restricted for the container at least. 38 | umount, 39 | #umount /mnt/{**,}, 40 | 41 | # This may look a bit redundant, however it appears we need all of 42 | # them if we want things to work properly on all combinations of kernel 43 | # and userspace parser... 44 | pivot_root /usr/lib*/lxc/, 45 | pivot_root /usr/lib*/*/lxc/, 46 | pivot_root /usr/lib*/lxc/**, 47 | pivot_root /usr/lib*/*/lxc/**, 48 | pivot_root @LXCROOTFSMOUNT@/{,**}, 49 | 50 | change_profile -> lxc-*, 51 | change_profile -> lxc-**, 52 | change_profile -> unconfined, 53 | change_profile -> :lxc-*:unconfined, 54 | -------------------------------------------------------------------------------- /hooks/mountecryptfsroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | # 5 | # This hook can be used to mount an ecryptfs filesystem as a container's 6 | # rootfs. 7 | # To use this hook, assuming your container is called q1, 8 | # 1. add 'lxc.hook.pre-mount = /usr/share/lxc/hooks/mountecryptfsroot' to 9 | # the container's configuration file 10 | # 2. Create /var/lib/lxc/q1/ecryptfs-root 11 | # a. mkdir /var/lib/lxc/q1/ecryptfs-root 12 | # 3. convert your container's root filesystem to be ecryptfs-backed. Assuming 13 | # your container is called 'q1', do 14 | # a. c=q1 15 | # b. mv /var/lib/lxc/$c/rootfs /var/lib/lxc/$c/rootfs.plain 16 | # c. mkdir /var/lib/lxc/$c/rootfs{,.crypt} 17 | # d. sig=$(echo none | ecryptfs-add-passphrase | grep -v Passphrase | cut -d[ -f 2 | cut -d] -f 1) 18 | # e. echo $sig > /var/lib/lxc/$c/sig 19 | # f. mount -t ecryptfs -o ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_passthrough=n,ecryptfs_enable_filename_crypto=n,ecryptfs_sig=${sig},sig=${sig},verbosity=0 /var/lib/lxc/$c/rootfs.crypt /var/lib/lxc/$c/rootfs 20 | # g. rsync -va /var/lib/lxc/$c/rootfs.plain/ /var/lib/lxc/$c/rootfs/ 21 | # h. umount /var/lib/lxc/$c/rootfs 22 | # i. rm -rf /var/lib/lxc/$c/rootfs.plain 23 | # 4. Now you can start your container by adding the passphrase to your 24 | # in-kernel keyring using 'ecryptfs-add-passphrase', then starting your 25 | # container as normal. 26 | # a. echo none | ecryptfs-add-passphrase 27 | # b. lxc-start -n q1 28 | # Note that you may well want to use a wrapped passphrase (see the ecryptfs-wrap-passphrase(1) manual page). 29 | 30 | set -e 31 | ecryptfs_crypt=$(echo $LXC_ROOTFS_PATH | sed 's/rootfs$/rootfs.crypt/') 32 | sigfile=$(echo $LXC_CONFIG_FILE | sed 's/config$/sig/') 33 | 34 | sig=$(cat $sigfile) 35 | mount -n -t ecryptfs -o ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_passthrough=n,ecryptfs_enable_filename_crypto=n,ecryptfs_sig=${sig},sig=${sig},verbosity=0 $ecryptfs_crypt $LXC_ROOTFS_PATH 36 | exit 0 37 | -------------------------------------------------------------------------------- /.github/workflows/code-test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: 3 | - pull_request 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | name: Build test 9 | steps: 10 | - uses: actions/checkout@v4 11 | 12 | - name: Set up Android NDK 13 | uses: nttld/setup-ndk@v1 14 | with: 15 | ndk-version: r27c 16 | 17 | - name: Install dependencies 18 | run: | 19 | sudo apt-get install -y -qq build-essential pipx python3-venv pkg-config cmake docbook2x \ 20 | python3-pip pipx 21 | pipx ensurepath 22 | pipx install meson==0.61 23 | pipx install ninja 24 | 25 | - name: Test build 26 | run: | 27 | sed -i "s|android-ndk-r27c|$ANDROID_NDK_HOME|g" aarch64-android-api30.txt 28 | 29 | meson setup build \ 30 | -Dprefix=/data/share \ 31 | -Dinit-script=module \ 32 | -Druntime-path=/data/share/tmp \ 33 | -Dstrip=true \ 34 | -Dd_lto=true \ 35 | -Db_pie=false \ 36 | -Dlog-path=log/lxc \ 37 | -Ddata-path=lib/lxc \ 38 | --localstatedir=/data/share/var \ 39 | -Dmemfd-rexec=true \ 40 | --buildtype debug \ 41 | -Dcapabilities=false \ 42 | -Dseccomp=false \ 43 | -Dselinux=false \ 44 | -Dapparmor=false \ 45 | -Dopenssl=false \ 46 | -Ddbus=false \ 47 | -Dandroid-log=true \ 48 | -Dlandlock-monitor=true \ 49 | --cross-file aarch64-android-api30.txt 50 | 51 | meson compile -C build 52 | sudo /usr/local/bin/ninja -C build install 53 | 54 | - name: Upload artifacts lxc 55 | uses: actions/upload-artifact@v4.3.1 56 | with: 57 | name: android-aarch64-lxc-shared-api30 58 | path: /data/share/* 59 | 60 | - name: Upload artifacts lxc-module 61 | uses: actions/upload-artifact@v4.3.1 62 | with: 63 | name: android-lxc-module 64 | path: lxc-module.zip 65 | -------------------------------------------------------------------------------- /.github/workflows/coverity.yml: -------------------------------------------------------------------------------- 1 | name: Coverity 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | coverity: 12 | name: Build and upload 13 | runs-on: ubuntu-24.04 14 | if: github.repository == 'lxc/lxc' 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v6 18 | 19 | - name: Download Coverity Build Tool 20 | run: | 21 | wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=lxc/lxc" -O cov-analysis-linux64.tar.gz 22 | mkdir cov-analysis-linux64 23 | tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64 24 | env: 25 | TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} 26 | 27 | - name: Install dependencies 28 | run: | 29 | sudo apt-get update -qq 30 | sudo apt-get install -qq gcc clang meson 31 | sudo apt-get install -qq libapparmor-dev libcap-dev libseccomp-dev libselinux1-dev linux-libc-dev libpam0g-dev docbook2x libdbus-1-dev 32 | 33 | - name: Run coverity 34 | run: | 35 | # Configure 36 | export PATH="$(pwd)/cov-analysis-linux64/bin:${PATH}" 37 | export CFLAGS="-Wall -Werror" 38 | export LDFLAGS="-pthread -lpthread" 39 | 40 | BUILD="$(pwd)/build" 41 | meson setup -Dtests=true -Dpam-cgroup=true -Dcoverity-build=true build/ 42 | 43 | # Build 44 | cov-build --dir cov-int ninja -C ${BUILD} 45 | tar czvf upload.tgz cov-int 46 | 47 | # Submit the results 48 | curl \ 49 | --form project=lxc/lxc \ 50 | --form token=${TOKEN} \ 51 | --form email=lxc-devel@lists.linuxcontainers.org \ 52 | --form file=@upload.tgz \ 53 | --form version=main \ 54 | --form description="${GITHUB_SHA}" \ 55 | https://scan.coverity.com/builds?project=lxc/lxc 56 | env: 57 | TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} 58 | -------------------------------------------------------------------------------- /doc/lxc-unfreeze.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | ]> 8 | 9 | 10 | 11 | @LXC_GENERATE_DATE@ 12 | 13 | 14 | lxc-unfreeze 15 | 1 16 | 17 | 18 | 19 | lxc-unfreeze 20 | 21 | 22 | thaw all the container's processes 23 | 24 | 25 | 26 | 27 | 28 | lxc-unfreeze 29 | -n name 30 | 31 | 32 | 33 | 34 | Description 35 | 36 | 37 | lxc-unfreeze will thaw all the processes 38 | previously frozen by the lxc-freeze command. 39 | 40 | 41 | 42 | 43 | &commonoptions; 44 | 45 | 46 | Diagnostic 47 | 48 | 49 | 50 | 51 | The container was not found 52 | 53 | 54 | The specified container was not created before with 55 | the lxc-create command. 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | &seealso; 66 | 67 | 68 | 69 | 85 | -------------------------------------------------------------------------------- /hooks/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | hooks_unmount_namespace_sources = files('unmount-namespace.c') 4 | 5 | hook_programs += executable( 6 | 'unmount-namespace', 7 | hooks_unmount_namespace_sources, 8 | include_directories: liblxc_includes, 9 | install: true, 10 | install_dir: join_paths(lxclibexec, 'hooks')) 11 | 12 | hook_programs = configure_file( 13 | configuration: dummy_config_data, 14 | input: 'clonehostname', 15 | output: 'clonehostname') 16 | install_data(join_paths(project_build_root, 'hooks/clonehostname'), install_dir: lxchookdir) 17 | 18 | hook_programs = configure_file( 19 | configuration: dummy_config_data, 20 | input: 'dhclient-script', 21 | output: 'dhclient-script') 22 | install_data(join_paths(project_build_root, 'hooks/dhclient-script'), install_dir: lxchookdir) 23 | 24 | hook_programs = configure_file( 25 | configuration: conf, 26 | input: 'dhclient.in', 27 | output: 'dhclient') 28 | install_data(join_paths(project_build_root, 'hooks/dhclient'), install_dir: lxchookdir) 29 | 30 | hook_programs = configure_file( 31 | configuration: dummy_config_data, 32 | input: 'mountecryptfsroot', 33 | output: 'mountecryptfsroot') 34 | install_data(join_paths(project_build_root, 'hooks/mountecryptfsroot'), install_dir: lxchookdir) 35 | 36 | hook_programs = configure_file( 37 | configuration: dummy_config_data, 38 | input: 'nvidia', 39 | output: 'nvidia') 40 | install_data(join_paths(project_build_root, 'hooks/nvidia'), install_dir: lxchookdir) 41 | 42 | hook_programs = configure_file( 43 | configuration: dummy_config_data, 44 | input: 'squid-deb-proxy-client', 45 | output: 'squid-deb-proxy-client') 46 | install_data(join_paths(project_build_root, 'hooks/squid-deb-proxy-client'), install_dir: lxchookdir) 47 | 48 | hook_programs = configure_file( 49 | configuration: dummy_config_data, 50 | input: 'ubuntu-cloud-prep', 51 | output: 'ubuntu-cloud-prep') 52 | install_data(join_paths(project_build_root, 'hooks/ubuntu-cloud-prep'), install_dir: lxchookdir) 53 | -------------------------------------------------------------------------------- /src/tests/createtest.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define MYNAME "lxctest1" 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | struct lxc_container *c; 24 | int ret = 1; 25 | 26 | if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { 27 | fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); 28 | ret = 1; 29 | goto out; 30 | } 31 | 32 | if (c->is_defined(c)) { 33 | fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); 34 | goto out; 35 | } 36 | 37 | if (!c->set_config_item(c, "lxc.net.0.type", "veth")) { 38 | fprintf(stderr, "%d: failed to set network type\n", __LINE__); 39 | goto out; 40 | } 41 | 42 | c->set_config_item(c, "lxc.net.0.link", "lxcbr0"); 43 | c->set_config_item(c, "lxc.net.0.flags", "up"); 44 | 45 | if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { 46 | fprintf(stderr, "%d: failed to create a container\n", __LINE__); 47 | goto out; 48 | } 49 | 50 | if (!c->is_defined(c)) { 51 | fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); 52 | goto out; 53 | } 54 | 55 | c->clear_config(c); 56 | c->load_config(c, NULL); 57 | c->want_daemonize(c, true); 58 | 59 | if (!c->startl(c, 0, NULL)) { 60 | fprintf(stderr, "%d: failed to start %s\n", __LINE__, MYNAME); 61 | goto out; 62 | } 63 | 64 | if (!c->stop(c)) { 65 | fprintf(stderr, "%d: failed to stop %s\n", __LINE__, MYNAME); 66 | goto out; 67 | } 68 | 69 | if (!c->destroy(c)) { 70 | fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); 71 | goto out; 72 | } 73 | 74 | if (c->is_defined(c)) { 75 | fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); 76 | goto out; 77 | } 78 | 79 | fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); 80 | ret = 0; 81 | 82 | out: 83 | lxc_container_put(c); 84 | exit(ret); 85 | } 86 | -------------------------------------------------------------------------------- /doc/ko/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if want_mans 4 | PAGES = [ 5 | ['lxc', '7'], 6 | ['lxc.conf', '5'], 7 | ['lxc.container.conf', '5'], 8 | ['lxc.system.conf', '5'], 9 | ['lxc-usernet', '5'], 10 | ['lxc-user-nic', '1'], 11 | ['lxc-usernsexec', '1'], 12 | ] 13 | 14 | if want_tools 15 | PAGES += [ 16 | ['lxc-attach', '1'], 17 | ['lxc-autostart', '1'], 18 | ['lxc-cgroup', '1'], 19 | ['lxc-checkconfig', '1'], 20 | ['lxc-checkpoint', '1'], 21 | ['lxc-config', '1'], 22 | ['lxc-console', '1'], 23 | ['lxc-copy', '1'], 24 | ['lxc-create', '1'], 25 | ['lxc-destroy', '1'], 26 | ['lxc-device', '1'], 27 | ['lxc-execute', '1'], 28 | ['lxc-freeze', '1'], 29 | ['lxc-info', '1'], 30 | ['lxc-ls', '1'], 31 | ['lxc-monitor', '1'], 32 | ['lxc-snapshot', '1'], 33 | ['lxc-start', '1'], 34 | ['lxc-stop', '1'], 35 | ['lxc-top', '1'], 36 | ['lxc-unfreeze', '1'], 37 | ['lxc-unshare', '1'], 38 | ['lxc-wait', '1'], 39 | ] 40 | endif 41 | 42 | # Common files. 43 | configure_file( 44 | configuration: docconf, 45 | input: 'common_options.sgml.in', 46 | output: 'common_options.sgml') 47 | 48 | configure_file( 49 | configuration: docconf, 50 | input: 'see_also.sgml.in', 51 | output: 'see_also.sgml') 52 | 53 | # Initial templating. 54 | foreach page : PAGES 55 | sgml = configure_file( 56 | configuration: docconf, 57 | input: page[0] + '.sgml.in', 58 | output: page[0] + '.sgml') 59 | 60 | configure_file( 61 | input: sgml, 62 | output: page[0] + '.' + page[1], 63 | command: [sgml2man, '--encoding=UTF-8', page[0] + '.sgml'], 64 | install: true, 65 | install_dir: join_paths(mandir, 'ko', 'man' + page[1])) 66 | endforeach 67 | endif 68 | -------------------------------------------------------------------------------- /src/lxc/mainloop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_MAINLOOP_H 4 | #define __LXC_MAINLOOP_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | 10 | #include "compiler.h" 11 | #include "hlist.h" 12 | #include "memory_utils.h" 13 | 14 | #define LXC_MAINLOOP_ERROR -1 15 | #define LXC_MAINLOOP_CONTINUE 0 16 | #define LXC_MAINLOOP_CLOSE 1 17 | #define LXC_MAINLOOP_DISARM 2 18 | 19 | typedef enum { 20 | LXC_MAINLOOP_EPOLL = 1, 21 | LXC_MAINLOOP_IO_URING = 2, 22 | } async_descr_t; 23 | 24 | struct lxc_async_descr { 25 | async_descr_t type; 26 | union { 27 | int epfd; 28 | #if HAVE_LIBURING 29 | struct io_uring *ring; 30 | #endif 31 | }; 32 | struct list_head handlers; 33 | }; 34 | 35 | static inline int default_cleanup_handler(int fd, void *data) 36 | { 37 | return 0; 38 | } 39 | 40 | typedef int (*lxc_mainloop_callback_t)(int fd, uint32_t event, void *data, 41 | struct lxc_async_descr *descr); 42 | 43 | typedef int (*lxc_mainloop_cleanup_t)(int fd, void *data); 44 | 45 | __hidden extern int lxc_mainloop(struct lxc_async_descr *descr, int timeout_ms); 46 | 47 | __hidden extern int lxc_mainloop_add_handler_events(struct lxc_async_descr *descr, int fd, int events, 48 | lxc_mainloop_callback_t callback, 49 | lxc_mainloop_cleanup_t cleanup, 50 | void *data, const char *name); 51 | __hidden extern int lxc_mainloop_add_handler(struct lxc_async_descr *descr, int fd, 52 | lxc_mainloop_callback_t callback, 53 | lxc_mainloop_cleanup_t cleanup, 54 | void *data, const char *name); 55 | __hidden extern int lxc_mainloop_add_oneshot_handler(struct lxc_async_descr *descr, int fd, 56 | lxc_mainloop_callback_t callback, 57 | lxc_mainloop_cleanup_t cleanup, 58 | void *data, const char *name); 59 | 60 | __hidden extern int lxc_mainloop_del_handler(struct lxc_async_descr *descr, int fd); 61 | 62 | __hidden extern int lxc_mainloop_open(struct lxc_async_descr *descr); 63 | 64 | __hidden extern void lxc_mainloop_close(struct lxc_async_descr *descr); 65 | 66 | define_cleanup_function(struct lxc_async_descr *, lxc_mainloop_close); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /doc/ja/lxc-checkconfig.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | ]> 7 | 8 | 9 | 10 | @LXC_GENERATE_DATE@ 11 | 12 | 13 | lxc-checkconfig 14 | 1 15 | 16 | 17 | 18 | lxc-checkconfig 19 | 20 | 21 | 24 | 現在のカーネルが lxc に必要な機能をサポートしているかのチェック 25 | 26 | 27 | 28 | 29 | 30 | lxc-checkconfig 31 | 32 | 33 | 34 | 35 | <!-- Description -->説明 36 | 37 | 41 | lxc-checkconfig は、現在のカーネルが lxc に必要な機能をサポートしているかをチェックします。 42 | 43 | 44 | 45 | 46 | <!-- Examples -->例 47 | 48 | 49 | lxc-checkconfig 50 | 51 | 52 | 56 | 現在のカーネルをチェックします。 57 | CONFIG 環境変数に別の場所を設定することも可能です。 58 | (訳注: カーネルビルド時の設定オプションのファイルの位置を指定します。デフォルトは /proc/config.gz です。) 59 | 60 | 61 | 62 | 63 | 64 | 65 | &seealso; 66 | 67 | 68 | 84 | -------------------------------------------------------------------------------- /doc/ko/lxc-checkconfig.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | ]> 7 | 8 | 9 | 10 | @LXC_GENERATE_DATE@ 11 | 12 | 13 | lxc-checkconfig 14 | 1 15 | 16 | 17 | 18 | lxc-checkconfig 19 | 20 | 21 | 24 | 현재 커널의 lxc 지원 여부 검사 25 | 26 | 27 | 28 | 29 | 30 | lxc-checkconfig 31 | 32 | 33 | 34 | 35 | <!-- Description -->설명 36 | 37 | 41 | lxc-checkconfig는 현재 커널이 lxc를 지원하는지 검사한다. 42 | 43 | 44 | 45 | 46 | <!-- Examples -->예제 47 | 48 | 49 | lxc-checkconfig 50 | 51 | 52 | 56 | 현재 커널을 검사한다. 57 | CONFIG 환경 변수를 이용하여 다른 위치를 설정할 수 있다. 58 | (역주 : 기본값은 /proc/config.gz 이다. Kernel compile option에서 Enable access to .config through /proc/config.gz를 체크하여야 한다) 59 | 60 | 61 | 62 | 63 | 64 | 65 | &seealso; 66 | 67 | 68 | 84 | -------------------------------------------------------------------------------- /doc/lxc-freeze.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | ]> 8 | 9 | 10 | 11 | @LXC_GENERATE_DATE@ 12 | 13 | 14 | lxc-freeze 15 | 1 16 | 17 | 18 | 19 | lxc-freeze 20 | 21 | 22 | freeze all the container's processes 23 | 24 | 25 | 26 | 27 | 28 | lxc-freeze 29 | -n name 30 | 31 | 32 | 33 | 34 | Description 35 | 36 | 37 | lxc-freeze freezes all the processes running 38 | inside the container. The processes will be blocked until they 39 | are explicitly thawed by the lxc-unfreeze 40 | command. This command is useful for batch managers to schedule a 41 | group of processes. 42 | 43 | 44 | 45 | 46 | &commonoptions; 47 | 48 | 49 | Diagnostic 50 | 51 | 52 | 53 | 54 | The container was not found 55 | 56 | 57 | The specified container was not created before with 58 | the lxc-create command. 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | &seealso; 69 | 70 | 71 | 72 | 88 | -------------------------------------------------------------------------------- /doc/ja/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if want_mans 4 | PAGES = [ 5 | ['lxc', '7'], 6 | ['lxc.conf', '5'], 7 | ['lxc.container.conf', '5'], 8 | ['lxc.system.conf', '5'], 9 | ['lxc-update-config', '1'], 10 | ['lxc-usernet', '5'], 11 | ['lxc-user-nic', '1'], 12 | ['lxc-usernsexec', '1'], 13 | ] 14 | 15 | if want_tools 16 | PAGES += [ 17 | ['lxc-attach', '1'], 18 | ['lxc-autostart', '1'], 19 | ['lxc-cgroup', '1'], 20 | ['lxc-checkconfig', '1'], 21 | ['lxc-checkpoint', '1'], 22 | ['lxc-config', '1'], 23 | ['lxc-console', '1'], 24 | ['lxc-copy', '1'], 25 | ['lxc-create', '1'], 26 | ['lxc-destroy', '1'], 27 | ['lxc-device', '1'], 28 | ['lxc-execute', '1'], 29 | ['lxc-freeze', '1'], 30 | ['lxc-info', '1'], 31 | ['lxc-ls', '1'], 32 | ['lxc-monitor', '1'], 33 | ['lxc-snapshot', '1'], 34 | ['lxc-start', '1'], 35 | ['lxc-stop', '1'], 36 | ['lxc-top', '1'], 37 | ['lxc-unfreeze', '1'], 38 | ['lxc-unshare', '1'], 39 | ['lxc-wait', '1'], 40 | ] 41 | endif 42 | 43 | if want_pam_cgroup 44 | PAGES += [ 45 | ['pam_cgfs', '8'], 46 | ] 47 | endif 48 | 49 | # Common files. 50 | configure_file( 51 | configuration: docconf, 52 | input: 'common_options.sgml.in', 53 | output: 'common_options.sgml') 54 | 55 | configure_file( 56 | configuration: docconf, 57 | input: 'see_also.sgml.in', 58 | output: 'see_also.sgml') 59 | 60 | # Initial templating. 61 | foreach page : PAGES 62 | sgml = configure_file( 63 | configuration: docconf, 64 | input: page[0] + '.sgml.in', 65 | output: page[0] + '.sgml') 66 | 67 | configure_file( 68 | input: sgml, 69 | output: page[0] + '.' + page[1], 70 | command: [sgml2man, '--encoding=UTF-8', page[0] + '.sgml'], 71 | install: true, 72 | install_dir: join_paths(mandir, 'ja', 'man' + page[1])) 73 | endforeach 74 | endif 75 | -------------------------------------------------------------------------------- /src/tests/destroytest.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define MYNAME "lxctest1" 20 | 21 | static int create_container(void) 22 | { 23 | int status, ret; 24 | pid_t pid = fork(); 25 | 26 | if (pid < 0) { 27 | perror("fork"); 28 | return -1; 29 | } 30 | 31 | if (pid == 0) { 32 | execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | again: 37 | ret = waitpid(pid, &status, 0); 38 | if (ret == -1) { 39 | if (errno == EINTR) 40 | goto again; 41 | 42 | perror("waitpid"); 43 | return -1; 44 | } 45 | 46 | if (ret != pid) 47 | goto again; 48 | 49 | if (!WIFEXITED(status)) { // did not exit normally 50 | fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__); 51 | return -1; 52 | } 53 | 54 | return WEXITSTATUS(status); 55 | } 56 | 57 | int main(int argc, char *argv[]) 58 | { 59 | struct lxc_container *c; 60 | int ret = 1; 61 | 62 | if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { 63 | fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); 64 | ret = 1; 65 | goto out; 66 | } 67 | 68 | if (c->is_defined(c)) { 69 | fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); 70 | goto out; 71 | } 72 | 73 | if (create_container()) { 74 | fprintf(stderr, "%d: failed to create a container\n", __LINE__); 75 | goto out; 76 | } 77 | 78 | if (!c->is_defined(c)) { 79 | fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); 80 | goto out; 81 | } 82 | 83 | if (!c->destroy(c)) { 84 | fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); 85 | goto out; 86 | } 87 | 88 | if (c->is_defined(c)) { 89 | fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); 90 | goto out; 91 | } 92 | 93 | fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); 94 | ret = 0; 95 | 96 | out: 97 | lxc_container_put(c); 98 | exit(ret); 99 | } 100 | -------------------------------------------------------------------------------- /src/lxc/tools/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | tools_common_sources = files('arguments.c', 'arguments.h') + include_sources 4 | tools_common_sources_for_dynamic_link = tools_common_sources + netns_ifaddrs_sources 5 | 6 | tools_commands_dynamic_link = ['attach', 'autostart', 'cgroup', 'checkpoint', 'config', 7 | 'console', 'copy', 'create', 'destroy', 'device', 'execute', 'freeze', 8 | 'info', 'ls', 'snapshot', 'start', 'stop', 'top', 'unfreeze', 9 | 'unshare', 'wait'] 10 | 11 | tools_commands_static_link = ['monitor'] 12 | 13 | tools_commands = tools_commands_dynamic_link + tools_commands_static_link 14 | 15 | if want_tools 16 | foreach cmd : tools_commands_dynamic_link 17 | public_programs += executable( 18 | 'lxc-' + cmd, 19 | files('lxc_' + cmd + '.c') + tools_common_sources_for_dynamic_link + liblxc_ext_sources, 20 | dependencies: liblxc_dependencies, 21 | include_directories: liblxc_includes, 22 | c_args: ['-DNO_LXC_CONF'], 23 | link_with: [liblxc], 24 | install: true) 25 | endforeach 26 | 27 | foreach cmd : tools_commands_static_link 28 | public_programs += executable( 29 | 'lxc-' + cmd, 30 | files('lxc_' + cmd + '.c') + files('arguments.c', 'arguments.h'), 31 | dependencies: liblxc_dependencies, 32 | include_directories: liblxc_includes, 33 | link_whole: [liblxc_static], 34 | install: true) 35 | endforeach 36 | endif 37 | 38 | if want_tools_multicall 39 | tools_all_sources = files('lxc_multicall.c') + files('arguments.c', 'arguments.h') 40 | foreach cmd : tools_commands 41 | tools_all_sources += files('lxc_' + cmd + '.c') 42 | endforeach 43 | 44 | public_programs += executable( 45 | 'lxc', 46 | tools_all_sources, 47 | include_directories: liblxc_includes, 48 | dependencies: liblxc_dependencies, 49 | link_whole: [liblxc_static], 50 | install: true) 51 | 52 | if want_tools == false 53 | foreach cmd : tools_commands 54 | public_programs += install_symlink( 55 | 'lxc-' + cmd, 56 | pointing_to: 'lxc', 57 | install_dir: get_option('bindir')) 58 | endforeach 59 | endif 60 | endif 61 | -------------------------------------------------------------------------------- /src/tests/lxc-test-autostart: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # SPDX-License-Identifier: LGPL-2.1+ 4 | 5 | # lxc: linux Container library 6 | 7 | DONE=0 8 | cleanup() { 9 | lxc-destroy -n $CONTAINER_NAME >/dev/null 2>&1 || true 10 | 11 | if [ $DONE -eq 0 ]; then 12 | echo "FAIL" 13 | exit 1 14 | fi 15 | echo "PASS" 16 | } 17 | 18 | trap cleanup EXIT HUP INT TERM 19 | set -eu 20 | 21 | # Create a container 22 | CONTAINER_NAME=lxc-test-auto 23 | 24 | lxc-create -t busybox -n $CONTAINER_NAME -B dir 25 | CONTAINER_PATH=$(dirname $(lxc-info -n $CONTAINER_NAME -c lxc.rootfs.path -H) | sed -e 's/dir://') 26 | cp $CONTAINER_PATH/config $CONTAINER_PATH/config.bak 27 | 28 | # Ensure it's not in lxc-autostart 29 | lxc-autostart -L | grep -q $CONTAINER_NAME && \ 30 | (echo "Container shouldn't be auto-started" && exit 1) 31 | 32 | # Mark it as auto-started and re-check 33 | echo "lxc.start.auto = 1" >> $CONTAINER_PATH/config 34 | lxc-autostart -L | grep -q $CONTAINER_NAME || \ 35 | (echo "Container should be auto-started" && exit 1) 36 | 37 | # Put it in a test group and set a delay 38 | echo "lxc.group = lxc-auto-test" >> $CONTAINER_PATH/config 39 | echo "lxc.start.delay = 5" >> $CONTAINER_PATH/config 40 | 41 | # Check that everything looks good 42 | if [ "$(lxc-autostart -L -g lxc-auto-test | grep $CONTAINER_NAME)" != "$CONTAINER_NAME 5" ]; then 43 | echo "Invalid autostart setting" && exit 1 44 | fi 45 | 46 | # Start it 47 | lxc-autostart -g lxc-auto-test 48 | lxc-wait -n $CONTAINER_NAME -t 5 -s RUNNING || (echo "Container didn't start" && exit 1) 49 | sleep 5 50 | 51 | # Restart it 52 | lxc-autostart -g lxc-auto-test -r 53 | lxc-wait -n $CONTAINER_NAME -t 5 -s RUNNING || (echo "Container didn't restart" && exit 1) 54 | sleep 5 55 | 56 | # When shutting down, the container calls sync. If the machine running 57 | # the test has a massive backlog, it can take minutes for the sync call to 58 | # finish, causing a test failure. 59 | # So try to reduce that by flushing everything to disk before we attempt 60 | # a container shutdown. 61 | sync 62 | 63 | # Shut it down 64 | lxc-autostart -g lxc-auto-test -s -t 120 65 | lxc-wait -n $CONTAINER_NAME -t 120 -s STOPPED || (echo "Container didn't stop" && exit 1) 66 | 67 | # Kill it 68 | lxc-autostart -g lxc-auto-test -k 69 | lxc-wait -n $CONTAINER_NAME -t 60 -s STOPPED || (echo "Container didn't die" && exit 1) 70 | 71 | DONE=1 72 | -------------------------------------------------------------------------------- /doc/ja/lxc-unfreeze.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | ]> 8 | 9 | 10 | 11 | @LXC_GENERATE_DATE@ 12 | 13 | 14 | lxc-unfreeze 15 | 1 16 | 17 | 18 | 19 | lxc-unfreeze 20 | 21 | 22 | 25 | 全てのコンテナのプロセスの解凍 26 | 27 | 28 | 29 | 30 | 31 | lxc-unfreeze 32 | -n name 33 | 34 | 35 | 36 | 37 | <!-- Description -->説明 38 | 39 | 40 | 44 | lxc-unfreeze は、先に lxc-freeze を使って凍結した全てのプロセスを解凍します。 45 | 46 | 47 | 48 | 49 | &commonoptions; 50 | 51 | 52 | <!-- Diagnostic -->診断 53 | 54 | 55 | 56 | 57 | The container was not found 58 | 59 | 60 | 64 | 指定したコンテナが lxc-create で作成されておらず存在しません。 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | &seealso; 75 | 76 | 77 | 78 | 94 | -------------------------------------------------------------------------------- /doc/examples/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | example_lxc_complex = configure_file( 4 | configuration: dummy_config_data, 5 | input: 'lxc-complex.conf.in', 6 | output: 'lxc-complex.conf', 7 | install: want_examples, 8 | install_dir: lxcexamplesdir) 9 | 10 | example_lxc_empty_netns = configure_file( 11 | configuration: dummy_config_data, 12 | input: 'lxc-empty-netns.conf.in', 13 | output: 'lxc-empty-netns.conf', 14 | install: want_examples, 15 | install_dir: lxcexamplesdir) 16 | 17 | example_lxc_macvlan = configure_file( 18 | configuration: dummy_config_data, 19 | input: 'lxc-macvlan.conf.in', 20 | output: 'lxc-macvlan.conf', 21 | install: want_examples, 22 | install_dir: lxcexamplesdir) 23 | 24 | example_lxc_no_netns = configure_file( 25 | configuration: dummy_config_data, 26 | input: 'lxc-no-netns.conf.in', 27 | output: 'lxc-no-netns.conf', 28 | install: want_examples, 29 | install_dir: lxcexamplesdir) 30 | 31 | example_lxc_phys = configure_file( 32 | configuration: dummy_config_data, 33 | input: 'lxc-phys.conf.in', 34 | output: 'lxc-phys.conf', 35 | install: want_examples, 36 | install_dir: lxcexamplesdir) 37 | 38 | example_lxc_veth = configure_file( 39 | configuration: dummy_config_data, 40 | input: 'lxc-veth.conf.in', 41 | output: 'lxc-veth.conf', 42 | install: want_examples, 43 | install_dir: lxcexamplesdir) 44 | 45 | example_lxc_vlan = configure_file( 46 | configuration: dummy_config_data, 47 | input: 'lxc-vlan.conf.in', 48 | output: 'lxc-vlan.conf', 49 | install: want_examples, 50 | install_dir: lxcexamplesdir) 51 | 52 | example_lxc_seccomp_v1 = configure_file( 53 | configuration: dummy_config_data, 54 | input: 'seccomp-v1.conf', 55 | output: 'seccomp-v1.conf', 56 | install: want_examples, 57 | install_dir: lxcexamplesdir) 58 | 59 | example_lxc_seccomp_v2 = configure_file( 60 | configuration: dummy_config_data, 61 | input: 'seccomp-v2.conf', 62 | output: 'seccomp-v2.conf', 63 | install: want_examples, 64 | install_dir: lxcexamplesdir) 65 | 66 | example_lxc_seccomp_v2 = configure_file( 67 | configuration: dummy_config_data, 68 | input: 'seccomp-v2-denylist.conf', 69 | output: 'seccomp-v2-denylist.conf', 70 | install: want_examples, 71 | install_dir: lxcexamplesdir) 72 | -------------------------------------------------------------------------------- /src/tests/shutdowntest.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define MYNAME "lxctest1" 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | struct lxc_container *c; 24 | int ret = 1; 25 | 26 | if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { 27 | fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); 28 | ret = 1; 29 | goto out; 30 | } 31 | 32 | if (c->is_defined(c)) { 33 | fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); 34 | goto out; 35 | } 36 | 37 | if (!c->set_config_item(c, "lxc.net.0.type", "veth")) { 38 | fprintf(stderr, "%d: failed to set network type\n", __LINE__); 39 | goto out; 40 | } 41 | 42 | c->set_config_item(c, "lxc.net.0.link", "lxcbr0"); 43 | c->set_config_item(c, "lxc.net.0.flags", "up"); 44 | 45 | if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { 46 | fprintf(stderr, "%d: failed to create a container\n", __LINE__); 47 | goto out; 48 | } 49 | 50 | if (!c->is_defined(c)) { 51 | fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); 52 | goto out; 53 | } 54 | 55 | c->clear_config(c); 56 | c->load_config(c, NULL); 57 | c->want_daemonize(c, true); 58 | 59 | if (!c->startl(c, 0, NULL)) { 60 | fprintf(stderr, "%d: failed to start %s\n", __LINE__, MYNAME); 61 | goto out; 62 | } 63 | 64 | /* Wait for init to be ready for SIGPWR */ 65 | sleep(20); 66 | 67 | if (!c->shutdown(c, 120)) { 68 | fprintf(stderr, "%d: failed to shut down %s\n", __LINE__, MYNAME); 69 | if (!c->stop(c)) 70 | fprintf(stderr, "%d: failed to kill %s\n", __LINE__, MYNAME); 71 | 72 | goto out; 73 | } 74 | 75 | if (!c->destroy(c)) { 76 | fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); 77 | goto out; 78 | } 79 | 80 | if (c->is_defined(c)) { 81 | fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); 82 | goto out; 83 | } 84 | 85 | fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); 86 | ret = 0; 87 | 88 | out: 89 | if (c && c->is_defined(c)) 90 | c->destroy(c); 91 | 92 | lxc_container_put(c); 93 | exit(ret); 94 | } 95 | -------------------------------------------------------------------------------- /doc/ko/lxc-unfreeze.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | ]> 8 | 9 | 10 | 11 | @LXC_GENERATE_DATE@ 12 | 13 | 14 | lxc-unfreeze 15 | 1 16 | 17 | 18 | 19 | lxc-unfreeze 20 | 21 | 22 | 25 | 컨테이너의 모든 프로세스를 동결해제 26 | 27 | 28 | 29 | 30 | 31 | lxc-unfreeze 32 | -n name 33 | 34 | 35 | 36 | 37 | <!-- Description -->설명 38 | 39 | 40 | 44 | lxc-unfreeze는 이전에 lxc-freeze로 동결 시켰던 모든 프로세스들을 동결해제한다. 45 | 46 | 47 | 48 | 49 | &commonoptions; 50 | 51 | 52 | <!-- Diagnostic -->진단 53 | 54 | 55 | 56 | 57 | The container was not found 58 | 59 | 60 | 64 | 지정한 컨테이너가 lxc-create로 생성된 적이 없다. 65 | 컨테이너가 존재하지 않는다. 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | &seealso; 76 | 77 | 78 | 79 | 95 | -------------------------------------------------------------------------------- /src/tests/list.c: -------------------------------------------------------------------------------- 1 | /* list.c 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | static void test_list_func(const char *lxcpath, const char *type, 15 | int (*func)(const char *path, char ***names, 16 | struct lxc_container ***cret)) 17 | { 18 | int i, n, n2; 19 | struct lxc_container **clist; 20 | char **names; 21 | 22 | printf("%-10s Counting containers\n", type); 23 | 24 | n = func(lxcpath, NULL, NULL); 25 | printf("%-10s Counted %d containers\n", type, n); 26 | printf("%-10s Get container struct only\n", type); 27 | 28 | n2 = func(lxcpath, NULL, &clist); 29 | if (n2 != n) 30 | printf("Warning: first call returned %d, second %d\n", n, n2); 31 | 32 | for (i = 0; i < n2; i++) { 33 | struct lxc_container *c = clist[i]; 34 | printf("%-10s Got container struct %s\n", type, c->name); 35 | lxc_container_put(c); 36 | } 37 | 38 | if (n2 > 0) { 39 | free(clist); 40 | clist = NULL; 41 | } 42 | 43 | printf("%-10s Get names only\n", type); 44 | n2 = func(lxcpath, &names, NULL); 45 | if (n2 != n) 46 | printf("Warning: first call returned %d, second %d\n", n, n2); 47 | 48 | for (i = 0; i < n2; i++) { 49 | printf("%-10s Got container name %s\n", type, names[i]); 50 | free(names[i]); 51 | } 52 | 53 | if (n2 > 0) { 54 | free(names); 55 | names = NULL; 56 | } 57 | 58 | printf("%-10s Get names and containers\n", type); 59 | n2 = func(lxcpath, &names, &clist); 60 | if (n2 != n) 61 | printf("Warning: first call returned %d, second %d\n", n, n2); 62 | 63 | for (i = 0; i < n2; i++) { 64 | struct lxc_container *c = clist[i]; 65 | printf("%-10s Got container struct %s, name %s\n", type, c->name, names[i]); 66 | 67 | if (strcmp(c->name, names[i])) 68 | fprintf(stderr, "ERROR: name mismatch!\n"); 69 | 70 | free(names[i]); 71 | lxc_container_put(c); 72 | } 73 | 74 | if (n2 > 0) { 75 | free(names); 76 | free(clist); 77 | } 78 | } 79 | 80 | int main(int argc, char *argv[]) 81 | { 82 | const char *lxcpath = NULL; 83 | 84 | if (argc > 1) 85 | lxcpath = argv[1]; 86 | 87 | test_list_func(lxcpath, "Defined:", list_defined_containers); 88 | test_list_func(lxcpath, "Active:", list_active_containers); 89 | test_list_func(lxcpath, "All:", list_all_containers); 90 | 91 | exit(EXIT_SUCCESS); 92 | } 93 | -------------------------------------------------------------------------------- /src/lxc/storage/overlay.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_OVERLAY_H 4 | #define __LXC_OVERLAY_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "compiler.h" 16 | #include "storage.h" 17 | 18 | struct lxc_storage; 19 | 20 | struct bdev_specs; 21 | 22 | struct lxc_conf; 23 | 24 | struct lxc_rootfs; 25 | 26 | __hidden extern int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, 27 | const char *oldname, const char *cname, const char *oldpath, 28 | const char *lxcpath, int snap, uint64_t newsize, 29 | struct lxc_conf *conf); 30 | __hidden extern int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n, 31 | struct bdev_specs *specs, const struct lxc_conf *conf); 32 | __hidden extern int ovl_destroy(struct lxc_storage *orig); 33 | __hidden extern bool ovl_detect(const char *path); 34 | __hidden extern int ovl_mount(struct lxc_storage *bdev); 35 | __hidden extern int ovl_umount(struct lxc_storage *bdev); 36 | 37 | /* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container 38 | * with overlay lxc.mount.entry entries we need to update absolute paths for 39 | * upper- and workdir. This update is done in two locations: 40 | * lxc_conf->unexpanded_config and lxc_conf->mount_entries. Both updates are 41 | * done independent of each other since lxc_conf->mountlist may container more 42 | * mount entries (e.g. from other included files) than 43 | * lxc_conf->unexpanded_config . 44 | */ 45 | __hidden extern int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path, 46 | const char *lxc_name, const char *newpath, 47 | const char *newname); 48 | 49 | /* To be called from functions in lxccontainer.c: Get lower directory for 50 | * overlay rootfs. 51 | */ 52 | __hidden extern const char *ovl_get_lower(const char *rootfs_path); 53 | 54 | /* Get rootfs path for overlay backed containers. Allocated memory must be freed 55 | * by caller. 56 | */ 57 | __hidden extern char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen); 58 | 59 | /* Create upper- and workdirs for overlay mounts. 60 | */ 61 | __hidden extern int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs, 62 | const char *lxc_name, const char *lxc_path); 63 | 64 | #endif /* __LXC_OVERLAY_H */ 65 | -------------------------------------------------------------------------------- /src/lxc/ringbuf.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_RINGBUF_H 4 | #define __LXC_RINGBUF_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "compiler.h" 14 | 15 | /** 16 | * lxc_ringbuf - Implements a simple and efficient memory mapped ringbuffer. 17 | * - The "addr" field of struct lxc_ringbuf is considered immutable. Instead the 18 | * read and write offsets r_off and w_off are used to calculate the current 19 | * read and write addresses. There should never be a need to use any of those 20 | * fields directly. Instead use the appropriate helpers below. 21 | * - Callers are expected to synchronize read and write accesses to the 22 | * ringbuffer. 23 | */ 24 | struct lxc_ringbuf { 25 | char *addr; /* start address of the ringbuffer */ 26 | uint64_t size; /* total size of the ringbuffer in bytes */ 27 | uint64_t r_off; /* read offset */ 28 | uint64_t w_off; /* write offset */ 29 | }; 30 | 31 | /** 32 | * lxc_ringbuf_create - Initialize a new ringbuffer. 33 | * 34 | * @param[in] size Size of the new ringbuffer as a power of 2. 35 | */ 36 | __hidden extern int lxc_ringbuf_create(struct lxc_ringbuf *buf, size_t size); 37 | __hidden extern void lxc_ringbuf_move_read_addr(struct lxc_ringbuf *buf, size_t len); 38 | __hidden extern int lxc_ringbuf_write(struct lxc_ringbuf *buf, const char *msg, size_t len); 39 | __hidden extern int lxc_ringbuf_read(struct lxc_ringbuf *buf, char *out, size_t *len); 40 | 41 | static inline void lxc_ringbuf_release(struct lxc_ringbuf *buf) 42 | { 43 | if (buf->addr) 44 | munmap(buf->addr, buf->size * 2); 45 | } 46 | 47 | static inline void lxc_ringbuf_clear(struct lxc_ringbuf *buf) 48 | { 49 | buf->r_off = 0; 50 | buf->w_off = 0; 51 | } 52 | 53 | static inline uint64_t lxc_ringbuf_used(struct lxc_ringbuf *buf) 54 | { 55 | return buf->w_off - buf->r_off; 56 | } 57 | 58 | static inline uint64_t lxc_ringbuf_free(struct lxc_ringbuf *buf) 59 | { 60 | return buf->size - lxc_ringbuf_used(buf); 61 | } 62 | 63 | static inline char *lxc_ringbuf_get_read_addr(struct lxc_ringbuf *buf) 64 | { 65 | return buf->addr + buf->r_off; 66 | } 67 | 68 | static inline char *lxc_ringbuf_get_write_addr(struct lxc_ringbuf *buf) 69 | { 70 | return buf->addr + buf->w_off; 71 | } 72 | 73 | static inline void lxc_ringbuf_move_write_addr(struct lxc_ringbuf *buf, size_t len) 74 | { 75 | buf->w_off += len; 76 | } 77 | 78 | #endif /* __LXC_RINGBUF_H */ 79 | -------------------------------------------------------------------------------- /src/lxc/freezer.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "attach_options.h" 15 | #include "cgroups/cgroup.h" 16 | #include "cgroups/cgroup_utils.h" 17 | #include "commands.h" 18 | #include "commands_utils.h" 19 | #include "error.h" 20 | #include "log.h" 21 | #include "lxc.h" 22 | #include "monitor.h" 23 | #include "state.h" 24 | #include "string_utils.h" 25 | 26 | lxc_log_define(freezer, lxc); 27 | 28 | static int do_freeze_thaw(bool freeze, struct lxc_conf *conf, const char *name, 29 | const char *lxcpath) 30 | { 31 | call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL; 32 | lxc_state_t new_state = freeze ? FROZEN : THAWED; 33 | int ret; 34 | const char *state; 35 | size_t state_len; 36 | 37 | state = lxc_state2str(new_state); 38 | state_len = strlen(state); 39 | 40 | cgroup_ops = cgroup_init(conf); 41 | if (!cgroup_ops) 42 | return -1; 43 | 44 | ret = cgroup_ops->set(cgroup_ops, "freezer.state", state, name, lxcpath); 45 | if (ret < 0) 46 | return log_error(-1, "Failed to %s %s", 47 | freeze ? "freeze" : "unfreeze", name); 48 | 49 | for (;;) { 50 | char cur_state[MAX_STATE_LENGTH] = ""; 51 | 52 | ret = cgroup_ops->get(cgroup_ops, "freezer.state", cur_state, 53 | sizeof(cur_state), name, lxcpath); 54 | if (ret < 0) 55 | return log_error(-1, "Failed to get freezer state of %s", name); 56 | 57 | cur_state[lxc_char_right_gc(cur_state, strlen(cur_state))] = '\0'; 58 | if (strnequal(cur_state, state, state_len)) { 59 | lxc_cmd_notify_state_listeners(name, lxcpath, new_state); 60 | return 0; 61 | } 62 | 63 | sleep(1); 64 | } 65 | 66 | return 0; 67 | } 68 | 69 | int lxc_freeze(struct lxc_conf *conf, const char *name, const char *lxcpath) 70 | { 71 | int ret; 72 | 73 | lxc_cmd_notify_state_listeners(name, lxcpath, FREEZING); 74 | ret = do_freeze_thaw(true, conf, name, lxcpath); 75 | lxc_cmd_notify_state_listeners(name, lxcpath, !ret ? FROZEN : RUNNING); 76 | return ret; 77 | } 78 | 79 | int lxc_unfreeze(struct lxc_conf *conf, const char *name, const char *lxcpath) 80 | { 81 | int ret; 82 | 83 | lxc_cmd_notify_state_listeners(name, lxcpath, THAWED); 84 | ret = do_freeze_thaw(false, conf, name, lxcpath); 85 | lxc_cmd_notify_state_listeners(name, lxcpath, !ret ? RUNNING : FROZEN); 86 | return ret; 87 | } 88 | -------------------------------------------------------------------------------- /doc/lxc-config.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | ]> 7 | 8 | 9 | @LXC_GENERATE_DATE@ 10 | 11 | lxc-config 12 | 1 13 | 14 | 15 | 16 | lxc-config 17 | 18 | 19 | query LXC system configuration 20 | 21 | 22 | 23 | 24 | 25 | lxc-config 26 | -l 27 | item 28 | 29 | 30 | 31 | 32 | Description 33 | 34 | 35 | lxc-config queries the lxc system 36 | configuration and lets you list all valid keys or query 37 | individual keys for their value. 38 | 39 | 40 | 41 | 42 | Options 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | List all supported keys. 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Query the value of the specified key. 62 | 63 | 64 | 65 | 66 | 67 | 68 | &seealso; 69 | 70 | 71 | 87 | -------------------------------------------------------------------------------- /src/lxc/tools/lxc_freeze.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "lxc.h" 12 | 13 | #include "arguments.h" 14 | #include "log.h" 15 | 16 | lxc_log_define(lxc_freeze, lxc); 17 | 18 | static const struct option my_longopts[] = { 19 | LXC_COMMON_OPTIONS 20 | }; 21 | 22 | static struct lxc_arguments my_args = { 23 | .progname = "lxc-freeze", 24 | .help = "\ 25 | --name=NAME\n\ 26 | \n\ 27 | lxc-freeze freezes a container with the identifier NAME\n\ 28 | \n\ 29 | Options :\n\ 30 | -n, --name=NAME NAME of the container\n\ 31 | --rcfile=FILE Load configuration file FILE\n", 32 | .options = my_longopts, 33 | .parser = NULL, 34 | .checker = NULL, 35 | .log_priority = "ERROR", 36 | .log_file = "none", 37 | }; 38 | 39 | int __attribute__((weak, alias("lxc_freeze_main"))) main(int argc, char *argv[]); 40 | int lxc_freeze_main(int argc, char *argv[]) 41 | { 42 | struct lxc_container *c; 43 | struct lxc_log log; 44 | 45 | if (lxc_arguments_parse(&my_args, argc, argv)) 46 | exit(EXIT_FAILURE); 47 | 48 | log.name = my_args.name; 49 | log.file = my_args.log_file; 50 | log.level = my_args.log_priority; 51 | log.prefix = my_args.progname; 52 | log.quiet = my_args.quiet; 53 | log.lxcpath = my_args.lxcpath[0]; 54 | 55 | if (lxc_log_init(&log)) 56 | exit(EXIT_FAILURE); 57 | 58 | c = lxc_container_new(my_args.name, my_args.lxcpath[0]); 59 | if (!c) { 60 | ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name); 61 | exit(EXIT_FAILURE); 62 | } 63 | 64 | if (my_args.rcfile) { 65 | c->clear_config(c); 66 | 67 | if (!c->load_config(c, my_args.rcfile)) { 68 | ERROR("Failed to load rcfile"); 69 | lxc_container_put(c); 70 | exit(EXIT_FAILURE); 71 | } 72 | 73 | c->configfile = strdup(my_args.rcfile); 74 | if (!c->configfile) { 75 | ERROR("Out of memory setting new config filename"); 76 | lxc_container_put(c); 77 | exit(EXIT_FAILURE); 78 | } 79 | } 80 | 81 | if (!c->may_control(c)) { 82 | ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name); 83 | lxc_container_put(c); 84 | exit(EXIT_FAILURE); 85 | } 86 | 87 | if (!c->freeze(c)) { 88 | ERROR("Failed to freeze %s:%s", my_args.lxcpath[0], my_args.name); 89 | lxc_container_put(c); 90 | exit(EXIT_FAILURE); 91 | } 92 | 93 | lxc_container_put(c); 94 | 95 | exit(EXIT_SUCCESS); 96 | } 97 | -------------------------------------------------------------------------------- /src/lxc/tools/lxc_unfreeze.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "lxc.h" 12 | 13 | #include "arguments.h" 14 | #include "log.h" 15 | 16 | lxc_log_define(lxc_unfreeze, lxc); 17 | 18 | static const struct option my_longopts[] = { 19 | LXC_COMMON_OPTIONS 20 | }; 21 | 22 | static struct lxc_arguments my_args = { 23 | .progname = "lxc-unfreeze", 24 | .help = "\ 25 | --name=NAME\n\ 26 | \n\ 27 | lxc-unfreeze unfreezes a container with the identifier NAME\n\ 28 | \n\ 29 | Options :\n\ 30 | -n, --name=NAME NAME of the container\n\ 31 | --rcfile=FILE Load configuration file FILE\n", 32 | .options = my_longopts, 33 | .parser = NULL, 34 | .checker = NULL, 35 | .log_priority = "ERROR", 36 | .log_file = "none", 37 | }; 38 | 39 | int __attribute__((weak, alias("lxc_unfreeze_main"))) main(int argc, char *argv[]); 40 | int lxc_unfreeze_main(int argc, char *argv[]) 41 | { 42 | struct lxc_container *c; 43 | struct lxc_log log; 44 | 45 | if (lxc_arguments_parse(&my_args, argc, argv)) 46 | exit(EXIT_FAILURE); 47 | 48 | log.name = my_args.name; 49 | log.file = my_args.log_file; 50 | log.level = my_args.log_priority; 51 | log.prefix = my_args.progname; 52 | log.quiet = my_args.quiet; 53 | log.lxcpath = my_args.lxcpath[0]; 54 | 55 | if (lxc_log_init(&log)) 56 | exit(EXIT_FAILURE); 57 | 58 | c = lxc_container_new(my_args.name, my_args.lxcpath[0]); 59 | if (!c) { 60 | ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name); 61 | exit(EXIT_FAILURE); 62 | } 63 | 64 | if (!c->may_control(c)) { 65 | ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name); 66 | lxc_container_put(c); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | if (my_args.rcfile) { 71 | c->clear_config(c); 72 | 73 | if (!c->load_config(c, my_args.rcfile)) { 74 | ERROR("Failed to load rcfile"); 75 | lxc_container_put(c); 76 | exit(EXIT_FAILURE); 77 | } 78 | 79 | c->configfile = strdup(my_args.rcfile); 80 | if (!c->configfile) { 81 | ERROR("Out of memory setting new config filename"); 82 | lxc_container_put(c); 83 | exit(EXIT_FAILURE); 84 | } 85 | } 86 | 87 | if (!c->unfreeze(c)) { 88 | ERROR("Failed to unfreeze %s:%s", my_args.lxcpath[0], my_args.name); 89 | lxc_container_put(c); 90 | exit(EXIT_FAILURE); 91 | } 92 | 93 | lxc_container_put(c); 94 | 95 | exit(EXIT_SUCCESS); 96 | } 97 | -------------------------------------------------------------------------------- /doc/ja/lxc-freeze.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | ]> 8 | 9 | 10 | 11 | @LXC_GENERATE_DATE@ 12 | 13 | 14 | lxc-freeze 15 | 1 16 | 17 | 18 | 19 | lxc-freeze 20 | 21 | 22 | 25 | コンテナ内のプロセス全ての凍結 26 | 27 | 28 | 29 | 30 | 31 | lxc-freeze 32 | -n name 33 | 34 | 35 | 36 | 37 | <!-- Description -->説明 38 | 39 | 40 | 47 | lxc-freeze は、コンテナ内部で実行中のプロセスを全て凍結します。 48 | プロセスは lxc-unfreeze コマンドによって明示的に解凍されるまでブロックされます。 49 | このコマンドはプロセスのグループをスケジューリングするバッチマネージャに便利なコマンドです。 50 | 51 | 52 | 53 | 54 | &commonoptions; 55 | 56 | 57 | <!-- Diagnostic -->診断 58 | 59 | 60 | 61 | 62 | The container was not found 63 | 64 | 65 | 69 | 指定したコンテナが lxc-create で作成されておらず存在しません。 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | &seealso; 80 | 81 | 82 | 83 | 99 | -------------------------------------------------------------------------------- /doc/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1+ 2 | 3 | if want_mans 4 | PAGES = [ 5 | ['lxc', '7'], 6 | ['lxc.conf', '5'], 7 | ['lxc.container.conf', '5'], 8 | ['lxc.system.conf', '5'], 9 | ['lxc-update-config', '1'], 10 | ['lxc-usernet', '5'], 11 | ['lxc-user-nic', '1'], 12 | ['lxc-usernsexec', '1'], 13 | ] 14 | 15 | if want_tools 16 | PAGES += [ 17 | ['lxc-attach', '1'], 18 | ['lxc-autostart', '1'], 19 | ['lxc-cgroup', '1'], 20 | ['lxc-checkconfig', '1'], 21 | ['lxc-checkpoint', '1'], 22 | ['lxc-config', '1'], 23 | ['lxc-console', '1'], 24 | ['lxc-copy', '1'], 25 | ['lxc-create', '1'], 26 | ['lxc-destroy', '1'], 27 | ['lxc-device', '1'], 28 | ['lxc-execute', '1'], 29 | ['lxc-freeze', '1'], 30 | ['lxc-info', '1'], 31 | ['lxc-ls', '1'], 32 | ['lxc-monitor', '1'], 33 | ['lxc-snapshot', '1'], 34 | ['lxc-start', '1'], 35 | ['lxc-stop', '1'], 36 | ['lxc-top', '1'], 37 | ['lxc-unfreeze', '1'], 38 | ['lxc-unshare', '1'], 39 | ['lxc-wait', '1'], 40 | ] 41 | endif 42 | 43 | if want_pam_cgroup 44 | PAGES += [ 45 | ['pam_cgfs', '8'], 46 | ] 47 | endif 48 | 49 | # Common files. 50 | configure_file( 51 | configuration: docconf, 52 | input: 'common_options.sgml.in', 53 | output: 'common_options.sgml') 54 | 55 | configure_file( 56 | configuration: docconf, 57 | input: 'see_also.sgml.in', 58 | output: 'see_also.sgml') 59 | 60 | # Initial templating. 61 | foreach page : PAGES 62 | sgml = configure_file( 63 | configuration: docconf, 64 | input: page[0] + '.sgml.in', 65 | output: page[0] + '.sgml') 66 | 67 | configure_file( 68 | input: sgml, 69 | output: page[0] + '.' + page[1], 70 | command: [sgml2man, '--encoding=UTF-8', page[0] + '.sgml'], 71 | install: true, 72 | install_dir: join_paths(mandir, 'man' + page[1])) 73 | endforeach 74 | endif 75 | 76 | # API Docs (Doxygen) 77 | if want_api_docs 78 | doxygen = find_program('doxygen', required: true) 79 | 80 | api_docs = custom_target( 81 | 'api-docs', 82 | input: files('api/Doxyfile'), 83 | output: 'api-docs.stamp', 84 | command: [doxygen, '@INPUT@'], 85 | build_by_default: true 86 | ) 87 | endif -------------------------------------------------------------------------------- /config/templates/common.conf.in: -------------------------------------------------------------------------------- 1 | # Default configuration shared by all containers 2 | 3 | # Setup the LXC devices in /dev/lxc/ 4 | lxc.tty.dir = lxc 5 | 6 | # Allow for 1024 pseudo terminals 7 | lxc.pty.max = 1024 8 | 9 | # Setup 4 tty devices 10 | lxc.tty.max = 4 11 | 12 | # Drop some harmful capabilities 13 | lxc.cap.drop = mac_admin mac_override sys_time sys_module sys_rawio 14 | 15 | # Ensure hostname is changed on clone 16 | lxc.hook.clone = @LXCHOOKDIR@/clonehostname 17 | 18 | # Default legacy cgroup configuration 19 | # 20 | # CGroup allowlist 21 | lxc.cgroup.devices.deny = a 22 | ## Allow any mknod (but not reading/writing the node) 23 | lxc.cgroup.devices.allow = c *:* m 24 | lxc.cgroup.devices.allow = b *:* m 25 | ## Allow specific devices 26 | ### /dev/null 27 | lxc.cgroup.devices.allow = c 1:3 rwm 28 | ### /dev/zero 29 | lxc.cgroup.devices.allow = c 1:5 rwm 30 | ### /dev/full 31 | lxc.cgroup.devices.allow = c 1:7 rwm 32 | ### /dev/tty 33 | lxc.cgroup.devices.allow = c 5:0 rwm 34 | ### /dev/console 35 | lxc.cgroup.devices.allow = c 5:1 rwm 36 | ### /dev/ptmx 37 | lxc.cgroup.devices.allow = c 5:2 rwm 38 | ### /dev/random 39 | lxc.cgroup.devices.allow = c 1:8 rwm 40 | ### /dev/urandom 41 | lxc.cgroup.devices.allow = c 1:9 rwm 42 | ### /dev/pts/* 43 | lxc.cgroup.devices.allow = c 136:* rwm 44 | ### fuse 45 | lxc.cgroup.devices.allow = c 10:229 rwm 46 | 47 | # Default unified cgroup configuration 48 | # 49 | # CGroup allowlist 50 | lxc.cgroup2.devices.deny = a 51 | ## Allow any mknod (but not reading/writing the node) 52 | lxc.cgroup2.devices.allow = c *:* m 53 | lxc.cgroup2.devices.allow = b *:* m 54 | ## Allow specific devices 55 | ### /dev/null 56 | lxc.cgroup2.devices.allow = c 1:3 rwm 57 | ### /dev/zero 58 | lxc.cgroup2.devices.allow = c 1:5 rwm 59 | ### /dev/full 60 | lxc.cgroup2.devices.allow = c 1:7 rwm 61 | ### /dev/tty 62 | lxc.cgroup2.devices.allow = c 5:0 rwm 63 | ### /dev/console 64 | lxc.cgroup2.devices.allow = c 5:1 rwm 65 | ### /dev/ptmx 66 | lxc.cgroup2.devices.allow = c 5:2 rwm 67 | ### /dev/random 68 | lxc.cgroup2.devices.allow = c 1:8 rwm 69 | ### /dev/urandom 70 | lxc.cgroup2.devices.allow = c 1:9 rwm 71 | ### /dev/pts/* 72 | lxc.cgroup2.devices.allow = c 136:* rwm 73 | ### fuse 74 | lxc.cgroup2.devices.allow = c 10:229 rwm 75 | 76 | # Setup the default mounts 77 | lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed 78 | lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none bind,optional 0 0 79 | 80 | # Block some syscalls which are not safe in privileged 81 | # containers 82 | lxc.seccomp.profile = @LXCTEMPLATECONFIG@/common.seccomp 83 | 84 | # Lastly, include all the configs from @LXCTEMPLATECONFIG@/common.conf.d/ 85 | lxc.include = @LXCTEMPLATECONFIG@/common.conf.d/ 86 | -------------------------------------------------------------------------------- /src/lxc/cgroups/cgroup2_devices.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | /* Parts of this taken from systemd's implementation. */ 4 | 5 | #ifndef __LXC_CGROUP2_DEVICES_H 6 | #define __LXC_CGROUP2_DEVICES_H 7 | 8 | #include "config.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "cgroup.h" 21 | #include "compiler.h" 22 | #include "conf.h" 23 | #include "list.h" 24 | #include "macro.h" 25 | #include "memory_utils.h" 26 | #include "syscall_numbers.h" 27 | 28 | #include "bpf.h" 29 | #include "bpf_common.h" 30 | 31 | #if !HAVE_BPF 32 | static inline int bpf_lxc(int cmd, union bpf_attr *attr, size_t size) 33 | { 34 | return syscall(__NR_bpf, cmd, attr, size); 35 | } 36 | #define bpf bpf_lxc 37 | #endif /* HAVE_BPF */ 38 | 39 | struct bpf_program { 40 | int device_list_type; 41 | int kernel_fd; 42 | __u32 prog_type; 43 | 44 | size_t n_instructions; 45 | struct bpf_insn *instructions; 46 | 47 | int fd_cgroup; 48 | int attached_type; 49 | __u32 attached_flags; 50 | }; 51 | 52 | __hidden extern struct bpf_program *bpf_program_new(__u32 prog_type); 53 | __hidden extern int bpf_program_init(struct bpf_program *prog); 54 | __hidden extern int bpf_program_append_device(struct bpf_program *prog, struct device_item *device); 55 | __hidden extern int bpf_program_finalize(struct bpf_program *prog); 56 | __hidden extern int bpf_program_cgroup_detach(struct bpf_program *prog); 57 | __hidden extern void bpf_device_program_free(struct cgroup_ops *ops); 58 | __hidden extern bool bpf_devices_cgroup_supported(void); 59 | 60 | /* 61 | * Note that bpf_list_add_device() returns 1 if it altered the device list and 62 | * 0 if it didn't; both return values indicate success. Only a negative return 63 | * value indicates an error. 64 | */ 65 | __hidden extern int bpf_list_add_device(struct bpf_devices *bpf_devices, 66 | struct device_item *device); 67 | __hidden extern bool bpf_cgroup_devices_attach(struct cgroup_ops *ops, 68 | struct bpf_devices *bpf_devices); 69 | __hidden extern bool bpf_cgroup_devices_update(struct cgroup_ops *ops, 70 | struct bpf_devices *bpf_devices, 71 | struct device_item *device); 72 | 73 | static inline void bpf_program_free(struct bpf_program *prog) 74 | { 75 | if (prog) { 76 | (void)bpf_program_cgroup_detach(prog); 77 | free(prog->instructions); 78 | free(prog); 79 | } 80 | } 81 | define_cleanup_function(struct bpf_program *, bpf_program_free); 82 | #define __do_bpf_program_free call_cleaner(bpf_program_free) 83 | 84 | #endif /* __LXC_CGROUP2_DEVICES_H */ 85 | -------------------------------------------------------------------------------- /src/tests/device_add_remove.c: -------------------------------------------------------------------------------- 1 | /* DEVICE_add_remove.c 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "lxctest.h" 14 | #include "memory_utils.h" 15 | #include "utils.h" 16 | 17 | #if !HAVE_STRLCPY 18 | #include "strlcpy.h" 19 | #endif 20 | 21 | #define NAME "device_add_remove_test" 22 | #define DEVICE "/dev/loop-control" 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | __do_close int fd_log = -EBADF; 27 | int ret = 1; 28 | struct lxc_log log = {}; 29 | struct lxc_container *c = NULL; 30 | char template[sizeof(P_tmpdir"/attach_XXXXXX")]; 31 | 32 | (void)strlcpy(template, P_tmpdir"/attach_XXXXXX", sizeof(template)); 33 | 34 | fd_log = lxc_make_tmpfile(template, false); 35 | if (fd_log < 0) { 36 | lxc_error("Failed to create temporary log file for container %s\n", NAME); 37 | exit(EXIT_FAILURE); 38 | } 39 | log.name = NAME; 40 | log.file = template; 41 | log.level = "TRACE"; 42 | log.prefix = "device_add_remove"; 43 | log.quiet = false; 44 | log.lxcpath = NULL; 45 | if (lxc_log_init(&log)) 46 | goto out; 47 | 48 | c = lxc_container_new(NAME, NULL); 49 | if (!c) { 50 | fprintf(stderr, "Unable to instantiate container (%s)...\n", NAME); 51 | goto out; 52 | } 53 | 54 | if (!c->create(c, "busybox", NULL, NULL, 1, NULL)) { 55 | fprintf(stderr, "Creating the container (%s) failed...\n", NAME); 56 | goto out; 57 | } 58 | 59 | c->want_daemonize(c, true); 60 | 61 | if (!c->start(c, false, NULL)) { 62 | fprintf(stderr, "Starting the container (%s) failed...\n", NAME); 63 | goto out; 64 | } 65 | 66 | if (!c->add_device_node(c, DEVICE, DEVICE)) { 67 | fprintf(stderr, "Adding %s to the container (%s) failed...\n", DEVICE, NAME); 68 | goto out; 69 | } 70 | 71 | if (!c->remove_device_node(c, DEVICE, DEVICE)) { 72 | fprintf(stderr, "Removing %s from the container (%s) failed...\n", DEVICE, NAME); 73 | goto out; 74 | } 75 | 76 | if (!c->stop(c)) { 77 | fprintf(stderr, "Stopping the container (%s) failed...\n", NAME); 78 | goto out; 79 | } 80 | 81 | if (!c->destroy(c)) { 82 | fprintf(stderr, "Destroying the container (%s) failed...\n", NAME); 83 | goto out; 84 | } 85 | 86 | ret = 0; 87 | 88 | out: 89 | if (ret != 0) { 90 | char buf[4096]; 91 | ssize_t buflen; 92 | while ((buflen = read(fd_log, buf, 1024)) > 0) { 93 | buflen = write(STDERR_FILENO, buf, buflen); 94 | if (buflen <= 0) 95 | break; 96 | } 97 | } 98 | (void)unlink(template); 99 | 100 | if (c) 101 | lxc_container_put(c); 102 | return ret; 103 | } 104 | -------------------------------------------------------------------------------- /src/lxc/monitor.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ 2 | 3 | #ifndef __LXC_MONITOR_H 4 | #define __LXC_MONITOR_H 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "compiler.h" 14 | 15 | typedef enum { 16 | lxc_msg_state, 17 | lxc_msg_priority, 18 | lxc_msg_exit_code, 19 | } lxc_msg_type_t; 20 | 21 | struct lxc_msg { 22 | lxc_msg_type_t type; 23 | char name[NAME_MAX + 1]; 24 | int value; 25 | }; 26 | 27 | __hidden extern int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr); 28 | __hidden extern int lxc_monitor_fifo_name(const char *lxcpath, char *fifo_path, size_t fifo_path_sz, 29 | int do_mkdirp); 30 | __hidden extern void lxc_monitor_send_state(const char *name, lxc_state_t state, const char *lxcpath); 31 | __hidden extern void lxc_monitor_send_exit_code(const char *name, int exit_code, const char *lxcpath); 32 | __hidden extern int lxc_monitord_spawn(const char *lxcpath); 33 | 34 | /* 35 | * Open the monitoring mechanism for a specific container 36 | * The function will return an fd corresponding to the events 37 | * Returns a file descriptor on success, < 0 otherwise 38 | */ 39 | __hidden extern int lxc_monitor_open(const char *lxcpath); 40 | 41 | /* 42 | * Blocking read for the next container state change 43 | * @fd : the file descriptor provided by lxc_monitor_open 44 | * @msg : the variable which will be filled with the state 45 | * Returns 0 if the monitored container has exited, > 0 if 46 | * data was read, < 0 otherwise 47 | */ 48 | __hidden extern int lxc_monitor_read(int fd, struct lxc_msg *msg); 49 | 50 | /* 51 | * Blocking read for the next container state change with timeout 52 | * @fd : the file descriptor provided by lxc_monitor_open 53 | * @msg : the variable which will be filled with the state 54 | * @timeout : the timeout in seconds to wait for a state change 55 | * Returns 0 if the monitored container has exited, > 0 if 56 | * data was read, < 0 otherwise 57 | */ 58 | __hidden extern int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout); 59 | 60 | /* 61 | * Blocking read from multiple monitors for the next container state 62 | * change with timeout 63 | * @fds : struct pollfd describing the fds to use 64 | * @nfds : the number of entries in fds 65 | * @msg : the variable which will be filled with the state 66 | * @timeout : the timeout in seconds to wait for a state change 67 | * Returns 0 if the monitored container has exited, > 0 if 68 | * data was read, < 0 otherwise 69 | */ 70 | __hidden extern int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds, struct lxc_msg *msg, 71 | int timeout); 72 | 73 | #endif /* __LXC_MONITOR_H */ 74 | -------------------------------------------------------------------------------- /src/tests/criu_check_feature.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | #include 11 | 12 | #include "lxc/lxccontainer.h" 13 | #include "lxctest.h" 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | struct lxc_container *c; 18 | struct migrate_opts m_opts; 19 | int ret = EXIT_FAILURE; 20 | 21 | /* Test the feature check interface, 22 | * we actually do not need a container. */ 23 | c = lxc_container_new("check_feature", NULL); 24 | if (!c) { 25 | lxc_error("%s", "Failed to create container \"check_feature\""); 26 | exit(ret); 27 | } 28 | 29 | if (c->is_defined(c)) { 30 | lxc_error("%s\n", "Container \"check_feature\" is defined"); 31 | goto on_error_put; 32 | } 33 | 34 | /* check the migrate API call with wrong 'cmd' */ 35 | if (!c->migrate(c, UINT_MAX, &m_opts, sizeof(struct migrate_opts))) { 36 | /* This should failed */ 37 | lxc_error("%s\n", "Migrate API calls with command UINT_MAX did not fail"); 38 | goto on_error_put; 39 | } 40 | 41 | /* do the actual feature check for memory tracking */ 42 | m_opts.features_to_check = FEATURE_MEM_TRACK; 43 | if (c->migrate(c, MIGRATE_FEATURE_CHECK, &m_opts, sizeof(struct migrate_opts))) { 44 | lxc_debug("%s\n", "System does not support \"FEATURE_MEM_TRACK\"."); 45 | } 46 | 47 | /* check for lazy pages */ 48 | m_opts.features_to_check = FEATURE_LAZY_PAGES; 49 | if (c->migrate(c, MIGRATE_FEATURE_CHECK, &m_opts, sizeof(struct migrate_opts))) { 50 | lxc_debug("%s\n", "System does not support \"FEATURE_LAZY_PAGES\"."); 51 | } 52 | 53 | /* check for lazy pages and memory tracking */ 54 | m_opts.features_to_check = FEATURE_LAZY_PAGES | FEATURE_MEM_TRACK; 55 | if (c->migrate(c, MIGRATE_FEATURE_CHECK, &m_opts, sizeof(struct migrate_opts))) { 56 | if (m_opts.features_to_check == FEATURE_LAZY_PAGES) 57 | lxc_debug("%s\n", "System does not support \"FEATURE_MEM_TRACK\""); 58 | else if (m_opts.features_to_check == FEATURE_MEM_TRACK) 59 | lxc_debug("%s\n", "System does not support \"FEATURE_LAZY_PAGES\""); 60 | else 61 | lxc_debug("%s\n", "System does not support \"FEATURE_MEM_TRACK\" " 62 | "and \"FEATURE_LAZY_PAGES\""); 63 | } 64 | 65 | /* test for unknown feature; once there are 64 features to test 66 | * this will be valid... */ 67 | m_opts.features_to_check = -1ULL; 68 | if (!c->migrate(c, MIGRATE_FEATURE_CHECK, &m_opts, sizeof(struct migrate_opts))) { 69 | lxc_error("%s\n", "Unsupported feature supported, which is strange."); 70 | goto on_error_put; 71 | } 72 | 73 | ret = EXIT_SUCCESS; 74 | 75 | on_error_put: 76 | lxc_container_put(c); 77 | if (ret == EXIT_SUCCESS) 78 | lxc_debug("%s\n", "All criu feature check tests passed"); 79 | 80 | exit(ret); 81 | } 82 | -------------------------------------------------------------------------------- /src/tests/saveconfig.c: -------------------------------------------------------------------------------- 1 | /* liblxcapi 2 | * 3 | * SPDX-License-Identifier: GPL-2.0-only 4 | * 5 | */ 6 | 7 | #include "config.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define MYNAME "lxctest1" 20 | 21 | static int create_container(void) 22 | { 23 | int status, ret; 24 | pid_t pid = fork(); 25 | 26 | if (pid < 0) { 27 | perror("fork"); 28 | return -1; 29 | } 30 | 31 | if (pid == 0) { 32 | execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | again: 37 | ret = waitpid(pid, &status, 0); 38 | if (ret == -1) { 39 | if (errno == EINTR) 40 | goto again; 41 | 42 | perror("waitpid"); 43 | return -1; 44 | } 45 | 46 | if (ret != pid) 47 | goto again; 48 | 49 | if (!WIFEXITED(status)) { // did not exit normally 50 | fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__); 51 | return -1; 52 | } 53 | 54 | return WEXITSTATUS(status); 55 | } 56 | 57 | int main(int argc, char *argv[]) 58 | { 59 | struct lxc_container *c; 60 | int ret = 1; 61 | 62 | if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { 63 | fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); 64 | ret = 1; 65 | goto out; 66 | } 67 | 68 | if (c->is_defined(c)) { 69 | fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); 70 | goto out; 71 | } 72 | 73 | if (create_container()) { 74 | fprintf(stderr, "%d: failed to create a container\n", __LINE__); 75 | goto out; 76 | } 77 | 78 | if (!c->is_defined(c)) { 79 | fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); 80 | goto out; 81 | } 82 | 83 | c->load_config(c, NULL); 84 | unlink("/tmp/lxctest1"); 85 | if (!c->save_config(c, "/tmp/lxctest1")) { 86 | fprintf(stderr, "%d: failed writing config file /tmp/lxctest1\n", __LINE__); 87 | goto out; 88 | } 89 | 90 | rename(LXCPATH "/" MYNAME "/config", LXCPATH "/" MYNAME "/config.bak"); 91 | if (!c->save_config(c, NULL)) { 92 | fprintf(stderr, "%d: failed writing config file\n", __LINE__); 93 | goto out; 94 | } 95 | 96 | if (!c->destroy(c)) { 97 | fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); 98 | goto out; 99 | } 100 | 101 | if (c->is_defined(c)) { 102 | fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); 103 | goto out; 104 | } 105 | 106 | fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); 107 | ret = 0; 108 | 109 | out: 110 | lxc_container_put(c); 111 | exit(ret); 112 | } 113 | -------------------------------------------------------------------------------- /doc/ko/lxc-freeze.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | ]> 8 | 9 | 10 | 11 | @LXC_GENERATE_DATE@ 12 | 13 | 14 | lxc-freeze 15 | 1 16 | 17 | 18 | 19 | lxc-freeze 20 | 21 | 22 | 25 | 컨테이너의 모든 프로세스를 동결 26 | 27 | 28 | 29 | 30 | 31 | lxc-freeze 32 | -n name 33 | 34 | 35 | 36 | 37 | <!-- Description -->설명 38 | 39 | 40 | 47 | lxc-freeze는 컨테이너 내부에서 실행되는 모든 프로세스를 동결시킨다. 48 | 프로세스는 lxc-unfreeze 명령어를 이용하여 명시적으로 동결 해제시킬 때까지 블로킹 된다. 49 | 이 명령어는 프로세스 그룹들을 스케줄링하여 일괄처리하는 데 유용하다. 50 | 51 | 52 | 53 | 54 | &commonoptions; 55 | 56 | 57 | <!-- Diagnostic -->진단 58 | 59 | 60 | 61 | 62 | The container was not found 63 | 64 | 65 | 69 | 지정한 컨테이너가 lxc-create로 생성된 적이 없다. 70 | 컨테이너가 존재하지 않는다. 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | &seealso; 81 | 82 | 83 | 84 | 100 | -------------------------------------------------------------------------------- /doc/see_also.sgml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | See Also 5 | 6 | 7 | 8 | lxc 9 | 7 10 | , 11 | 12 | 13 | lxc-create 14 | 1 15 | , 16 | 17 | 18 | lxc-copy 19 | 1 20 | , 21 | 22 | 23 | lxc-destroy 24 | 1 25 | , 26 | 27 | 28 | lxc-start 29 | 1 30 | , 31 | 32 | 33 | lxc-stop 34 | 1 35 | , 36 | 37 | 38 | lxc-execute 39 | 1 40 | , 41 | 42 | 43 | lxc-console 44 | 1 45 | , 46 | 47 | 48 | lxc-monitor 49 | 1 50 | , 51 | 52 | 53 | lxc-wait 54 | 1 55 | , 56 | 57 | 58 | lxc-cgroup 59 | 1 60 | , 61 | 62 | 63 | lxc-ls 64 | 1 65 | , 66 | 67 | 68 | lxc-info 69 | 1 70 | , 71 | 72 | 73 | lxc-freeze 74 | 1 75 | , 76 | 77 | 78 | lxc-unfreeze 79 | 1 80 | , 81 | 82 | 83 | lxc-attach 84 | 1 85 | , 86 | 87 | 88 | lxc.conf 89 | 5 90 | 91 | 92 | 93 | 94 | 95 | 96 | --------------------------------------------------------------------------------