cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mount.c (6897B)


      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. */
     13static 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 */
     30static 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 */
     47static 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 */
     77static 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 */
    191int 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}