← Back to team overview

kernel-packages team mailing list archive

[Bug 1408106] [NEW] allow defining the attach root for attach_disconnected

 

Public bug reported:

With the following use of overlayfs, we get a disconnected path:

$ cat ./profile
#include <tunables/global>
profile foo {
  #include <abstractions/base>

  capability sys_admin,
  capability sys_chroot,
  mount,
  pivot_root,
}

$ cat ./overlay.c
#include <alloca.h>
#include <linux/sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/mount.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    int i = 0;
    int len = 0;
    int ret = 0;
    char* options;

    if (geteuid())
        unshare(CLONE_NEWUSER);
    unshare(CLONE_NEWNS);

    for (i = 1; i < argc; i++) {
        if (i == 1) {
            len = strlen(argv[i]) + strlen("upperdir=,lowerdir=/") + 2;
            options = alloca(len);
            ret = snprintf(options, len, "upperdir=%s,lowerdir=/", argv[i]);
        }
        else {
            len = strlen(argv[i]) + strlen("upperdir=,lowerdir=/mnt") + 2;
            options = alloca(len);
            ret = snprintf(options, len, "upperdir=%s,lowerdir=/mnt", argv[i]);
        }

        mount("overlayfs", "/mnt", "overlayfs", MS_MGC_VAL, options);
    }

    chdir("/mnt");
    pivot_root(".", ".");
    chroot(".");

    chdir("/");
    execl("/bin/bash", "/bin/bash", NULL);
}

$ sudo apparmor_parser -r ./profile && aa-exec -p foo -- ./a.out /tmp
[255]
...
Dec 12 14:31:38 localhost kernel: [57278.040216] audit: type=1400 audit(1418387498.613:712): apparmor="DENIED" operation="exec" info="Failed name lookup - disconnected path" error=-13 profile="foo" name="/bin/bash" pid=18255 comm="a.out" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0

With the above, the expectation was for the denial to be /mnt/bin/bash. There are three ways forward:
1. the correct solution is to patch overlayfs to properly track the loopback, but this will take a while, may ultimately be unachievable (investigation is needed) and is likely non-upstreamable
2. we could rely on the fact that overlayfs creates a private unshared submount, and provide a way to not mediate the path when that is present, and tagged. This would take a bit of time, and might be the preferred method over 1 longer term
3. we could extend attach_disconnected so that we can define the attach root. Eg, we can use profile foo (attach_disconnected=/mnt) {} such that '/bin/bash' maps to '/mnt/bin/bash'.

While attach_disconnected should in general be discouraged, this method:
 * is doable in a short time frame,
 * is generally useful even when the proper fix is in place
 * would help lxc in a few cases
 * would be sufficient for snappy

** Affects: apparmor
     Importance: Critical
     Assignee: John Johansen (jjohansen)
         Status: In Progress

** Affects: apparmor (Ubuntu)
     Importance: Critical
     Assignee: Steve Beattie (sbeattie)
         Status: Confirmed

** Affects: linux (Ubuntu)
     Importance: Critical
     Assignee: John Johansen (jjohansen)
         Status: Confirmed


** Tags: aa-kernel aa-parser aa-tools

** Description changed:

  With the following use of overlayfs, we get a disconnected path:
  
- $ cat ./profile 
+ $ cat ./profile
  #include <tunables/global>
  profile foo {
-   #include <abstractions/base>
+   #include <abstractions/base>
  
-   capability sys_admin,
-   capability sys_chroot,
-   mount,
-   pivot_root,
+   capability sys_admin,
+   capability sys_chroot,
+   mount,
+   pivot_root,
  }
  
- 
- $ cat ./overlay.c 
+ $ cat ./overlay.c
  #include <alloca.h>
  #include <linux/sched.h>
  #include <stdio.h>
  #include <string.h>
  #include <sys/mount.h>
  #include <fcntl.h>
  #include <unistd.h>
  
  int main(int argc, char* argv[]) {
-     int i = 0;
-     int len = 0;
-     int ret = 0;
-     char* options;
+     int i = 0;
+     int len = 0;
+     int ret = 0;
+     char* options;
  
-     if (geteuid())
-         unshare(CLONE_NEWUSER);
-     unshare(CLONE_NEWNS);
+     if (geteuid())
+         unshare(CLONE_NEWUSER);
+     unshare(CLONE_NEWNS);
  
-     for (i = 1; i < argc; i++) {
-         if (i == 1) {
-             len = strlen(argv[i]) + strlen("upperdir=,lowerdir=/") + 2;
-             options = alloca(len);
-             ret = snprintf(options, len, "upperdir=%s,lowerdir=/", argv[i]);
-         }
-         else {
-             len = strlen(argv[i]) + strlen("upperdir=,lowerdir=/mnt") + 2;
-             options = alloca(len);
-             ret = snprintf(options, len, "upperdir=%s,lowerdir=/mnt", argv[i]);
-         }
+     for (i = 1; i < argc; i++) {
+         if (i == 1) {
+             len = strlen(argv[i]) + strlen("upperdir=,lowerdir=/") + 2;
+             options = alloca(len);
+             ret = snprintf(options, len, "upperdir=%s,lowerdir=/", argv[i]);
+         }
+         else {
+             len = strlen(argv[i]) + strlen("upperdir=,lowerdir=/mnt") + 2;
+             options = alloca(len);
+             ret = snprintf(options, len, "upperdir=%s,lowerdir=/mnt", argv[i]);
+         }
  
-         mount("overlayfs", "/mnt", "overlayfs", MS_MGC_VAL, options);
-     }
+         mount("overlayfs", "/mnt", "overlayfs", MS_MGC_VAL, options);
+     }
  
-     chdir("/mnt");
-     pivot_root(".", ".");
-     chroot(".");
+     chdir("/mnt");
+     pivot_root(".", ".");
+     chroot(".");
  
-     chdir("/");
-     execl("/bin/bash", "/bin/bash", NULL);
+     chdir("/");
+     execl("/bin/bash", "/bin/bash", NULL);
  }
- 
  
  $ sudo apparmor_parser -r ./profile && aa-exec -p foo -- ./a.out /tmp
  [255]
  ...
  Dec 12 14:31:38 localhost kernel: [57278.040216] audit: type=1400 audit(1418387498.613:712): apparmor="DENIED" operation="exec" info="Failed name lookup - disconnected path" error=-13 profile="foo" name="/bin/bash" pid=18255 comm="a.out" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0
  
- 
- With the above, the expectation was for the denial to be /tmp/bin/bash. There are three ways forward:
+ With the above, the expectation was for the denial to be /mnt/bin/bash. There are three ways forward:
  1. the correct solution is to patch overlayfs to properly track the loopback, but this will take a while, may ultimately be unachievable (investigation is needed) and is likely non-upstreamable
  2. we could rely on the fact that overlayfs creates a private unshared submount, and provide a way to not mediate the path when that is present, and tagged. This would take a bit of time, and might be the preferred method over 1 longer term
- 3. we could extend attach_disconnected so that we can define the attach root. Eg, we can use profile foo (attach_disconnected=/tmp) {} such that '/bin/bash' maps to '/tmp/bin/bash'.
+ 3. we could extend attach_disconnected so that we can define the attach root. Eg, we can use profile foo (attach_disconnected=/mnt) {} such that '/bin/bash' maps to '/mnt/bin/bash'.
  
  While attach_disconnected should in general be discouraged, this method:
-  * is doable in a short time frame,
-  * is generally useful even when the proper fix is in place
-  * would help lxc in a few cases
-  * would be sufficient for snappy
+  * is doable in a short time frame,
+  * is generally useful even when the proper fix is in place
+  * would help lxc in a few cases
+  * would be sufficient for snappy

** Also affects: apparmor
   Importance: Undecided
       Status: New

** Changed in: apparmor
       Status: New => In Progress

** Changed in: apparmor
   Importance: Undecided => Critical

** Changed in: apparmor
     Assignee: (unassigned) => John Johansen (jjohansen)

** Changed in: apparmor (Ubuntu)
       Status: In Progress => Confirmed

** Changed in: apparmor (Ubuntu)
     Assignee: John Johansen (jjohansen) => Steve Beattie (sbeattie)

** Also affects: linux (Ubuntu)
   Importance: Undecided
       Status: New

** Changed in: linux (Ubuntu)
   Importance: Undecided => Critical

** Changed in: linux (Ubuntu)
       Status: New => Confirmed

** Changed in: linux (Ubuntu)
     Assignee: (unassigned) => John Johansen (jjohansen)

-- 
You received this bug notification because you are a member of Kernel
Packages, which is subscribed to linux in Ubuntu.
https://bugs.launchpad.net/bugs/1408106

Title:
  allow defining the attach root for attach_disconnected

Status in AppArmor Linux application security framework:
  In Progress
Status in apparmor package in Ubuntu:
  Confirmed
Status in linux package in Ubuntu:
  Confirmed

Bug description:
  With the following use of overlayfs, we get a disconnected path:

  $ cat ./profile
  #include <tunables/global>
  profile foo {
    #include <abstractions/base>

    capability sys_admin,
    capability sys_chroot,
    mount,
    pivot_root,
  }

  $ cat ./overlay.c
  #include <alloca.h>
  #include <linux/sched.h>
  #include <stdio.h>
  #include <string.h>
  #include <sys/mount.h>
  #include <fcntl.h>
  #include <unistd.h>

  int main(int argc, char* argv[]) {
      int i = 0;
      int len = 0;
      int ret = 0;
      char* options;

      if (geteuid())
          unshare(CLONE_NEWUSER);
      unshare(CLONE_NEWNS);

      for (i = 1; i < argc; i++) {
          if (i == 1) {
              len = strlen(argv[i]) + strlen("upperdir=,lowerdir=/") + 2;
              options = alloca(len);
              ret = snprintf(options, len, "upperdir=%s,lowerdir=/", argv[i]);
          }
          else {
              len = strlen(argv[i]) + strlen("upperdir=,lowerdir=/mnt") + 2;
              options = alloca(len);
              ret = snprintf(options, len, "upperdir=%s,lowerdir=/mnt", argv[i]);
          }

          mount("overlayfs", "/mnt", "overlayfs", MS_MGC_VAL, options);
      }

      chdir("/mnt");
      pivot_root(".", ".");
      chroot(".");

      chdir("/");
      execl("/bin/bash", "/bin/bash", NULL);
  }

  $ sudo apparmor_parser -r ./profile && aa-exec -p foo -- ./a.out /tmp
  [255]
  ...
  Dec 12 14:31:38 localhost kernel: [57278.040216] audit: type=1400 audit(1418387498.613:712): apparmor="DENIED" operation="exec" info="Failed name lookup - disconnected path" error=-13 profile="foo" name="/bin/bash" pid=18255 comm="a.out" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0

  With the above, the expectation was for the denial to be /mnt/bin/bash. There are three ways forward:
  1. the correct solution is to patch overlayfs to properly track the loopback, but this will take a while, may ultimately be unachievable (investigation is needed) and is likely non-upstreamable
  2. we could rely on the fact that overlayfs creates a private unshared submount, and provide a way to not mediate the path when that is present, and tagged. This would take a bit of time, and might be the preferred method over 1 longer term
  3. we could extend attach_disconnected so that we can define the attach root. Eg, we can use profile foo (attach_disconnected=/mnt) {} such that '/bin/bash' maps to '/mnt/bin/bash'.

  While attach_disconnected should in general be discouraged, this method:
   * is doable in a short time frame,
   * is generally useful even when the proper fix is in place
   * would help lxc in a few cases
   * would be sufficient for snappy

To manage notifications about this bug go to:
https://bugs.launchpad.net/apparmor/+bug/1408106/+subscriptions


Follow ups

References