LCOV - code coverage report
Current view: top level - security/apparmor - path.c (source / functions) Hit Total Coverage
Test: Real Lines: 0 68 0.0 %
Date: 2020-10-17 15:46:16 Functions: 0 3 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * AppArmor security module
       4                 :            :  *
       5                 :            :  * This file contains AppArmor function for pathnames
       6                 :            :  *
       7                 :            :  * Copyright (C) 1998-2008 Novell/SUSE
       8                 :            :  * Copyright 2009-2010 Canonical Ltd.
       9                 :            :  */
      10                 :            : 
      11                 :            : #include <linux/magic.h>
      12                 :            : #include <linux/mount.h>
      13                 :            : #include <linux/namei.h>
      14                 :            : #include <linux/nsproxy.h>
      15                 :            : #include <linux/path.h>
      16                 :            : #include <linux/sched.h>
      17                 :            : #include <linux/slab.h>
      18                 :            : #include <linux/fs_struct.h>
      19                 :            : 
      20                 :            : #include "include/apparmor.h"
      21                 :            : #include "include/path.h"
      22                 :            : #include "include/policy.h"
      23                 :            : 
      24                 :            : /* modified from dcache.c */
      25                 :            : static int prepend(char **buffer, int buflen, const char *str, int namelen)
      26                 :            : {
      27                 :          0 :         buflen -= namelen;
      28                 :          0 :         if (buflen < 0)
      29                 :            :                 return -ENAMETOOLONG;
      30                 :          0 :         *buffer -= namelen;
      31                 :          0 :         memcpy(*buffer, str, namelen);
      32                 :            :         return 0;
      33                 :            : }
      34                 :            : 
      35                 :            : #define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
      36                 :            : 
      37                 :            : /* If the path is not connected to the expected root,
      38                 :            :  * check if it is a sysctl and handle specially else remove any
      39                 :            :  * leading / that __d_path may have returned.
      40                 :            :  * Unless
      41                 :            :  *     specifically directed to connect the path,
      42                 :            :  * OR
      43                 :            :  *     if in a chroot and doing chroot relative paths and the path
      44                 :            :  *     resolves to the namespace root (would be connected outside
      45                 :            :  *     of chroot) and specifically directed to connect paths to
      46                 :            :  *     namespace root.
      47                 :            :  */
      48                 :          0 : static int disconnect(const struct path *path, char *buf, char **name,
      49                 :            :                       int flags, const char *disconnected)
      50                 :            : {
      51                 :            :         int error = 0;
      52                 :            : 
      53                 :          0 :         if (!(flags & PATH_CONNECT_PATH) &&
      54                 :          0 :             !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
      55                 :          0 :               our_mnt(path->mnt))) {
      56                 :            :                 /* disconnected path, don't return pathname starting
      57                 :            :                  * with '/'
      58                 :            :                  */
      59                 :            :                 error = -EACCES;
      60                 :          0 :                 if (**name == '/')
      61                 :          0 :                         *name = *name + 1;
      62                 :            :         } else {
      63                 :          0 :                 if (**name != '/')
      64                 :            :                         /* CONNECT_PATH with missing root */
      65                 :          0 :                         error = prepend(name, *name - buf, "/", 1);
      66                 :          0 :                 if (!error && disconnected)
      67                 :          0 :                         error = prepend(name, *name - buf, disconnected,
      68                 :          0 :                                         strlen(disconnected));
      69                 :            :         }
      70                 :            : 
      71                 :          0 :         return error;
      72                 :            : }
      73                 :            : 
      74                 :            : /**
      75                 :            :  * d_namespace_path - lookup a name associated with a given path
      76                 :            :  * @path: path to lookup  (NOT NULL)
      77                 :            :  * @buf:  buffer to store path to  (NOT NULL)
      78                 :            :  * @name: Returns - pointer for start of path name with in @buf (NOT NULL)
      79                 :            :  * @flags: flags controlling path lookup
      80                 :            :  * @disconnected: string to prefix to disconnected paths
      81                 :            :  *
      82                 :            :  * Handle path name lookup.
      83                 :            :  *
      84                 :            :  * Returns: %0 else error code if path lookup fails
      85                 :            :  *          When no error the path name is returned in @name which points to
      86                 :            :  *          to a position in @buf
      87                 :            :  */
      88                 :          0 : static int d_namespace_path(const struct path *path, char *buf, char **name,
      89                 :            :                             int flags, const char *disconnected)
      90                 :            : {
      91                 :            :         char *res;
      92                 :            :         int error = 0;
      93                 :            :         int connected = 1;
      94                 :          0 :         int isdir = (flags & PATH_IS_DIR) ? 1 : 0;
      95                 :          0 :         int buflen = aa_g_path_max - isdir;
      96                 :            : 
      97                 :          0 :         if (path->mnt->mnt_flags & MNT_INTERNAL) {
      98                 :            :                 /* it's not mounted anywhere */
      99                 :          0 :                 res = dentry_path(path->dentry, buf, buflen);
     100                 :          0 :                 *name = res;
     101                 :          0 :                 if (IS_ERR(res)) {
     102                 :          0 :                         *name = buf;
     103                 :          0 :                         return PTR_ERR(res);
     104                 :            :                 }
     105                 :          0 :                 if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
     106                 :          0 :                     strncmp(*name, "/sys/", 5) == 0) {
     107                 :            :                         /* TODO: convert over to using a per namespace
     108                 :            :                          * control instead of hard coded /proc
     109                 :            :                          */
     110                 :          0 :                         error = prepend(name, *name - buf, "/proc", 5);
     111                 :          0 :                         goto out;
     112                 :            :                 } else
     113                 :          0 :                         error = disconnect(path, buf, name, flags,
     114                 :            :                                            disconnected);
     115                 :          0 :                 goto out;
     116                 :            :         }
     117                 :            : 
     118                 :            :         /* resolve paths relative to chroot?*/
     119                 :          0 :         if (flags & PATH_CHROOT_REL) {
     120                 :            :                 struct path root;
     121                 :          0 :                 get_fs_root(current->fs, &root);
     122                 :          0 :                 res = __d_path(path, &root, buf, buflen);
     123                 :          0 :                 path_put(&root);
     124                 :            :         } else {
     125                 :          0 :                 res = d_absolute_path(path, buf, buflen);
     126                 :          0 :                 if (!our_mnt(path->mnt))
     127                 :            :                         connected = 0;
     128                 :            :         }
     129                 :            : 
     130                 :            :         /* handle error conditions - and still allow a partial path to
     131                 :            :          * be returned.
     132                 :            :          */
     133                 :          0 :         if (!res || IS_ERR(res)) {
     134                 :          0 :                 if (PTR_ERR(res) == -ENAMETOOLONG) {
     135                 :            :                         error = -ENAMETOOLONG;
     136                 :          0 :                         *name = buf;
     137                 :          0 :                         goto out;
     138                 :            :                 }
     139                 :            :                 connected = 0;
     140                 :          0 :                 res = dentry_path_raw(path->dentry, buf, buflen);
     141                 :          0 :                 if (IS_ERR(res)) {
     142                 :            :                         error = PTR_ERR(res);
     143                 :          0 :                         *name = buf;
     144                 :          0 :                         goto out;
     145                 :            :                 };
     146                 :          0 :         } else if (!our_mnt(path->mnt))
     147                 :            :                 connected = 0;
     148                 :            : 
     149                 :          0 :         *name = res;
     150                 :            : 
     151                 :          0 :         if (!connected)
     152                 :          0 :                 error = disconnect(path, buf, name, flags, disconnected);
     153                 :            : 
     154                 :            :         /* Handle two cases:
     155                 :            :          * 1. A deleted dentry && profile is not allowing mediation of deleted
     156                 :            :          * 2. On some filesystems, newly allocated dentries appear to the
     157                 :            :          *    security_path hooks as a deleted dentry except without an inode
     158                 :            :          *    allocated.
     159                 :            :          */
     160                 :          0 :         if (d_unlinked(path->dentry) && d_is_positive(path->dentry) &&
     161                 :          0 :             !(flags & (PATH_MEDIATE_DELETED | PATH_DELEGATE_DELETED))) {
     162                 :            :                         error = -ENOENT;
     163                 :          0 :                         goto out;
     164                 :            :         }
     165                 :            : 
     166                 :            : out:
     167                 :            :         /*
     168                 :            :          * Append "/" to the pathname.  The root directory is a special
     169                 :            :          * case; it already ends in slash.
     170                 :            :          */
     171                 :          0 :         if (!error && isdir && ((*name)[1] != '\0' || (*name)[0] != '/'))
     172                 :          0 :                 strcpy(&buf[aa_g_path_max - 2], "/");
     173                 :            : 
     174                 :          0 :         return error;
     175                 :            : }
     176                 :            : 
     177                 :            : /**
     178                 :            :  * aa_path_name - get the pathname to a buffer ensure dir / is appended
     179                 :            :  * @path: path the file  (NOT NULL)
     180                 :            :  * @flags: flags controlling path name generation
     181                 :            :  * @buffer: buffer to put name in (NOT NULL)
     182                 :            :  * @name: Returns - the generated path name if !error (NOT NULL)
     183                 :            :  * @info: Returns - information on why the path lookup failed (MAYBE NULL)
     184                 :            :  * @disconnected: string to prepend to disconnected paths
     185                 :            :  *
     186                 :            :  * @name is a pointer to the beginning of the pathname (which usually differs
     187                 :            :  * from the beginning of the buffer), or NULL.  If there is an error @name
     188                 :            :  * may contain a partial or invalid name that can be used for audit purposes,
     189                 :            :  * but it can not be used for mediation.
     190                 :            :  *
     191                 :            :  * We need PATH_IS_DIR to indicate whether the file is a directory or not
     192                 :            :  * because the file may not yet exist, and so we cannot check the inode's
     193                 :            :  * file type.
     194                 :            :  *
     195                 :            :  * Returns: %0 else error code if could retrieve name
     196                 :            :  */
     197                 :          0 : int aa_path_name(const struct path *path, int flags, char *buffer,
     198                 :            :                  const char **name, const char **info, const char *disconnected)
     199                 :            : {
     200                 :          0 :         char *str = NULL;
     201                 :          0 :         int error = d_namespace_path(path, buffer, &str, flags, disconnected);
     202                 :            : 
     203                 :          0 :         if (info && error) {
     204                 :          0 :                 if (error == -ENOENT)
     205                 :          0 :                         *info = "Failed name lookup - deleted entry";
     206                 :          0 :                 else if (error == -EACCES)
     207                 :          0 :                         *info = "Failed name lookup - disconnected path";
     208                 :          0 :                 else if (error == -ENAMETOOLONG)
     209                 :          0 :                         *info = "Failed name lookup - name too long";
     210                 :            :                 else
     211                 :          0 :                         *info = "Failed name lookup";
     212                 :            :         }
     213                 :            : 
     214                 :          0 :         *name = str;
     215                 :            : 
     216                 :          0 :         return error;
     217                 :            : }
    

Generated by: LCOV version 1.14