github.com/chipaca/snappy@v0.0.0-20210104084008-1f06296fe8ad/interfaces/builtin/greengrass_support.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2017 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package builtin
    21  
    22  import (
    23  	"github.com/snapcore/snapd/interfaces"
    24  	"github.com/snapcore/snapd/interfaces/apparmor"
    25  	"github.com/snapcore/snapd/interfaces/seccomp"
    26  	"github.com/snapcore/snapd/interfaces/udev"
    27  	"github.com/snapcore/snapd/release"
    28  )
    29  
    30  const greengrassSupportSummary = `allows operating as the Greengrass service`
    31  
    32  const greengrassSupportBaseDeclarationPlugs = `
    33    greengrass-support:
    34      allow-installation: false
    35      deny-auto-connection: true
    36  `
    37  
    38  const greengrassSupportBaseDeclarationSlots = `
    39    greengrass-support:
    40      allow-installation:
    41        slot-snap-type:
    42          - core
    43      deny-auto-connection: true
    44  `
    45  
    46  const greengrassSupportConnectedPlugAppArmorCore = `
    47  # these accesses are necessary for Ubuntu Core 16, likely due to the version 
    48  # of apparmor or the kernel which doesn't resolve the upper layer of an 
    49  # overlayfs mount correctly
    50  # the accesses show up as runc trying to read from
    51  # /system-data/var/snap/greengrass/x1/ggc-writable/packages/1.7.0/var/worker/overlays/$UUID/upper/
    52  /system-data/var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/ rw,
    53  /system-data/var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/{,**} rw,
    54  `
    55  
    56  const greengrassSupportProcessModeConnectedPlugAppArmor = `
    57  # Description: can manage greengrass 'things' and their sandboxes. This policy
    58  # is meant currently only to enable Greengrass to run _only_ process-mode or 
    59  # "no container" lambdas.
    60  # needed by older versions of cloneBinary.ensureSelfCloned() to avoid 
    61  # CVE-2019-5736
    62  / ix,
    63  # newer versions of runC have this denial instead of "/ ix" above
    64  /bin/runc rix,
    65  `
    66  
    67  const greengrassSupportFullContainerConnectedPlugAppArmor = `
    68  # Description: can manage greengrass 'things' and their sandboxes. This
    69  # policy is intentionally not restrictive and is here to help guard against
    70  # programming errors and not for security confinement. The greengrassd
    71  # daemon by design requires extensive access to the system and
    72  # cannot be effectively confined against malicious activity.
    73  
    74  # greengrassd uses 'prctl(PR_CAPBSET_DROP, ...)'
    75  capability setpcap,
    76  
    77  # Allow managing child processes (signals, OOM, ptrace, cgroups)
    78  capability kill,
    79  
    80  capability sys_resource,
    81  /sys/kernel/mm/hugepages/ r,
    82  /sys/kernel/mm/transparent_hugepage/{,**} r,
    83  owner @{PROC}/[0-9]*/oom_score_adj rw,
    84  
    85  capability sys_ptrace,
    86  ptrace (trace) peer=@{profile_name},
    87  
    88  # allow use of ggc_user and ggc_group
    89  capability chown,
    90  capability fowner,
    91  capability fsetid,
    92  capability setuid,
    93  capability setgid,
    94  
    95  # Note: when AppArmor supports fine-grained owner matching, can match on
    96  # ggc_user (LP: #1697090)
    97  @{PROC}/[0-9]*/uid_map r,
    98  @{PROC}/[0-9]*/gid_map r,
    99  @{PROC}/[0-9]*/environ r,
   100  owner @{PROC}/[0-9]*/uid_map w,
   101  owner @{PROC}/[0-9]*/gid_map w,
   102  
   103  # Allow greengrassd to read restricted non-root directories (LP: #1697090)
   104  capability dac_read_search,
   105  
   106  # overlayfs
   107  capability sys_admin,
   108  capability dac_override,  # for various overlayfs accesses
   109  
   110  # for setting up mounts
   111  @{PROC}/[0-9]*/mountinfo r,
   112  @{PROC}/filesystems r,
   113  
   114  # runc needs this
   115  @{PROC}/[0-9]*/setgroups r,
   116  
   117  # cgroup accesses
   118  # greengrassd extensively uses cgroups to confine it's containers (AKA lambdas)
   119  # and needs to read what cgroups are available; we allow reading any cgroup, 
   120  # but limit writes below
   121  # also note that currently greengrass is not implemented in such a way that it
   122  # can stack it's cgroups inside the cgroup that snapd would normally enforce
   123  # but this may change in the future
   124  # an example cgroup access looks like this:
   125  # /old_rootfs/sys/fs/cgroup/cpuset/system.slice/7d23e67f-13f5-4b7e-5a85-83f8773345a8/
   126  # the old_rootfs prefix is due to the pivot_root - the "old" rootfs is mounted
   127  # at /old_rootfs before
   128  @{PROC}/cgroups r,
   129  owner @{PROC}/[0-9]*/cgroup r,
   130  owner /old_rootfs/sys/fs/cgroup/{,**} r,
   131  owner /old_rootfs/sys/fs/cgroup/{blkio,cpuset,devices,hugetlb,memory,perf_event,pids,freezer/snap.@{SNAP_NAME}}/{,system.slice/}system.slice/ rw,
   132  owner /old_rootfs/sys/fs/cgroup/{blkio,cpuset,devices,hugetlb,memory,perf_event,pids,freezer/snap.@{SNAP_NAME}}/{,system.slice/}system.slice/[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/{,**} rw,
   133  # separated from the above rule for clarity due to the comma in "net_cls,net_prio"
   134  owner /old_rootfs/sys/fs/cgroup/net_cls,net_prio/{,system.slice/}system.slice/ rw,
   135  owner /old_rootfs/sys/fs/cgroup/net_cls,net_prio/{,system.slice/}system.slice/[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/{,**} rw,
   136  owner /old_rootfs/sys/fs/cgroup/cpu,cpuacct/{,system.slice/}system.slice/ rw,
   137  owner /old_rootfs/sys/fs/cgroup/cpu,cpuacct/{,system.slice/}system.slice/[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/{,**} rw,
   138  owner /old_rootfs/sys/fs/cgroup/{devices,memory,pids,blkio,systemd}/{,system.slice/}snap.@{SNAP_NAME}.greengrass{,d.service}/system.slice/ rw,
   139  owner /old_rootfs/sys/fs/cgroup/{devices,memory,pids,blkio,systemd}/{,system.slice/}snap.@{SNAP_NAME}.greengrass{,d.service}/system.slice/[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/{,**} rw,
   140  owner /old_rootfs/sys/fs/cgroup/cpu,cpuacct/system.slice/snap.@{SNAP_NAME}.greengrass{,d.service}/system.slice/ rw,
   141  owner /old_rootfs/sys/fs/cgroup/cpu,cpuacct/system.slice/snap.@{SNAP_NAME}.greengrass{,d.service}/system.slice/{,**} rw,
   142  # specific rule for cpuset files
   143  owner /old_rootfs/sys/fs/cgroup/cpuset/{,system.slice/}cpuset.{cpus,mems} rw,
   144  
   145  # the wrapper scripts need to use mount/umount and pivot_root from the 
   146  # core snap
   147  /bin/{,u}mount ixr,
   148  /sbin/pivot_root ixr,
   149  
   150  # allow pivot_root'ing into the rootfs prepared for the greengrass daemon
   151  # parallel-installs: SNAP_{DATA,COMMON} are remapped, need to use SNAP_NAME, for
   152  # completeness allow SNAP_INSTANCE_NAME too
   153  pivot_root
   154  	oldroot=/var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/old_rootfs/
   155  	/var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/,
   156  
   157  # miscellaneous accesses by greengrassd
   158  /sys/devices/virtual/block/loop[0-9]*/loop/autoclear r,
   159  /sys/devices/virtual/block/loop[0-9]*/loop/backing_file r,
   160  
   161  # greengrassd needs protected hardlinks, symlinks, etc to run securely, but
   162  # won't turn them on itself, hence only read access for these things -
   163  # the user is clearly informed if these are disabled and so the user can
   164  # enable these themselves rather than give the snap permission to turn these
   165  # on
   166  @{PROC}/sys/fs/protected_hardlinks r,
   167  @{PROC}/sys/fs/protected_symlinks r,
   168  @{PROC}/sys/fs/protected_fifos r,
   169  @{PROC}/sys/fs/protected_regular r,
   170  
   171  # mount tries to access this, but it doesn't really need it
   172  deny /run/mount/utab rw,
   173  
   174  # these accesses are needed in order to mount a squashfs file for the rootfs
   175  # note that these accesses allow reading other snaps and thus grants device control
   176  /dev/loop-control rw,
   177  /dev/loop[0-9]* rw,
   178  /sys/devices/virtual/block/loop[0-9]*/ r,
   179  /sys/devices/virtual/block/loop[0-9]*/** r,
   180  
   181  # mount for mounting the rootfs which is a squashfs image inside $SNAP_DATA/rootfs
   182  mount options=ro /dev/loop[0-9]* -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/,
   183  
   184  # generic mounts for allowing anything inside $SNAP_DATA to be remounted anywhere else inside $SNAP_DATA
   185  # parallel-installs: SNAP_{DATA,COMMON} are remapped, need to use SNAP_NAME, for
   186  # completeness allow SNAP_INSTANCE_NAME too
   187  mount options=(rw, bind) /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/** -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/** ,
   188  mount options=(rw, rbind) /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/** -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/** ,
   189  # also allow mounting new files anywhere underneath the rootfs of the target 
   190  # overlayfs directory, which is the rootfs of the container
   191  # this is for allowing local resource access which first makes a mount at 
   192  # the target destination and then a bind mount from the source to the destination
   193  # the source destination mount will be allowed under the above rule
   194  mount -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/**,
   195  
   196  # specific mounts for setting up the mount namespace that greengrassd runs inside
   197  mount options=(rw, bind) /proc/ -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/proc/,
   198  mount /sys -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/sys/,
   199  mount options=(rw, bind) /dev/ -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/dev/,
   200  mount options=(rw, bind) /{,var/}run/ -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/{,var/}run/,
   201  mount options=(rw, nosuid, strictatime) fstype=tmpfs tmpfs -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/dev/,
   202  # note that we don't mount a new tmpfs here so that everytime we run and setup
   203  # the mount ns for greengrassd it uses the same tmpfs which will be the tmpfs
   204  # that snapd sets up for the snap
   205  mount options=(rw, bind) /tmp/ -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/tmp/,
   206  mount options=(rw, nosuid, nodev, noexec) fstype=mqueue mqueue -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/dev/mqueue/,
   207  mount options=(rw, nosuid, noexec) fstype=devpts devpts -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/dev/pts/,
   208  mount options=(rw, nosuid, nodev, noexec) fstype=tmpfs shm -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/dev/shm/,
   209  mount fstype=proc proc -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/proc/,
   210  
   211  # mounts for setting up child container rootfs
   212  mount options=(rw, rprivate) -> /,
   213  mount options=(ro, remount, rbind) -> /,
   214  mount fstype=overlay -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/,
   215  
   216  # for jailing the process by removing the rootfs when the overlayfs is setup
   217  umount /,
   218  
   219  # mounts greengrassd performs for the containers
   220  mount fstype="tmpfs" options=(rw, nosuid, strictatime) tmpfs -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/,
   221  mount fstype="proc" proc -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/proc/,
   222  mount fstype="devpts" options=(rw, nosuid, noexec) devpts -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/pts/,
   223  mount fstype="tmpfs" options=(rw, nosuid, nodev, noexec) shm -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/shm/,
   224  mount fstype="mqueue" options=(rw, nosuid, nodev, noexec) mqueue -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/mqueue/,
   225  mount options=(ro, remount, bind) -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/lambda/,
   226  mount options=(ro, remount, bind) -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/runtime/,
   227  mount options=(rw, bind) /dev/null -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/null,
   228  mount options=(rw, bind) /dev/random -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/random,
   229  mount options=(rw, bind) /dev/full -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/full,
   230  mount options=(rw, bind) /dev/tty -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/tty,
   231  mount options=(rw, bind) /dev/zero -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/zero,
   232  mount options=(rw, bind) /dev/urandom -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/dev/urandom,
   233  
   234  # mounts for /run in the greengrassd mount namespace
   235  mount options=(rw, bind) /run/ -> /run/,
   236  
   237  # mounts for resolv.conf inside the container
   238  # we have to manually do this otherwise the go DNS resolver fails to work, because it isn't configured to 
   239  # use the system DNS server and attempts to do DNS resolution itself, manually inspecting /etc/resolv.conf
   240  mount options=(ro, bind) /run/systemd/resolve/stub-resolv.conf -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/etc/resolv.conf,
   241  mount options=(ro, bind) /run/resolvconf/resolv.conf -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/etc/resolv.conf,
   242  mount options=(ro, remount, bind) -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/rootfs/etc/resolv.conf,
   243  
   244  # pivot_root for the container initialization into the rootfs
   245  # note that the actual syscall is pivotroot(".",".")
   246  # so the oldroot is the same as the new root
   247  pivot_root 
   248  	oldroot=/var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/
   249  	/var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/ggc-writable/packages/*/rootfs/merged/,
   250  
   251  # mounts for /proc
   252  mount options=(ro, remount) -> /proc/{asound/,bus/,fs/,irq/,sys/,sysrq-trigger},
   253  mount options=(ro, remount, rbind) -> /proc/{asound/,bus/,fs/,irq/,sys/,sysrq-trigger},
   254  mount options=(ro, nosuid, nodev, noexec, remount, rbind) -> /proc/{asound/,bus/,fs/,irq/,sys/,sysrq-trigger},
   255  mount options=(rw, bind) /proc/asound/ -> /proc/asound/,
   256  mount options=(rw, bind) /proc/bus/ -> /proc/bus/,
   257  mount options=(rw, bind) /proc/fs/ -> /proc/fs/,
   258  mount options=(rw, bind) /proc/irq/ -> /proc/irq/,
   259  mount options=(rw, bind) /proc/sys/ -> /proc/sys/,
   260  mount options=(rw, bind) /proc/sysrq-trigger -> /proc/sysrq-trigger,
   261  
   262  # mount some devices using /dev/null
   263  mount options=(rw, bind) /dev/null -> /proc/kcore,
   264  mount options=(rw, bind) /dev/null -> /proc/sched_debug,
   265  mount options=(rw, bind) /dev/null -> /proc/timer_stats,
   266  
   267  # greengrass will also mount over /proc/latency_stats when running on
   268  # kernels configured with CONFIG_LATENCYTOP set
   269  mount options=(rw, bind) /dev/null -> /proc/latency_stats,
   270  
   271  # umounts for tearing down containers
   272  umount /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/*/**,
   273  
   274  # this is for container device creation
   275  # also need mknod and mknodat in seccomp
   276  capability mknod,
   277  
   278  # for the greengrassd pid file
   279  # note we can't use layouts for this because /var/run is a symlink to /run
   280  # and /run is explicitly disallowed for use by layouts
   281  # also note that technically this access is post-pivot_root, but during the setup
   282  # for the mount ns that the snap performs (not snapd), /var/run is bind mounted
   283  # from outside the pivot_root to inside the pivot_root, so this will always 
   284  # access the same files inside or outside the pivot_root
   285  owner /{var/,}run/greengrassd.pid rw,
   286  
   287  # all of the rest of the accesses are made by child containers and as such are 
   288  # "post-pivot_root", meaning that they aren't accessing these files on the 
   289  # host root filesystem, but rather somewhere inside $SNAP_DATA/rootfs/
   290  # Note: eventually greengrass will gain the ability to specify child profiles
   291  # for it's containers and include these rules in that profile so they won't
   292  # be here, but that work isn't done yet
   293  # Additionally see LP bug #1791711 for apparmor resolving file accesses after
   294  # a pivot_root
   295  
   296  # for IPC communication via lambda helpers
   297  /[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/upper/{,greengrass_ipc.sock} rw,
   298  
   299  # for child container lambda certificates
   300  /certs/ r,
   301  /certs/** r,
   302  /group/ r,
   303  /group/** r,
   304  /state/ r,
   305  /state/{,**} krw,
   306  # the child containers need to use a file lock here
   307  owner /state/secretsmanager/secrets.db krw,
   308  owner /state/secretsmanager/secrets.db-journal rw,
   309  owner /state/shadow/ rw,
   310  owner /state/shadow/{,**} krw,
   311  # more specific accesses for writing
   312  owner /state/server/ rw,
   313  owner /state/server/{,**} rw,
   314  
   315  # for executing python, nodejs, java, and C (executable) lambda functions
   316  # currently the runtimes are "python2.7", "nodejs6.10", "java8" and "executable",
   317  # but those version numbers could change so we add a "*" on the end of the folders to be safe for
   318  # future potential upgrades
   319  /runtime/{python*,executable*,nodejs*,java*}/ r,
   320  /runtime/{python*,executable*,nodejs*,java*}/** r,
   321  
   322  # Ideally we would use a child profile for these but since the greengrass
   323  # sandbox is using prctl(PR_SET_NO_NEW_PRIVS, ...) we cannot since that blocks
   324  # profile transitions. With policy stacking we could use a more restrictive
   325  # child profile, but there are bugs which prevent that at this time
   326  # (LP: #1696552, LP: #1696551). As such, must simply rely on the greengrass
   327  # sandbox for now.
   328  /lambda/ r,
   329  /lambda/** ixr,
   330  
   331  # needed by cloneBinary.ensureSelfCloned()
   332  / ix,
   333  
   334  # the python runtime tries to access /etc/debian_version, presumably to identify what system it's running on
   335  # note there may be other accesses that the containers try to run...
   336  /etc/ r,
   337  /etc/debian_version r,
   338  #include <abstractions/python>
   339  # additional accesses needed for newer pythons in later bases
   340  /usr/lib{,32,64}/python3.[0-9]/**.{pyc,so}           mr,
   341  /usr/lib{,32,64}/python3.[0-9]/**.{egg,py,pth}       r,
   342  /usr/lib{,32,64}/python3.[0-9]/{site,dist}-packages/ r,
   343  /usr/lib{,32,64}/python3.[0-9]/lib-dynload/*.so      mr,
   344  /etc/python3.[0-9]/**                                r,
   345  /usr/include/python3.[0-9]*/pyconfig.h               r,
   346  
   347  # manually add java certs here
   348  # see also https://bugs.launchpad.net/apparmor/+bug/1816372
   349  /etc/ssl/certs/java/{,*} r,
   350  #include <abstractions/ssl_certs>
   351  `
   352  
   353  const greengrassSupportConnectedPlugSeccomp = `
   354  # Description: can manage greengrass 'things' and their sandboxes. This
   355  # policy is intentionally not restrictive and is here to help guard against
   356  # programming errors and not for security confinement. The greengrassd
   357  # daemon by design requires extensive access to the system and
   358  # cannot be effectively confined against malicious activity.
   359  
   360  # allow use of ggc_user and ggc_group
   361  # FIXME: seccomp arg filter by this uid/gid when supported by snap-confine
   362  lchown
   363  lchown32
   364  fchown
   365  fchown32
   366  fchownat
   367  setgroups
   368  setgroups32
   369  
   370  # for creating a new mount namespace for the containers
   371  setns - CLONE_NEWNS
   372  unshare
   373  
   374  # for overlayfs and various bind mounts
   375  mount
   376  umount2
   377  pivot_root
   378  
   379  # greengrassd calls 'sethostname("sandbox", 7)'
   380  sethostname
   381  
   382  # greengrassd sets up several session keyrings. See:
   383  # https://github.com/torvalds/linux/blob/master/Documentation/security/keys.txt
   384  # Note that the lambda functions themselves run under a seccomp sandbox setup
   385  # by greengrassd.
   386  keyctl
   387  
   388  # special character device creation is necessary for creating the overlayfs 
   389  # mounts
   390  # Unfortunately this grants device ownership to the snap.
   391  mknod - |S_IFCHR -
   392  mknodat - - |S_IFCHR -
   393  `
   394  
   395  func (iface *greengrassSupportInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   396  	// check the flavor
   397  	var flavor string
   398  	_ = plug.Attr("flavor", &flavor)
   399  	switch flavor {
   400  	case "", "legacy-container":
   401  		// default, legacy version of the interface
   402  		if release.OnClassic {
   403  			spec.AddSnippet(greengrassSupportFullContainerConnectedPlugAppArmor)
   404  		} else {
   405  			spec.AddSnippet(greengrassSupportFullContainerConnectedPlugAppArmor + greengrassSupportConnectedPlugAppArmorCore)
   406  		}
   407  		// greengrass needs to use ptrace for controlling it's containers
   408  		spec.SetUsesPtraceTrace()
   409  	case "no-container":
   410  		// this is the no-container version, it does not use as much privilege
   411  		// as the default "legacy-container" flavor
   412  		spec.AddSnippet(greengrassSupportProcessModeConnectedPlugAppArmor)
   413  	}
   414  
   415  	return nil
   416  }
   417  
   418  func (iface *greengrassSupportInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   419  	// check the flavor
   420  	var flavor string
   421  	_ = plug.Attr("flavor", &flavor)
   422  	switch flavor {
   423  	case "", "legacy-container":
   424  		spec.AddSnippet(greengrassSupportConnectedPlugSeccomp)
   425  	case "no-container":
   426  		// no-container has no additional seccomp available to it
   427  	}
   428  
   429  	return nil
   430  }
   431  
   432  func (iface *greengrassSupportInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   433  	var flavor string
   434  	_ = plug.Attr("flavor", &flavor)
   435  	switch flavor {
   436  	case "", "legacy-container":
   437  		// default containerization controls the device cgroup
   438  		spec.SetControlsDeviceCgroup()
   439  	case "no-container":
   440  		// no-container does not control the device cgroup
   441  	}
   442  
   443  	return nil
   444  }
   445  
   446  type greengrassSupportInterface struct {
   447  	commonInterface
   448  }
   449  
   450  func init() {
   451  	// declare the greengrass-support interface as needing ptrace(trace)
   452  	registerIface(&greengrassSupportInterface{commonInterface{
   453  		name:                 "greengrass-support",
   454  		summary:              greengrassSupportSummary,
   455  		implicitOnCore:       true,
   456  		implicitOnClassic:    true,
   457  		baseDeclarationSlots: greengrassSupportBaseDeclarationSlots,
   458  		baseDeclarationPlugs: greengrassSupportBaseDeclarationPlugs,
   459  	}})
   460  }