root/security/tomoyo/mount.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tomoyo_audit_mount_log
  2. tomoyo_check_mount_acl
  3. tomoyo_mount_acl
  4. tomoyo_mount_permission

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * security/tomoyo/mount.c
   4  *
   5  * Copyright (C) 2005-2011  NTT DATA CORPORATION
   6  */
   7 
   8 #include <linux/slab.h>
   9 #include <uapi/linux/mount.h>
  10 #include "common.h"
  11 
  12 /* String table for special mount operations. */
  13 static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = {
  14         [TOMOYO_MOUNT_BIND]            = "--bind",
  15         [TOMOYO_MOUNT_MOVE]            = "--move",
  16         [TOMOYO_MOUNT_REMOUNT]         = "--remount",
  17         [TOMOYO_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable",
  18         [TOMOYO_MOUNT_MAKE_PRIVATE]    = "--make-private",
  19         [TOMOYO_MOUNT_MAKE_SLAVE]      = "--make-slave",
  20         [TOMOYO_MOUNT_MAKE_SHARED]     = "--make-shared",
  21 };
  22 
  23 /**
  24  * tomoyo_audit_mount_log - Audit mount log.
  25  *
  26  * @r: Pointer to "struct tomoyo_request_info".
  27  *
  28  * Returns 0 on success, negative value otherwise.
  29  */
  30 static int tomoyo_audit_mount_log(struct tomoyo_request_info *r)
  31 {
  32         return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n",
  33                                  r->param.mount.dev->name,
  34                                  r->param.mount.dir->name,
  35                                  r->param.mount.type->name,
  36                                  r->param.mount.flags);
  37 }
  38 
  39 /**
  40  * tomoyo_check_mount_acl - Check permission for path path path number operation.
  41  *
  42  * @r:   Pointer to "struct tomoyo_request_info".
  43  * @ptr: Pointer to "struct tomoyo_acl_info".
  44  *
  45  * Returns true if granted, false otherwise.
  46  */
  47 static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
  48                                    const struct tomoyo_acl_info *ptr)
  49 {
  50         const struct tomoyo_mount_acl *acl =
  51                 container_of(ptr, typeof(*acl), head);
  52 
  53         return tomoyo_compare_number_union(r->param.mount.flags,
  54                                            &acl->flags) &&
  55                 tomoyo_compare_name_union(r->param.mount.type,
  56                                           &acl->fs_type) &&
  57                 tomoyo_compare_name_union(r->param.mount.dir,
  58                                           &acl->dir_name) &&
  59                 (!r->param.mount.need_dev ||
  60                  tomoyo_compare_name_union(r->param.mount.dev,
  61                                            &acl->dev_name));
  62 }
  63 
  64 /**
  65  * tomoyo_mount_acl - Check permission for mount() operation.
  66  *
  67  * @r:        Pointer to "struct tomoyo_request_info".
  68  * @dev_name: Name of device file. Maybe NULL.
  69  * @dir:      Pointer to "struct path".
  70  * @type:     Name of filesystem type.
  71  * @flags:    Mount options.
  72  *
  73  * Returns 0 on success, negative value otherwise.
  74  *
  75  * Caller holds tomoyo_read_lock().
  76  */
  77 static int tomoyo_mount_acl(struct tomoyo_request_info *r,
  78                             const char *dev_name,
  79                             const struct path *dir, const char *type,
  80                             unsigned long flags)
  81 {
  82         struct tomoyo_obj_info obj = { };
  83         struct path path;
  84         struct file_system_type *fstype = NULL;
  85         const char *requested_type = NULL;
  86         const char *requested_dir_name = NULL;
  87         const char *requested_dev_name = NULL;
  88         struct tomoyo_path_info rtype;
  89         struct tomoyo_path_info rdev;
  90         struct tomoyo_path_info rdir;
  91         int need_dev = 0;
  92         int error = -ENOMEM;
  93 
  94         r->obj = &obj;
  95 
  96         /* Get fstype. */
  97         requested_type = tomoyo_encode(type);
  98         if (!requested_type)
  99                 goto out;
 100         rtype.name = requested_type;
 101         tomoyo_fill_path_info(&rtype);
 102 
 103         /* Get mount point. */
 104         obj.path2 = *dir;
 105         requested_dir_name = tomoyo_realpath_from_path(dir);
 106         if (!requested_dir_name) {
 107                 error = -ENOMEM;
 108                 goto out;
 109         }
 110         rdir.name = requested_dir_name;
 111         tomoyo_fill_path_info(&rdir);
 112 
 113         /* Compare fs name. */
 114         if (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) {
 115                 /* dev_name is ignored. */
 116         } else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] ||
 117                    type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] ||
 118                    type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] ||
 119                    type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) {
 120                 /* dev_name is ignored. */
 121         } else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] ||
 122                    type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) {
 123                 need_dev = -1; /* dev_name is a directory */
 124         } else {
 125                 fstype = get_fs_type(type);
 126                 if (!fstype) {
 127                         error = -ENODEV;
 128                         goto out;
 129                 }
 130                 if (fstype->fs_flags & FS_REQUIRES_DEV)
 131                         /* dev_name is a block device file. */
 132                         need_dev = 1;
 133         }
 134         if (need_dev) {
 135                 /* Get mount point or device file. */
 136                 if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
 137                         error = -ENOENT;
 138                         goto out;
 139                 }
 140                 obj.path1 = path;
 141                 requested_dev_name = tomoyo_realpath_from_path(&path);
 142                 if (!requested_dev_name) {
 143                         error = -ENOENT;
 144                         goto out;
 145                 }
 146         } else {
 147                 /* Map dev_name to "<NULL>" if no dev_name given. */
 148                 if (!dev_name)
 149                         dev_name = "<NULL>";
 150                 requested_dev_name = tomoyo_encode(dev_name);
 151                 if (!requested_dev_name) {
 152                         error = -ENOMEM;
 153                         goto out;
 154                 }
 155         }
 156         rdev.name = requested_dev_name;
 157         tomoyo_fill_path_info(&rdev);
 158         r->param_type = TOMOYO_TYPE_MOUNT_ACL;
 159         r->param.mount.need_dev = need_dev;
 160         r->param.mount.dev = &rdev;
 161         r->param.mount.dir = &rdir;
 162         r->param.mount.type = &rtype;
 163         r->param.mount.flags = flags;
 164         do {
 165                 tomoyo_check_acl(r, tomoyo_check_mount_acl);
 166                 error = tomoyo_audit_mount_log(r);
 167         } while (error == TOMOYO_RETRY_REQUEST);
 168  out:
 169         kfree(requested_dev_name);
 170         kfree(requested_dir_name);
 171         if (fstype)
 172                 put_filesystem(fstype);
 173         kfree(requested_type);
 174         /* Drop refcount obtained by kern_path(). */
 175         if (obj.path1.dentry)
 176                 path_put(&obj.path1);
 177         return error;
 178 }
 179 
 180 /**
 181  * tomoyo_mount_permission - Check permission for mount() operation.
 182  *
 183  * @dev_name:  Name of device file. Maybe NULL.
 184  * @path:      Pointer to "struct path".
 185  * @type:      Name of filesystem type. Maybe NULL.
 186  * @flags:     Mount options.
 187  * @data_page: Optional data. Maybe NULL.
 188  *
 189  * Returns 0 on success, negative value otherwise.
 190  */
 191 int tomoyo_mount_permission(const char *dev_name, const struct path *path,
 192                             const char *type, unsigned long flags,
 193                             void *data_page)
 194 {
 195         struct tomoyo_request_info r;
 196         int error;
 197         int idx;
 198 
 199         if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT)
 200             == TOMOYO_CONFIG_DISABLED)
 201                 return 0;
 202         if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
 203                 flags &= ~MS_MGC_MSK;
 204         if (flags & MS_REMOUNT) {
 205                 type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT];
 206                 flags &= ~MS_REMOUNT;
 207         } else if (flags & MS_BIND) {
 208                 type = tomoyo_mounts[TOMOYO_MOUNT_BIND];
 209                 flags &= ~MS_BIND;
 210         } else if (flags & MS_SHARED) {
 211                 if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
 212                         return -EINVAL;
 213                 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];
 214                 flags &= ~MS_SHARED;
 215         } else if (flags & MS_PRIVATE) {
 216                 if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
 217                         return -EINVAL;
 218                 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE];
 219                 flags &= ~MS_PRIVATE;
 220         } else if (flags & MS_SLAVE) {
 221                 if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
 222                         return -EINVAL;
 223                 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE];
 224                 flags &= ~MS_SLAVE;
 225         } else if (flags & MS_UNBINDABLE) {
 226                 if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
 227                         return -EINVAL;
 228                 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];
 229                 flags &= ~MS_UNBINDABLE;
 230         } else if (flags & MS_MOVE) {
 231                 type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
 232                 flags &= ~MS_MOVE;
 233         }
 234         if (!type)
 235                 type = "<NULL>";
 236         idx = tomoyo_read_lock();
 237         error = tomoyo_mount_acl(&r, dev_name, path, type, flags);
 238         tomoyo_read_unlock(idx);
 239         return error;
 240 }

/* [<][>][^][v][top][bottom][index][help] */