"Fossies" - the Fresh Open Source Software Archive

Member "lxc-4.0.10/src/lxc/lsm/apparmor.c" (16 Jul 2021, 37635 Bytes) of package /linux/misc/lxc-4.0.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "apparmor.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.0.9_vs_4.0.10.

    1 /* SPDX-License-Identifier: LGPL-2.1+ */
    2 
    3 #ifndef _GNU_SOURCE
    4 #define _GNU_SOURCE 1
    5 #endif
    6 #include <errno.h>
    7 #include <stdio.h>
    8 #include <stdlib.h>
    9 #include <sys/mount.h>
   10 #include <sys/stat.h>
   11 #include <sys/types.h>
   12 #include <sys/vfs.h>
   13 #include <unistd.h>
   14 
   15 #include "caps.h"
   16 #include "cgroups/cgroup_utils.h"
   17 #include "conf.h"
   18 #include "config.h"
   19 #include "initutils.h"
   20 #include "file_utils.h"
   21 #include "log.h"
   22 #include "lsm.h"
   23 #include "parse.h"
   24 #include "process_utils.h"
   25 #include "utils.h"
   26 
   27 lxc_log_define(apparmor, lsm);
   28 
   29 #define AA_DEF_PROFILE "lxc-container-default"
   30 #define AA_DEF_PROFILE_CGNS "lxc-container-default-cgns"
   31 #define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask"
   32 #define AA_ENABLED_FILE "/sys/module/apparmor/parameters/enabled"
   33 #define AA_UNCHANGED "unchanged"
   34 #define AA_GENERATED "generated"
   35 
   36 #define AA_CMD_LOAD   'r'
   37 #define AA_CMD_UNLOAD 'R'
   38 #define AA_CMD_PARSE  'Q'
   39 
   40 static const char AA_PROFILE_BASE[] =
   41 "  ### Base profile\n"
   42 "  capability,\n"
   43 "  dbus,\n"
   44 "  file,\n"
   45 "  network,\n"
   46 "  umount,\n"
   47 "\n"
   48 "  # Allow us to receive signals from anywhere.\n"
   49 "  signal (receive),\n"
   50 "\n"
   51 "  # Allow us to send signals to ourselves\n"
   52 "  signal peer=@{profile_name},\n"
   53 "\n"
   54 "  # Allow other processes to read our /proc entries, futexes, perf tracing and\n"
   55 "  # kcmp for now (they will need 'read' in the first place). Administrators can\n"
   56 "  # override with:\n"
   57 "  #   deny ptrace (readby) ...\n"
   58 "  ptrace (readby),\n"
   59 "\n"
   60 "  # Allow other processes to trace us by default (they will need 'trace' in\n"
   61 "  # the first place). Administrators can override with:\n"
   62 "  #   deny ptrace (tracedby) ...\n"
   63 "  ptrace (tracedby),\n"
   64 "\n"
   65 "  # Allow us to ptrace ourselves\n"
   66 "  ptrace peer=@{profile_name},\n"
   67 "\n"
   68 "  # ignore DENIED message on / remount\n"
   69 "  deny mount options=(ro, remount) -> /,\n"
   70 "  deny mount options=(ro, remount, silent) -> /,\n"
   71 "\n"
   72 "  # allow tmpfs mounts everywhere\n"
   73 "  mount fstype=tmpfs,\n"
   74 "\n"
   75 "  # allow hugetlbfs mounts everywhere\n"
   76 "  mount fstype=hugetlbfs,\n"
   77 "\n"
   78 "  # allow mqueue mounts everywhere\n"
   79 "  mount fstype=mqueue,\n"
   80 "\n"
   81 "  # allow fuse mounts everywhere\n"
   82 "  mount fstype=fuse,\n"
   83 "  mount fstype=fuse.*,\n"
   84 "\n"
   85 "  # deny access under /proc/bus to avoid e.g. messing with pci devices directly\n"
   86 "  deny @{PROC}/bus/** wklx,\n"
   87 "\n"
   88 "  # deny writes in /proc/sys/fs but allow binfmt_misc to be mounted\n"
   89 "  mount fstype=binfmt_misc -> /proc/sys/fs/binfmt_misc/,\n"
   90 "  deny @{PROC}/sys/fs/** wklx,\n"
   91 "\n"
   92 "  # allow efivars to be mounted, writing to it will be blocked though\n"
   93 "  mount fstype=efivarfs -> /sys/firmware/efi/efivars/,\n"
   94 "\n"
   95 "  # block some other dangerous paths\n"
   96 "  deny @{PROC}/kcore rwklx,\n"
   97 "  deny @{PROC}/sysrq-trigger rwklx,\n"
   98 "  deny @{PROC}/acpi/** rwklx,\n"
   99 "\n"
  100 "  # deny writes in /sys except for /sys/fs/cgroup, also allow\n"
  101 "  # fusectl, securityfs and debugfs to be mounted there (read-only)\n"
  102 "  mount fstype=fusectl -> /sys/fs/fuse/connections/,\n"
  103 "  mount fstype=securityfs -> /sys/kernel/security/,\n"
  104 "  mount fstype=debugfs -> /sys/kernel/debug/,\n"
  105 "  deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,\n"
  106 "  mount fstype=proc -> /proc/,\n"
  107 "  mount fstype=sysfs -> /sys/,\n"
  108 "  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,\n"
  109 "  deny /sys/firmware/efi/efivars/** rwklx,\n"
  110 "  # note, /sys/kernel/security/** handled below\n"
  111 "  mount options=(ro, nosuid, nodev, noexec, remount, strictatime) -> /sys/fs/cgroup/,\n"
  112 "\n"
  113 "  # deny reads from debugfs\n"
  114 "  deny /sys/kernel/debug/{,**} rwklx,\n"
  115 "\n"
  116 "  # allow paths to be made dependent, shared, private or unbindable\n"
  117 "  # TODO: This currently doesn't work due to the apparmor parser treating those as allowing all mounts.\n"
  118 "#  mount options=(rw,make-slave) -> **,\n"
  119 "#  mount options=(rw,make-rslave) -> **,\n"
  120 "#  mount options=(rw,make-shared) -> **,\n"
  121 "#  mount options=(rw,make-rshared) -> **,\n"
  122 "#  mount options=(rw,make-private) -> **,\n"
  123 "#  mount options=(rw,make-rprivate) -> **,\n"
  124 "#  mount options=(rw,make-unbindable) -> **,\n"
  125 "#  mount options=(rw,make-runbindable) -> **,\n"
  126 "\n"
  127 "# Allow limited modification of mount propagation\n"
  128 "  mount options=(rw,make-slave) -> /,\n"
  129 "  mount options=(rw,make-rslave) -> /,\n"
  130 "  mount options=(rw,make-shared) -> /,\n"
  131 "  mount options=(rw,make-rshared) -> /,\n"
  132 "  mount options=(rw,make-private) -> /,\n"
  133 "  mount options=(rw,make-rprivate) -> /,\n"
  134 "  mount options=(rw,make-unbindable) -> /,\n"
  135 "  mount options=(rw,make-runbindable) -> /,\n"
  136 "\n"
  137 "  # allow bind-mounts of anything except /proc, /sys and /dev\n"
  138 "  mount options=(rw,bind) /[^spd]*{,/**},\n"
  139 "  mount options=(rw,bind) /d[^e]*{,/**},\n"
  140 "  mount options=(rw,bind) /de[^v]*{,/**},\n"
  141 "  mount options=(rw,bind) /dev/.[^l]*{,/**},\n"
  142 "  mount options=(rw,bind) /dev/.l[^x]*{,/**},\n"
  143 "  mount options=(rw,bind) /dev/.lx[^c]*{,/**},\n"
  144 "  mount options=(rw,bind) /dev/.lxc?*{,/**},\n"
  145 "  mount options=(rw,bind) /dev/[^.]*{,/**},\n"
  146 "  mount options=(rw,bind) /dev?*{,/**},\n"
  147 "  mount options=(rw,bind) /p[^r]*{,/**},\n"
  148 "  mount options=(rw,bind) /pr[^o]*{,/**},\n"
  149 "  mount options=(rw,bind) /pro[^c]*{,/**},\n"
  150 "  mount options=(rw,bind) /proc?*{,/**},\n"
  151 "  mount options=(rw,bind) /s[^y]*{,/**},\n"
  152 "  mount options=(rw,bind) /sy[^s]*{,/**},\n"
  153 "  mount options=(rw,bind) /sys?*{,/**},\n"
  154 "\n"
  155 "  # Allow rbind-mounts of anything except /, /dev, /proc and /sys\n"
  156 "  mount options=(rw,rbind) /[^spd]*{,/**},\n"
  157 "  mount options=(rw,rbind) /d[^e]*{,/**},\n"
  158 "  mount options=(rw,rbind) /de[^v]*{,/**},\n"
  159 "  mount options=(rw,rbind) /dev?*{,/**},\n"
  160 "  mount options=(rw,rbind) /p[^r]*{,/**},\n"
  161 "  mount options=(rw,rbind) /pr[^o]*{,/**},\n"
  162 "  mount options=(rw,rbind) /pro[^c]*{,/**},\n"
  163 "  mount options=(rw,rbind) /proc?*{,/**},\n"
  164 "  mount options=(rw,rbind) /s[^y]*{,/**},\n"
  165 "  mount options=(rw,rbind) /sy[^s]*{,/**},\n"
  166 "  mount options=(rw,rbind) /sys?*{,/**},\n"
  167 "\n"
  168 "  # allow moving mounts except for /proc, /sys and /dev\n"
  169 "  mount options=(rw,move) /[^spd]*{,/**},\n"
  170 "  mount options=(rw,move) /d[^e]*{,/**},\n"
  171 "  mount options=(rw,move) /de[^v]*{,/**},\n"
  172 "  mount options=(rw,move) /dev/.[^l]*{,/**},\n"
  173 "  mount options=(rw,move) /dev/.l[^x]*{,/**},\n"
  174 "  mount options=(rw,move) /dev/.lx[^c]*{,/**},\n"
  175 "  mount options=(rw,move) /dev/.lxc?*{,/**},\n"
  176 "  mount options=(rw,move) /dev/[^.]*{,/**},\n"
  177 "  mount options=(rw,move) /dev?*{,/**},\n"
  178 "  mount options=(rw,move) /p[^r]*{,/**},\n"
  179 "  mount options=(rw,move) /pr[^o]*{,/**},\n"
  180 "  mount options=(rw,move) /pro[^c]*{,/**},\n"
  181 "  mount options=(rw,move) /proc?*{,/**},\n"
  182 "  mount options=(rw,move) /s[^y]*{,/**},\n"
  183 "  mount options=(rw,move) /sy[^s]*{,/**},\n"
  184 "  mount options=(rw,move) /sys?*{,/**},\n"
  185 "\n"
  186 "  # generated by: lxc-generate-aa-rules.py container-rules.base\n"
  187 "  deny /proc/sys/[^kn]*{,/**} wklx,\n"
  188 "  deny /proc/sys/k[^e]*{,/**} wklx,\n"
  189 "  deny /proc/sys/ke[^r]*{,/**} wklx,\n"
  190 "  deny /proc/sys/ker[^n]*{,/**} wklx,\n"
  191 "  deny /proc/sys/kern[^e]*{,/**} wklx,\n"
  192 "  deny /proc/sys/kerne[^l]*{,/**} wklx,\n"
  193 "  deny /proc/sys/kernel/[^smhd]*{,/**} wklx,\n"
  194 "  deny /proc/sys/kernel/d[^o]*{,/**} wklx,\n"
  195 "  deny /proc/sys/kernel/do[^m]*{,/**} wklx,\n"
  196 "  deny /proc/sys/kernel/dom[^a]*{,/**} wklx,\n"
  197 "  deny /proc/sys/kernel/doma[^i]*{,/**} wklx,\n"
  198 "  deny /proc/sys/kernel/domai[^n]*{,/**} wklx,\n"
  199 "  deny /proc/sys/kernel/domain[^n]*{,/**} wklx,\n"
  200 "  deny /proc/sys/kernel/domainn[^a]*{,/**} wklx,\n"
  201 "  deny /proc/sys/kernel/domainna[^m]*{,/**} wklx,\n"
  202 "  deny /proc/sys/kernel/domainnam[^e]*{,/**} wklx,\n"
  203 "  deny /proc/sys/kernel/domainname?*{,/**} wklx,\n"
  204 "  deny /proc/sys/kernel/h[^o]*{,/**} wklx,\n"
  205 "  deny /proc/sys/kernel/ho[^s]*{,/**} wklx,\n"
  206 "  deny /proc/sys/kernel/hos[^t]*{,/**} wklx,\n"
  207 "  deny /proc/sys/kernel/host[^n]*{,/**} wklx,\n"
  208 "  deny /proc/sys/kernel/hostn[^a]*{,/**} wklx,\n"
  209 "  deny /proc/sys/kernel/hostna[^m]*{,/**} wklx,\n"
  210 "  deny /proc/sys/kernel/hostnam[^e]*{,/**} wklx,\n"
  211 "  deny /proc/sys/kernel/hostname?*{,/**} wklx,\n"
  212 "  deny /proc/sys/kernel/m[^s]*{,/**} wklx,\n"
  213 "  deny /proc/sys/kernel/ms[^g]*{,/**} wklx,\n"
  214 "  deny /proc/sys/kernel/msg*/** wklx,\n"
  215 "  deny /proc/sys/kernel/s[^he]*{,/**} wklx,\n"
  216 "  deny /proc/sys/kernel/se[^m]*{,/**} wklx,\n"
  217 "  deny /proc/sys/kernel/sem*/** wklx,\n"
  218 "  deny /proc/sys/kernel/sh[^m]*{,/**} wklx,\n"
  219 "  deny /proc/sys/kernel/shm*/** wklx,\n"
  220 "  deny /proc/sys/kernel?*{,/**} wklx,\n"
  221 "  deny /proc/sys/n[^e]*{,/**} wklx,\n"
  222 "  deny /proc/sys/ne[^t]*{,/**} wklx,\n"
  223 "  deny /proc/sys/net?*{,/**} wklx,\n"
  224 "  deny /sys/[^fdck]*{,/**} wklx,\n"
  225 "  deny /sys/c[^l]*{,/**} wklx,\n"
  226 "  deny /sys/cl[^a]*{,/**} wklx,\n"
  227 "  deny /sys/cla[^s]*{,/**} wklx,\n"
  228 "  deny /sys/clas[^s]*{,/**} wklx,\n"
  229 "  deny /sys/class/[^n]*{,/**} wklx,\n"
  230 "  deny /sys/class/n[^e]*{,/**} wklx,\n"
  231 "  deny /sys/class/ne[^t]*{,/**} wklx,\n"
  232 "  deny /sys/class/net?*{,/**} wklx,\n"
  233 "  deny /sys/class?*{,/**} wklx,\n"
  234 "  deny /sys/d[^e]*{,/**} wklx,\n"
  235 "  deny /sys/de[^v]*{,/**} wklx,\n"
  236 "  deny /sys/dev[^i]*{,/**} wklx,\n"
  237 "  deny /sys/devi[^c]*{,/**} wklx,\n"
  238 "  deny /sys/devic[^e]*{,/**} wklx,\n"
  239 "  deny /sys/device[^s]*{,/**} wklx,\n"
  240 "  deny /sys/devices/[^v]*{,/**} wklx,\n"
  241 "  deny /sys/devices/v[^i]*{,/**} wklx,\n"
  242 "  deny /sys/devices/vi[^r]*{,/**} wklx,\n"
  243 "  deny /sys/devices/vir[^t]*{,/**} wklx,\n"
  244 "  deny /sys/devices/virt[^u]*{,/**} wklx,\n"
  245 "  deny /sys/devices/virtu[^a]*{,/**} wklx,\n"
  246 "  deny /sys/devices/virtua[^l]*{,/**} wklx,\n"
  247 "  deny /sys/devices/virtual/[^n]*{,/**} wklx,\n"
  248 "  deny /sys/devices/virtual/n[^e]*{,/**} wklx,\n"
  249 "  deny /sys/devices/virtual/ne[^t]*{,/**} wklx,\n"
  250 "  deny /sys/devices/virtual/net?*{,/**} wklx,\n"
  251 "  deny /sys/devices/virtual?*{,/**} wklx,\n"
  252 "  deny /sys/devices?*{,/**} wklx,\n"
  253 "  deny /sys/f[^s]*{,/**} wklx,\n"
  254 "  deny /sys/fs/[^c]*{,/**} wklx,\n"
  255 "  deny /sys/fs/c[^g]*{,/**} wklx,\n"
  256 "  deny /sys/fs/cg[^r]*{,/**} wklx,\n"
  257 "  deny /sys/fs/cgr[^o]*{,/**} wklx,\n"
  258 "  deny /sys/fs/cgro[^u]*{,/**} wklx,\n"
  259 "  deny /sys/fs/cgrou[^p]*{,/**} wklx,\n"
  260 "  deny /sys/fs/cgroup?*{,/**} wklx,\n"
  261 "  deny /sys/fs?*{,/**} wklx,\n"
  262 ;
  263 
  264 static const char AA_PROFILE_UNIX_SOCKETS[] =
  265 "\n"
  266 "  ### Feature: unix\n"
  267 "  # Allow receive via unix sockets from anywhere\n"
  268 "  unix (receive),\n"
  269 "\n"
  270 "  # Allow all unix sockets in the container\n"
  271 "  unix peer=(label=@{profile_name}),\n"
  272 ;
  273 
  274 static const char AA_PROFILE_CGROUP_NAMESPACES[] =
  275 "\n"
  276 "  ### Feature: cgroup namespace\n"
  277 "  mount fstype=cgroup -> /sys/fs/cgroup/**,\n"
  278 "  mount fstype=cgroup2 -> /sys/fs/cgroup/**,\n"
  279 ;
  280 
  281 /* '_BASE' because we still need to append generated change_profile rules */
  282 static const char AA_PROFILE_STACKING_BASE[] =
  283 "\n"
  284 "  ### Feature: apparmor stacking\n"
  285 "  ### Configuration: apparmor profile loading (in namespace)\n"
  286 "  deny /sys/k[^e]*{,/**} wklx,\n"
  287 "  deny /sys/ke[^r]*{,/**} wklx,\n"
  288 "  deny /sys/ker[^n]*{,/**} wklx,\n"
  289 "  deny /sys/kern[^e]*{,/**} wklx,\n"
  290 "  deny /sys/kerne[^l]*{,/**} wklx,\n"
  291 "  deny /sys/kernel/[^s]*{,/**} wklx,\n"
  292 "  deny /sys/kernel/s[^e]*{,/**} wklx,\n"
  293 "  deny /sys/kernel/se[^c]*{,/**} wklx,\n"
  294 "  deny /sys/kernel/sec[^u]*{,/**} wklx,\n"
  295 "  deny /sys/kernel/secu[^r]*{,/**} wklx,\n"
  296 "  deny /sys/kernel/secur[^i]*{,/**} wklx,\n"
  297 "  deny /sys/kernel/securi[^t]*{,/**} wklx,\n"
  298 "  deny /sys/kernel/securit[^y]*{,/**} wklx,\n"
  299 "  deny /sys/kernel/security/[^a]*{,/**} wklx,\n"
  300 "  deny /sys/kernel/security/a[^p]*{,/**} wklx,\n"
  301 "  deny /sys/kernel/security/ap[^p]*{,/**} wklx,\n"
  302 "  deny /sys/kernel/security/app[^a]*{,/**} wklx,\n"
  303 "  deny /sys/kernel/security/appa[^r]*{,/**} wklx,\n"
  304 "  deny /sys/kernel/security/appar[^m]*{,/**} wklx,\n"
  305 "  deny /sys/kernel/security/apparm[^o]*{,/**} wklx,\n"
  306 "  deny /sys/kernel/security/apparmo[^r]*{,/**} wklx,\n"
  307 "  deny /sys/kernel/security/apparmor?*{,/**} wklx,\n"
  308 "  deny /sys/kernel/security?*{,/**} wklx,\n"
  309 "  deny /sys/kernel?*{,/**} wklx,\n"
  310 ;
  311 
  312 static const char AA_PROFILE_NO_STACKING[] =
  313 "\n"
  314 "  ### Feature: apparmor stacking (not present)\n"
  315 "  deny /sys/k*{,/**} rwklx,\n"
  316 ;
  317 
  318 /* '_BASE' because we need to append change_profile for stacking */
  319 static const char AA_PROFILE_NESTING_BASE[] =
  320 "\n"
  321 "  ### Configuration: nesting\n"
  322 "  pivot_root,\n"
  323 "  ptrace,\n"
  324 "  signal,\n"
  325 "\n"
  326    /* NOTE: See conf.c's "nesting_helpers" for details. */
  327 "  deny /dev/.lxc/proc/** rw,\n"
  328 "  deny /dev/.lxc/sys/** rw,\n"
  329 "\n"
  330 "  mount fstype=proc -> /usr/lib/*/lxc/**,\n"
  331 "  mount fstype=sysfs -> /usr/lib/*/lxc/**,\n"
  332 "\n"
  333 "  # Allow nested LXD\n"
  334 "  mount none -> /var/lib/lxd/shmounts/,\n"
  335 "  mount /var/lib/lxd/shmounts/ -> /var/lib/lxd/shmounts/,\n"
  336 "  mount options=bind /var/lib/lxd/shmounts/** -> /var/lib/lxd/**,\n"
  337 "\n"
  338 "  # TODO: There doesn't seem to be a way to ask for:\n"
  339 "  # mount options=(ro,nosuid,nodev,noexec,remount,bind),\n"
  340 "  # as we always get mount to $cdir/proc/sys with those flags denied\n"
  341 "  # So allow all mounts until that is straightened out:\n"
  342 "  mount,\n"
  343 ;
  344 
  345 static const char AA_PROFILE_UNPRIVILEGED[] =
  346 "\n"
  347 "  ### Configuration: unprivileged container\n"
  348 "  pivot_root,\n"
  349 "\n"
  350 "  # Allow modifying mount propagation\n"
  351 "  mount options=(rw,make-slave) -> **,\n"
  352 "  mount options=(rw,make-rslave) -> **,\n"
  353 "  mount options=(rw,make-shared) -> **,\n"
  354 "  mount options=(rw,make-rshared) -> **,\n"
  355 "  mount options=(rw,make-private) -> **,\n"
  356 "  mount options=(rw,make-rprivate) -> **,\n"
  357 "  mount options=(rw,make-unbindable) -> **,\n"
  358 "  mount options=(rw,make-runbindable) -> **,\n"
  359 "\n"
  360 "  # Allow all bind-mounts\n"
  361 "  mount options=(rw,bind),\n"
  362 "  mount options=(rw,rbind),\n"
  363 "\n"
  364 "  # Allow remounting things read-only\n"
  365 "  mount options=(ro,remount),\n"
  366 ;
  367 
  368 static void load_mount_features_enabled(struct lsm_ops *ops)
  369 {
  370     struct stat statbuf;
  371     int ret;
  372 
  373     ret = stat(AA_MOUNT_RESTR, &statbuf);
  374     if (ret == 0)
  375         ops->aa_mount_features_enabled = 1;
  376 }
  377 
  378 /* aa_getcon is not working right now.  Use our hand-rolled version below */
  379 static int apparmor_enabled(struct lsm_ops *ops)
  380 {
  381     __do_fclose FILE *fin = NULL;
  382     char e;
  383     int ret;
  384 
  385     fin = fopen_cloexec(AA_ENABLED_FILE, "r");
  386     if (!fin)
  387         return 0;
  388 
  389     ret = fscanf(fin, "%c", &e);
  390     if (ret == 1 && e == 'Y') {
  391         load_mount_features_enabled(ops);
  392         return 1;
  393     }
  394 
  395     return 0;
  396 }
  397 
  398 static int __apparmor_process_label_open(struct lsm_ops *ops, pid_t pid, int o_flags, bool on_exec)
  399 {
  400     int ret = -1;
  401     int labelfd;
  402     char path[LXC_LSMATTRLEN];
  403 
  404     if (on_exec)
  405         TRACE("On-exec not supported with AppArmor");
  406 
  407     /* first try the apparmor subdir */
  408     ret = snprintf(path, LXC_LSMATTRLEN, "/proc/%d/attr/apparmor/current", pid);
  409     if (ret < 0 || ret >= LXC_LSMATTRLEN)
  410         return -1;
  411 
  412     labelfd = open(path, o_flags);
  413     if (labelfd >= 0)
  414         return labelfd;
  415     else if (errno != ENOENT)
  416         goto error;
  417 
  418     /* fallback to legacy global attr directory */
  419     ret = snprintf(path, LXC_LSMATTRLEN, "/proc/%d/attr/current", pid);
  420     if (ret < 0 || ret >= LXC_LSMATTRLEN)
  421         return -1;
  422 
  423     labelfd = open(path, o_flags);
  424     if (labelfd >= 0)
  425         return labelfd;
  426 
  427 error:
  428     return log_error_errno(-errno, errno, "Unable to open AppArmor LSM label file descriptor");
  429 }
  430 
  431 static char *apparmor_process_label_get(struct lsm_ops *ops, pid_t pid)
  432 {
  433     __do_close int fd_label = -EBADF;
  434     __do_free char *buf = NULL;
  435     __do_free char *label = NULL;
  436     int ret;
  437     size_t len;
  438 
  439     fd_label = __apparmor_process_label_open(ops, pid, O_RDONLY, false);
  440     if (fd_label < 0)
  441         return NULL;
  442 
  443     ret = fd_to_buf(fd_label, &buf, &len);
  444     if (ret < 0)
  445         return NULL;
  446 
  447     if (len == 0)
  448         return NULL;
  449 
  450     label = malloc(len + 1);
  451     if (!label)
  452         return NULL;
  453     memcpy(label, buf, len);
  454     label[len] = '\0';
  455 
  456     len = strcspn(label, "\n \t");
  457     if (len)
  458         label[len] = '\0';
  459 
  460     return move_ptr(label);
  461 }
  462 
  463 static char *apparmor_process_label_get_at(struct lsm_ops *ops, int fd_pid)
  464 {
  465     __do_free char *label = NULL;
  466     size_t len;
  467 
  468     /* first try the apparmor subdir, then fall back to legacy interface */
  469     label = read_file_at(fd_pid, "attr/apparmor/current", PROTECT_OPEN, PROTECT_LOOKUP_BENEATH);
  470     if (!label && errno == ENOENT)
  471         label = read_file_at(fd_pid, "attr/current", PROTECT_OPEN, PROTECT_LOOKUP_BENEATH);
  472     if (!label)
  473         return log_error_errno(NULL, errno, "Failed to get AppArmor context");
  474 
  475     len = strcspn(label, "\n \t");
  476     if (len)
  477         label[len] = '\0';
  478     return move_ptr(label);
  479 }
  480 
  481 /*
  482  * Probably makes sense to reorganize these to only read
  483  * the label once
  484  */
  485 static bool apparmor_am_unconfined(struct lsm_ops *ops)
  486 {
  487     char *p = apparmor_process_label_get(ops, lxc_raw_getpid());
  488     bool ret = false;
  489     if (!p || strequal(p, "unconfined"))
  490         ret = true;
  491     free(p);
  492     return ret;
  493 }
  494 
  495 static bool aa_needs_transition(char *curlabel)
  496 {
  497     if (!curlabel)
  498         return false;
  499     if (strequal(curlabel, "unconfined"))
  500         return false;
  501     if (strequal(curlabel, "/usr/bin/lxc-start"))
  502         return false;
  503     return true;
  504 }
  505 
  506 static inline void uint64hex(char *buf, uint64_t num)
  507 {
  508     size_t i;
  509 
  510     buf[16] = 0;
  511     for (i = 16; i--;) {
  512         char c = (char)(num & 0xf);
  513         buf[i] = c + (c < 0xa ? '0' : 'a' - 0xa);
  514         num >>= 4;
  515     }
  516 }
  517 
  518 static inline char *shorten_apparmor_name(char *name)
  519 {
  520     size_t len = strlen(name);
  521     if (len + 7 > 253) {
  522         uint64_t hash;
  523         hash = fnv_64a_buf(name, len, FNV1A_64_INIT);
  524         name = must_realloc(name, 16 + 1);
  525         uint64hex(name, hash);
  526     }
  527 
  528     return name;
  529 }
  530 
  531 /* Replace slashes with hyphens */
  532 static inline void sanitize_path(char *path)
  533 {
  534     size_t i;
  535 
  536     for (i = 0; path[i]; i++)
  537         if (path[i] == '/')
  538             path[i] = '-';
  539 }
  540 
  541 static inline char *apparmor_dir(const char *ctname, const char *lxcpath)
  542 {
  543     return must_make_path(lxcpath, ctname, "apparmor", NULL);
  544 }
  545 
  546 
  547 static inline char *apparmor_profile_full(const char *ctname, const char *lxcpath)
  548 {
  549     return shorten_apparmor_name(must_concat(NULL, "lxc-", ctname, "_<", lxcpath, ">", NULL));
  550 }
  551 
  552 /* Like apparmor_profile_full() but with slashes replaced by hyphens */
  553 static inline char *apparmor_namespace(const char *ctname, const char *lxcpath)
  554 {
  555     char *full;
  556 
  557     full = apparmor_profile_full(ctname, lxcpath);
  558     sanitize_path(full);
  559 
  560     return full;
  561 }
  562 
  563 static bool check_apparmor_parser_version(struct lsm_ops *ops)
  564 {
  565     int major = 0, minor = 0, micro = 0, ret = 0;
  566     struct lxc_popen_FILE *parserpipe;
  567     int rc;
  568 
  569     switch (ops->aa_parser_available) {
  570     case 0:
  571         return false;
  572     case 1:
  573         return true;
  574     }
  575 
  576     parserpipe = lxc_popen("apparmor_parser --version");
  577     if (!parserpipe) {
  578         fprintf(stderr, "Failed to run check for apparmor_parser\n");
  579         goto out;
  580     }
  581 
  582     rc = fscanf(parserpipe->f, "AppArmor parser version %d.%d.%d", &major, &minor, &micro);
  583     if (rc < 1) {
  584         lxc_pclose(parserpipe);
  585         /* We stay silent for now as this most likely means the shell
  586          * lxc_popen executed failed to find the apparmor_parser binary.
  587          * See the TODO comment above for details.
  588          */
  589         goto out;
  590     }
  591 
  592     rc = lxc_pclose(parserpipe);
  593     if (rc < 0) {
  594         fprintf(stderr, "Error waiting for child process\n");
  595         goto out;
  596     }
  597     if (rc != 0) {
  598         fprintf(stderr, "'apparmor_parser --version' executed with an error status\n");
  599         goto out;
  600     }
  601 
  602     if ((major > 2) || (major == 2 && minor > 10) || (major == 2 && minor == 10 && micro >= 95))
  603         ops->aa_supports_unix = 1;
  604 
  605     ret = 1;
  606 
  607 out:
  608     ops->aa_parser_available = ret;
  609     return ret == 1;
  610 }
  611 
  612 static bool file_is_yes(const char *path)
  613 {
  614     ssize_t rd;
  615     int fd;
  616     char buf[8]; /* we actually just expect "yes" or "no" */
  617 
  618     fd = open(path, O_RDONLY | O_CLOEXEC);
  619     if (fd < 0)
  620         return false;
  621 
  622     rd = lxc_read_nointr(fd, buf, sizeof(buf));
  623     close(fd);
  624 
  625     return rd >= 4 && strnequal(buf, "yes\n", 4);
  626 }
  627 
  628 static bool apparmor_can_stack(void)
  629 {
  630     int major, minor, scanned;
  631     FILE *f;
  632 
  633     if (!file_is_yes("/sys/kernel/security/apparmor/features/domain/stack"))
  634         return false;
  635 
  636     f = fopen_cloexec("/sys/kernel/security/apparmor/features/domain/version", "r");
  637     if (!f)
  638         return false;
  639 
  640     scanned = fscanf(f, "%d.%d", &major, &minor);
  641     fclose(f);
  642     if (scanned != 2)
  643         return false;
  644 
  645     return major > 1 || (major == 1 && minor >= 2);
  646 }
  647 
  648 static void must_append_sized_full(char **buf, size_t *bufsz, const char *data,
  649                    size_t size, bool append_newline)
  650 {
  651     size_t newsize = *bufsz + size;
  652 
  653     if (append_newline)
  654         ++newsize;
  655 
  656     *buf = must_realloc(*buf, newsize);
  657     memcpy(*buf + *bufsz, data, size);
  658 
  659     if (append_newline)
  660         (*buf)[newsize - 1] = '\n';
  661 
  662     *bufsz = newsize;
  663 }
  664 
  665 static void must_append_sized(char **buf, size_t *bufsz, const char *data, size_t size)
  666 {
  667     return must_append_sized_full(buf, bufsz, data, size, false);
  668 }
  669 
  670 static bool is_privileged(struct lxc_conf *conf)
  671 {
  672     return lxc_list_empty(&conf->id_map);
  673 }
  674 
  675 static const char* AA_ALL_DEST_PATH_LIST[] = {
  676     " -> /[^spd]*{,/**},\n",
  677     " -> /d[^e]*{,/**},\n",
  678     " -> /de[^v]*{,/**},\n",
  679     " -> /dev/.[^l]*{,/**},\n",
  680     " -> /dev/.l[^x]*{,/**},\n",
  681     " -> /dev/.lx[^c]*{,/**},\n",
  682     " -> /dev/.lxc?*{,/**},\n",
  683     " -> /dev/[^.]*{,/**},\n",
  684     " -> /dev?*{,/**},\n",
  685     " -> /p[^r]*{,/**},\n",
  686     " -> /pr[^o]*{,/**},\n",
  687     " -> /pro[^c]*{,/**},\n",
  688     " -> /proc?*{,/**},\n",
  689     " -> /s[^y]*{,/**},\n",
  690     " -> /sy[^s]*{,/**},\n",
  691     " -> /sys?*{,/**},\n",
  692     NULL,
  693 };
  694 
  695 static const struct mntopt_t {
  696     const char *opt;
  697     size_t len;
  698 } REMOUNT_OPTIONS[] = {
  699     { ",nodev", sizeof(",nodev")-1 },
  700     { ",nosuid", sizeof(",nosuid")-1 },
  701     { ",noexec", sizeof(",noexec")-1 },
  702 };
  703 
  704 static void append_remount_rule(char **profile, size_t *size, const char *rule)
  705 {
  706     size_t rule_len = strlen(rule);
  707 
  708     for (const char **dest = AA_ALL_DEST_PATH_LIST; *dest; ++dest) {
  709         must_append_sized(profile, size, rule, rule_len);
  710         must_append_sized(profile, size, *dest, strlen(*dest));
  711     }
  712 }
  713 
  714 static void append_all_remount_rules(char **profile, size_t *size)
  715 {
  716     /*
  717      * That's 30, and we add at most:
  718      * ",nodev,nosuid,noexec,strictatime -> /dev/.lx[^c]*{,/ **},\ n",
  719      * which is anouther ~58, this s hould be enough:
  720      */
  721     char buf[128] = "  mount options=(ro,remount,bind";
  722     const size_t buf_append_pos = strlen(buf);
  723 
  724     const size_t opt_count = ARRAY_SIZE(REMOUNT_OPTIONS);
  725     size_t opt_bits;
  726 
  727     must_append_sized(profile, size,
  728               "# allow various ro-bind-*re*mounts\n",
  729               sizeof("# allow various ro-bind-*re*mounts\n")-1);
  730 
  731     for (opt_bits = 0; opt_bits != 1 << opt_count; ++opt_bits) {
  732         size_t at = buf_append_pos;
  733         unsigned bit = 1;
  734         size_t o;
  735 
  736         for (o = 0; o != opt_count; ++o, bit <<= 1) {
  737             if (opt_bits & bit) {
  738                 const struct mntopt_t *opt = &REMOUNT_OPTIONS[o];
  739                 memcpy(&buf[at], opt->opt, opt->len);
  740                 at += opt->len;
  741             }
  742         }
  743 
  744         memcpy(&buf[at], ")", sizeof(")"));
  745         append_remount_rule(profile, size, buf);
  746 
  747         /* noatime and strictatime don't go together */
  748         memcpy(&buf[at], ",noatime)", sizeof(",noatime)"));
  749         append_remount_rule(profile, size, buf);
  750         memcpy(&buf[at], ",strictatime)", sizeof(",strictatime)"));
  751         append_remount_rule(profile, size, buf);
  752     }
  753 }
  754 
  755 static char *get_apparmor_profile_content(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
  756 {
  757     char *profile, *profile_name_full;
  758     size_t size;
  759     struct lxc_list *it;
  760 
  761     profile_name_full = apparmor_profile_full(conf->name, lxcpath);
  762 
  763     profile = must_concat(NULL,
  764 "#include <tunables/global>\n"
  765 "profile \"", profile_name_full, "\" flags=(attach_disconnected,mediate_deleted) {\n",
  766                           NULL);
  767     size = strlen(profile);
  768 
  769     must_append_sized(&profile, &size, AA_PROFILE_BASE,
  770                       STRARRAYLEN(AA_PROFILE_BASE));
  771 
  772     append_all_remount_rules(&profile, &size);
  773 
  774     if (ops->aa_supports_unix)
  775         must_append_sized(&profile, &size, AA_PROFILE_UNIX_SOCKETS,
  776                           STRARRAYLEN(AA_PROFILE_UNIX_SOCKETS));
  777 
  778     if (file_exists("/proc/self/ns/cgroup"))
  779         must_append_sized(&profile, &size, AA_PROFILE_CGROUP_NAMESPACES,
  780                           STRARRAYLEN(AA_PROFILE_CGROUP_NAMESPACES));
  781 
  782     if (ops->aa_can_stack && !ops->aa_is_stacked) {
  783         char *namespace, *temp;
  784 
  785         must_append_sized(&profile, &size, AA_PROFILE_STACKING_BASE,
  786                           STRARRAYLEN(AA_PROFILE_STACKING_BASE));
  787 
  788         namespace = apparmor_namespace(conf->name, lxcpath);
  789         temp = must_concat(NULL, "  change_profile -> \":", namespace, ":*\",\n"
  790                            "  change_profile -> \":", namespace, "://*\",\n",
  791                            NULL);
  792         free(namespace);
  793 
  794         must_append_sized(&profile, &size, temp, strlen(temp));
  795         free(temp);
  796     } else {
  797         must_append_sized(&profile, &size, AA_PROFILE_NO_STACKING,
  798                           STRARRAYLEN(AA_PROFILE_NO_STACKING));
  799     }
  800 
  801     if (conf->lsm_aa_allow_nesting) {
  802         must_append_sized(&profile, &size, AA_PROFILE_NESTING_BASE,
  803                           STRARRAYLEN(AA_PROFILE_NESTING_BASE));
  804 
  805         if (!ops->aa_can_stack || ops->aa_is_stacked) {
  806             char *temp;
  807 
  808             temp = must_concat(NULL, "  change_profile -> \"",
  809                                profile_name_full, "\",\n", NULL);
  810             must_append_sized(&profile, &size, temp, strlen(temp));
  811             free(temp);
  812         }
  813     }
  814 
  815     if (!is_privileged(conf) || am_host_unpriv())
  816         must_append_sized(&profile, &size, AA_PROFILE_UNPRIVILEGED,
  817                           STRARRAYLEN(AA_PROFILE_UNPRIVILEGED));
  818 
  819     lxc_list_for_each(it, &conf->lsm_aa_raw) {
  820         const char *line = it->elem;
  821 
  822         must_append_sized_full(&profile, &size, line, strlen(line), true);
  823     }
  824 
  825     /* include terminating \0 byte */
  826     must_append_sized(&profile, &size, "}\n", 3);
  827 
  828     free(profile_name_full);
  829 
  830     return profile;
  831 }
  832 
  833 /*
  834  * apparmor_parser creates a cache file using the parsed file's name as a name.
  835  * This means there may be multiple containers with the same name but different
  836  * lxcpaths. Therefore we need a sanitized version of the complete profile name
  837  * as profile file-name.
  838  * We already get this exactly from apparmor_namespace().
  839  */
  840 static char *make_apparmor_profile_path(const char *ctname, const char *lxcpath)
  841 {
  842     char *ret, *filename;
  843 
  844     filename = apparmor_namespace(ctname, lxcpath);
  845     ret = must_make_path(lxcpath, ctname, "apparmor", filename, NULL);
  846     free(filename);
  847 
  848     return ret;
  849 }
  850 
  851 static char *make_apparmor_namespace_path(const char *ctname, const char *lxcpath)
  852 {
  853     char *ret, *namespace;
  854 
  855     namespace = apparmor_namespace(ctname, lxcpath);
  856     ret = must_make_path("/sys/kernel/security/apparmor/policy/namespaces", namespace, NULL);
  857     free(namespace);
  858 
  859     return ret;
  860 }
  861 
  862 static bool make_apparmor_namespace(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
  863 {
  864     char *path;
  865 
  866     if (!ops->aa_can_stack || ops->aa_is_stacked)
  867         return true;
  868 
  869     path = make_apparmor_namespace_path(conf->name, lxcpath);
  870     errno = 0;
  871     if (mkdir(path, 0755) < 0 && errno != EEXIST) {
  872         SYSERROR("Error creating AppArmor namespace: %s", path);
  873         free(path);
  874         return false;
  875     }
  876     free(path);
  877 
  878     return true;
  879 }
  880 
  881 static void remove_apparmor_namespace(struct lxc_conf *conf, const char *lxcpath)
  882 {
  883     char *path;
  884 
  885     path = make_apparmor_namespace_path(conf->name, lxcpath);
  886     if (rmdir(path) != 0)
  887         SYSERROR("Error removing AppArmor namespace");
  888     free(path);
  889 }
  890 
  891 struct apparmor_parser_args {
  892     char cmd;
  893     char *file;
  894 };
  895 
  896 static int apparmor_parser_exec(void *data)
  897 {
  898     struct apparmor_parser_args *args = data;
  899     char cmdbuf[] = { '-', args->cmd, 'W', 'L', 0 };
  900 
  901     execlp("apparmor_parser", "apparmor_parser", cmdbuf, APPARMOR_CACHE_DIR, args->file, NULL);
  902 
  903     return -1;
  904 }
  905 
  906 static int run_apparmor_parser(char command,
  907                                struct lxc_conf *conf,
  908                                const char *lxcpath)
  909 {
  910     char output[PATH_MAX];
  911     int ret;
  912     struct apparmor_parser_args args = {
  913         .cmd = command,
  914         .file = make_apparmor_profile_path(conf->name, lxcpath),
  915     };
  916 
  917     ret = run_command(output, sizeof(output), apparmor_parser_exec, (void*)&args);
  918     if (ret < 0) {
  919         ERROR("Failed to run apparmor_parser on \"%s\": %s", args.file, output);
  920         ret = -1;
  921     }
  922 
  923 
  924     free(args.file);
  925     return ret;
  926 }
  927 
  928 static void remove_apparmor_profile(struct lxc_conf *conf, const char *lxcpath)
  929 {
  930     char *path;
  931 
  932     /* It's ok if these deletes fail: if the container was never started,
  933      * we'll have never written a profile or cached it.
  934      */
  935 
  936     path = make_apparmor_profile_path(conf->name, lxcpath);
  937     (void)unlink(path);
  938     free(path);
  939 
  940     /* Also remove the apparmor/ subdirectory */
  941     path = apparmor_dir(conf->name, lxcpath);
  942     (void)rmdir(path);
  943     free(path);
  944 }
  945 
  946 static int load_apparmor_profile(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
  947 {
  948     struct stat profile_sb;
  949     size_t content_len;
  950     int ret = -1;
  951     size_t old_len = 0;
  952     char *profile_path = NULL, *old_content = NULL, *new_content = NULL;
  953     int profile_fd = -1;
  954 
  955     if (!make_apparmor_namespace(ops, conf, lxcpath))
  956         return -1;
  957 
  958     /* In order to avoid forcing a profile parse (potentially slow) on
  959      * every container start, let's use apparmor's binary policy cache,
  960      * which checks mtime of the files to figure out if the policy needs to
  961      * be regenerated.
  962      *
  963      * Since it uses mtimes, we shouldn't just always write out our local
  964      * apparmor template; instead we should check to see whether the
  965      * template is the same as ours. If it isn't we should write our
  966      * version out so that the new changes are reflected and we definitely
  967      * force a recompile.
  968      */
  969 
  970     profile_path = make_apparmor_profile_path(conf->name, lxcpath);
  971     profile_fd = open(profile_path, O_RDONLY | O_CLOEXEC);
  972     if (profile_fd >= 0) {
  973         if (fstat(profile_fd, &profile_sb) < 0) {
  974             SYSERROR("Error accessing old profile from %s",
  975                      profile_path);
  976             goto out;
  977         }
  978         old_len = profile_sb.st_size;
  979         old_content = lxc_strmmap(NULL, old_len, PROT_READ,
  980                                   MAP_PRIVATE, profile_fd, 0);
  981         if (!old_content) {
  982             SYSERROR("Failed to mmap old profile from %s",
  983                      profile_path);
  984             goto out;
  985         }
  986     } else if (errno != ENOENT) {
  987         SYSERROR("Error reading old profile from %s", profile_path);
  988         goto out;
  989     }
  990 
  991     new_content = get_apparmor_profile_content(ops, conf, lxcpath);
  992     if (!new_content)
  993         goto out;
  994 
  995     content_len = strlen(new_content);
  996 
  997     if (!old_content || old_len != content_len || memcmp(old_content, new_content, content_len) != 0) {
  998         char *path;
  999 
 1000         ret = mkdir_p(APPARMOR_CACHE_DIR, 0755);
 1001         if (ret < 0) {
 1002             SYSERROR("Error creating AppArmor profile cache directory " APPARMOR_CACHE_DIR);
 1003             goto out;
 1004         }
 1005 
 1006         path = apparmor_dir(conf->name, lxcpath);
 1007         ret = mkdir_p(path, 0755);
 1008         if (ret < 0) {
 1009             SYSERROR("Error creating AppArmor profile directory: %s", path);
 1010             free(path);
 1011             goto out;
 1012         }
 1013         free(path);
 1014 
 1015         ret = lxc_write_to_file(profile_path, new_content, content_len, false, 0600);
 1016         if (ret < 0) {
 1017             SYSERROR("Error writing profile to %s", profile_path);
 1018             goto out;
 1019         }
 1020     }
 1021 
 1022     ret = run_apparmor_parser(AA_CMD_LOAD, conf, lxcpath);
 1023     if (ret != 0)
 1024         goto out_remove_profile;
 1025 
 1026     conf->lsm_aa_profile_created = true;
 1027 
 1028     goto out_ok;
 1029 
 1030 out_remove_profile:
 1031     remove_apparmor_profile(conf, lxcpath);
 1032 out:
 1033     remove_apparmor_namespace(conf, lxcpath);
 1034 out_ok:
 1035     if (profile_fd >= 0) {
 1036         if (old_content)
 1037             lxc_strmunmap(old_content, old_len);
 1038         close(profile_fd);
 1039     }
 1040     free(profile_path);
 1041     free(new_content);
 1042     return ret;
 1043 }
 1044 
 1045 /*
 1046  * Ensure that the container's policy namespace is unloaded to free kernel
 1047  * memory. This does not delete the policy from disk or cache.
 1048  */
 1049 static void apparmor_cleanup(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
 1050 {
 1051     if (!ops->aa_admin)
 1052         return;
 1053 
 1054     if (!conf->lsm_aa_profile_created)
 1055         return;
 1056 
 1057     remove_apparmor_namespace(conf, lxcpath);
 1058     (void)run_apparmor_parser(AA_CMD_UNLOAD, conf, lxcpath);
 1059 
 1060     remove_apparmor_profile(conf, lxcpath);
 1061 }
 1062 
 1063 static int apparmor_prepare(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
 1064 {
 1065     int ret = -1;
 1066     const char *label;
 1067     char *curlabel = NULL, *genlabel = NULL;
 1068 
 1069     if (!ops->aa_enabled)
 1070         return log_error(-1, "AppArmor not enabled");
 1071 
 1072     label = conf->lsm_aa_profile;
 1073 
 1074     /* user may request that we just ignore apparmor */
 1075     if (label && strequal(label, AA_UNCHANGED)) {
 1076         INFO("AppArmor profile unchanged per user request");
 1077         conf->lsm_aa_profile_computed = must_copy_string(label);
 1078         return 0;
 1079     }
 1080 
 1081     if (label && strequal(label, AA_GENERATED)) {
 1082         if (!check_apparmor_parser_version(ops)) {
 1083             ERROR("Cannot use generated profile: apparmor_parser not available");
 1084             goto out;
 1085         }
 1086 
 1087         /* auto-generate profile based on available/requested security features */
 1088         if (load_apparmor_profile(ops, conf, lxcpath) != 0) {
 1089             ERROR("Failed to load generated AppArmor profile");
 1090             goto out;
 1091         }
 1092 
 1093         genlabel = apparmor_profile_full(conf->name, lxcpath);
 1094         if (!genlabel) {
 1095             ERROR("Failed to build AppArmor profile name");
 1096             goto out;
 1097         }
 1098 
 1099         if (ops->aa_can_stack && !ops->aa_is_stacked) {
 1100             char *namespace = apparmor_namespace(conf->name, lxcpath);
 1101             size_t llen = strlen(genlabel);
 1102             must_append_sized(&genlabel, &llen, "//&:", STRARRAYLEN("//&:"));
 1103             must_append_sized(&genlabel, &llen, namespace, strlen(namespace));
 1104             must_append_sized(&genlabel, &llen, ":", STRARRAYLEN(":") + 1); /* with the nul byte */
 1105             free(namespace);
 1106         }
 1107 
 1108         label = genlabel;
 1109     }
 1110 
 1111     curlabel = apparmor_process_label_get(ops, lxc_raw_getpid());
 1112 
 1113     if (!ops->aa_can_stack && aa_needs_transition(curlabel)) {
 1114         /* we're already confined, and stacking isn't supported */
 1115 
 1116         if (!label || strequal(curlabel, label)) {
 1117             /* no change requested */
 1118             ret = 0;
 1119             goto out;
 1120         }
 1121 
 1122         ERROR("Already AppArmor confined, but new label requested.");
 1123         goto out;
 1124     }
 1125 
 1126     if (!label) {
 1127         if (cgns_supported())
 1128             label = AA_DEF_PROFILE_CGNS;
 1129         else
 1130             label = AA_DEF_PROFILE;
 1131     }
 1132 
 1133     if (!ops->aa_mount_features_enabled && !strequal(label, "unconfined")) {
 1134         WARN("Incomplete AppArmor support in your kernel");
 1135         if (!conf->lsm_aa_allow_incomplete) {
 1136             ERROR("If you really want to start this container, set");
 1137             ERROR("lxc.apparmor.allow_incomplete = 1");
 1138             ERROR("in your container configuration file");
 1139             goto out;
 1140         }
 1141     }
 1142 
 1143     conf->lsm_aa_profile_computed = must_copy_string(label);
 1144     ret = 0;
 1145 
 1146 out:
 1147     if (genlabel) {
 1148         free(genlabel);
 1149         if (ret != 0)
 1150             apparmor_cleanup(ops, conf, lxcpath);
 1151     }
 1152     free(curlabel);
 1153     return ret;
 1154 }
 1155 
 1156 static int apparmor_keyring_label_set(struct lsm_ops *ops, const char *label)
 1157 {
 1158     return 0;
 1159 }
 1160 
 1161 static int apparmor_process_label_fd_get(struct lsm_ops *ops, pid_t pid, bool on_exec)
 1162 {
 1163     return __apparmor_process_label_open(ops, pid, O_RDWR, on_exec);
 1164 }
 1165 
 1166 static int apparmor_process_label_set_at(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec)
 1167 {
 1168     __do_free char *command = NULL;
 1169     int ret = -1;
 1170     size_t len;
 1171 
 1172     if (on_exec)
 1173         TRACE("Changing AppArmor profile on exec not supported");
 1174 
 1175     len = strlen(label) + strlen("changeprofile ") + 1;
 1176     command = zalloc(len);
 1177     if (!command)
 1178         return ret_errno(ENOMEM);
 1179 
 1180     ret = snprintf(command, len, "changeprofile %s", label);
 1181     if (ret < 0 || (size_t)ret >= len)
 1182         return -EFBIG;
 1183 
 1184     ret = lxc_write_nointr(label_fd, command, len - 1);
 1185 
 1186     INFO("Set AppArmor label to \"%s\"", label);
 1187     return ret;
 1188 }
 1189 
 1190 /*
 1191  * apparmor_process_label_set: Set AppArmor process profile
 1192  *
 1193  * @label   : the profile to set
 1194  * @conf    : the container configuration to use if @label is NULL
 1195  * @default : use the default profile if @label is NULL
 1196  * @on_exec : this is ignored.  Apparmor profile will be changed immediately
 1197  *
 1198  * Returns 0 on success, < 0 on failure
 1199  *
 1200  * Notes: This relies on /proc being available.
 1201  */
 1202 static int apparmor_process_label_set(struct lsm_ops *ops, const char *inlabel,
 1203                       struct lxc_conf *conf, bool on_exec)
 1204 {
 1205     __do_close int label_fd = -EBADF;
 1206     int ret;
 1207     const char *label;
 1208 
 1209     if (!ops->aa_enabled)
 1210         return log_error_errno(-EOPNOTSUPP, EOPNOTSUPP, "AppArmor not enabled");
 1211 
 1212     label = inlabel ? inlabel : conf->lsm_aa_profile_computed;
 1213     if (!label)
 1214         return log_error_errno(-EINVAL, EINVAL, "LSM wasn't prepared");
 1215 
 1216     /* user may request that we just ignore apparmor */
 1217     if (strequal(label, AA_UNCHANGED))
 1218         return log_info(0, "AppArmor profile unchanged per user request");
 1219 
 1220     if (strequal(label, "unconfined") && apparmor_am_unconfined(ops))
 1221         return log_info(0, "AppArmor profile unchanged");
 1222 
 1223     label_fd = apparmor_process_label_fd_get(ops, lxc_raw_gettid(), on_exec);
 1224     if (label_fd < 0)
 1225         return log_error_errno(-EINVAL, EINVAL, "Failed to change AppArmor profile to %s", label);
 1226 
 1227     ret = apparmor_process_label_set_at(ops, label_fd, label, on_exec);
 1228     if (ret < 0)
 1229         return log_error_errno(-EINVAL, EINVAL, "Failed to change AppArmor profile to %s", label);
 1230 
 1231     return log_info(0, "Changed AppArmor profile to %s", label);
 1232 }
 1233 
 1234 static struct lsm_ops apparmor_ops = {
 1235     .name               = "AppArmor",
 1236     .aa_admin           = -1,
 1237     .aa_can_stack           = -1,
 1238     .aa_enabled         = -1,
 1239     .aa_is_stacked          = -1,
 1240     .aa_mount_features_enabled  = -1,
 1241     .aa_parser_available        = -1,
 1242     .aa_supports_unix       = -1,
 1243     .cleanup            = apparmor_cleanup,
 1244     .enabled            = apparmor_enabled,
 1245     .keyring_label_set      = apparmor_keyring_label_set,
 1246     .prepare                = apparmor_prepare,
 1247     .process_label_fd_get       = apparmor_process_label_fd_get,
 1248     .process_label_get      = apparmor_process_label_get,
 1249     .process_label_set      = apparmor_process_label_set,
 1250     .process_label_get_at       = apparmor_process_label_get_at,
 1251     .process_label_set_at       = apparmor_process_label_set_at,
 1252 };
 1253 
 1254 struct lsm_ops *lsm_apparmor_ops_init(void)
 1255 {
 1256     apparmor_ops.aa_admin = 0;
 1257     apparmor_ops.aa_can_stack = 0;
 1258     apparmor_ops.aa_enabled = 0;
 1259     apparmor_ops.aa_is_stacked = 0;
 1260     apparmor_ops.aa_mount_features_enabled = 0;
 1261     apparmor_ops.aa_parser_available = -1;
 1262     apparmor_ops.aa_supports_unix = 0;
 1263 
 1264     if (!apparmor_enabled(&apparmor_ops))
 1265         return NULL;
 1266 
 1267     apparmor_ops.aa_can_stack = apparmor_can_stack();
 1268     if (apparmor_ops.aa_can_stack)
 1269         apparmor_ops.aa_is_stacked = file_is_yes("/sys/kernel/security/apparmor/.ns_stacked");
 1270 
 1271     #if HAVE_LIBCAP
 1272     apparmor_ops.aa_admin = lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE);
 1273     #endif
 1274     if (!apparmor_ops.aa_admin)
 1275         WARN("Per-container AppArmor profiles are disabled because the mac_admin capability is missing");
 1276     else if (am_host_unpriv() && !apparmor_ops.aa_is_stacked)
 1277         WARN("Per-container AppArmor profiles are disabled because LXC is running in an unprivileged container without stacking");
 1278 
 1279     apparmor_ops.aa_enabled = 1;
 1280     return &apparmor_ops;
 1281 }