--- zzzz-none-000/linux-3.10.107/security/apparmor/path.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/security/apparmor/path.c 2021-02-04 17:41:59.000000000 +0000 @@ -25,6 +25,7 @@ #include "include/path.h" #include "include/policy.h" + /* modified from dcache.c */ static int prepend(char **buffer, int buflen, const char *str, int namelen) { @@ -38,38 +39,6 @@ #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) @@ -105,8 +74,7 @@ * control instead of hard coded /proc */ return prepend(name, *name - buf, "/proc", 5); - } else - return disconnect(path, buf, name, flags); + } return 0; } @@ -146,14 +114,35 @@ * security_path hooks as a deleted dentry except without an inode * allocated. */ - if (d_unlinked(path->dentry) && path->dentry->d_inode && + if (d_unlinked(path->dentry) && d_is_positive(path->dentry) && !(flags & PATH_MEDIATE_DELETED)) { error = -ENOENT; goto out; } - if (!connected) - error = disconnect(path, buf, name, flags); + /* 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; + } + } out: return error; @@ -185,7 +174,7 @@ if (info && error) { if (error == -ENOENT) *info = "Failed name lookup - deleted entry"; - else if (error == -ESTALE) + else if (error == -EACCES) *info = "Failed name lookup - disconnected path"; else if (error == -ENAMETOOLONG) *info = "Failed name lookup - name too long";