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