LCOV - code coverage report
Current view: top level - security/apparmor - path.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 28 67 41.8 %
Date: 2014-02-18 Functions: 3 3 100.0 %
Branches: 17 58 29.3 %

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

Generated by: LCOV version 1.9