apparmor: internal paths should be treated as disconnected
authorJohn Johansen <john.johansen@canonical.com>
Fri, 25 Jul 2014 11:02:10 +0000 (04:02 -0700)
committerWilly Tarreau <w@1wt.eu>
Tue, 20 Jun 2017 12:04:11 +0000 (14:04 +0200)
commit bd35db8b8ca6e27fc17a9057ef78e1ddfc0de351 upstream.

Internal mounts are not mounted anywhere and as such should be treated
as disconnected paths.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Willy Tarreau <w@1wt.eu>
security/apparmor/path.c

index ebc7780926b82cce26f42e3d74f14a77d0d946a0..07bf2ac1ef6f04269d3a119102fe32b8d9d9f892 100644 (file)
@@ -25,7 +25,6 @@
 #include "include/path.h"
 #include "include/policy.h"
 
-
 /* modified from dcache.c */
 static int prepend(char **buffer, int buflen, const char *str, int namelen)
 {
@@ -39,6 +38,38 @@ static int prepend(char **buffer, int buflen, const char *str, int namelen)
 
 #define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
 
+/* If the path is not connected to the expected root,
+ * check if it is a sysctl and handle specially else remove any
+ * leading / that __d_path may have returned.
+ * Unless
+ *     specifically directed to connect the path,
+ * OR
+ *     if in a chroot and doing chroot relative paths and the path
+ *     resolves to the namespace root (would be connected outside
+ *     of chroot) and specifically directed to connect paths to
+ *     namespace root.
+ */
+static int disconnect(const struct path *path, char *buf, char **name,
+                     int flags)
+{
+       int error = 0;
+
+       if (!(flags & PATH_CONNECT_PATH) &&
+           !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
+             our_mnt(path->mnt))) {
+               /* disconnected path, don't return pathname starting
+                * with '/'
+                */
+               error = -EACCES;
+               if (**name == '/')
+                       *name = *name + 1;
+       } else if (**name != '/')
+               /* CONNECT_PATH with missing root */
+               error = prepend(name, *name - buf, "/", 1);
+
+       return error;
+}
+
 /**
  * d_namespace_path - lookup a name associated with a given path
  * @path: path to lookup  (NOT NULL)
@@ -74,7 +105,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
                         * control instead of hard coded /proc
                         */
                        return prepend(name, *name - buf, "/proc", 5);
-               }
+               } else
+                       return disconnect(path, buf, name, flags);
                return 0;
        }
 
@@ -120,32 +152,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
                        goto out;
        }
 
-       /* If the path is not connected to the expected root,
-        * check if it is a sysctl and handle specially else remove any
-        * leading / that __d_path may have returned.
-        * Unless
-        *     specifically directed to connect the path,
-        * OR
-        *     if in a chroot and doing chroot relative paths and the path
-        *     resolves to the namespace root (would be connected outside
-        *     of chroot) and specifically directed to connect paths to
-        *     namespace root.
-        */
-       if (!connected) {
-               if (!(flags & PATH_CONNECT_PATH) &&
-                          !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
-                            our_mnt(path->mnt))) {
-                       /* disconnected path, don't return pathname starting
-                        * with '/'
-                        */
-                       error = -EACCES;
-                       if (*res == '/')
-                               *name = res + 1;
-               } else if (*res != '/')
-                       /* CONNECT_PATH with missing root */
-                       error = prepend(name, *name - buf, "/", 1);
-
-       }
+       if (!connected)
+               error = disconnect(path, buf, name, flags);
 
 out:
        return error;