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

xattr_acl.c (9924B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/capability.h>
      3#include <linux/fs.h>
      4#include <linux/posix_acl.h>
      5#include "reiserfs.h"
      6#include <linux/errno.h>
      7#include <linux/pagemap.h>
      8#include <linux/xattr.h>
      9#include <linux/slab.h>
     10#include <linux/posix_acl_xattr.h>
     11#include "xattr.h"
     12#include "acl.h"
     13#include <linux/uaccess.h>
     14
     15static int __reiserfs_set_acl(struct reiserfs_transaction_handle *th,
     16			    struct inode *inode, int type,
     17			    struct posix_acl *acl);
     18
     19
     20int
     21reiserfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
     22		 struct posix_acl *acl, int type)
     23{
     24	int error, error2;
     25	struct reiserfs_transaction_handle th;
     26	size_t jcreate_blocks;
     27	int size = acl ? posix_acl_xattr_size(acl->a_count) : 0;
     28	int update_mode = 0;
     29	umode_t mode = inode->i_mode;
     30
     31	/*
     32	 * Pessimism: We can't assume that anything from the xattr root up
     33	 * has been created.
     34	 */
     35
     36	jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
     37			 reiserfs_xattr_nblocks(inode, size) * 2;
     38
     39	reiserfs_write_lock(inode->i_sb);
     40	error = journal_begin(&th, inode->i_sb, jcreate_blocks);
     41	reiserfs_write_unlock(inode->i_sb);
     42	if (error == 0) {
     43		if (type == ACL_TYPE_ACCESS && acl) {
     44			error = posix_acl_update_mode(&init_user_ns, inode,
     45						      &mode, &acl);
     46			if (error)
     47				goto unlock;
     48			update_mode = 1;
     49		}
     50		error = __reiserfs_set_acl(&th, inode, type, acl);
     51		if (!error && update_mode)
     52			inode->i_mode = mode;
     53unlock:
     54		reiserfs_write_lock(inode->i_sb);
     55		error2 = journal_end(&th);
     56		reiserfs_write_unlock(inode->i_sb);
     57		if (error2)
     58			error = error2;
     59	}
     60
     61	return error;
     62}
     63
     64/*
     65 * Convert from filesystem to in-memory representation.
     66 */
     67static struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t size)
     68{
     69	const char *end = (char *)value + size;
     70	int n, count;
     71	struct posix_acl *acl;
     72
     73	if (!value)
     74		return NULL;
     75	if (size < sizeof(reiserfs_acl_header))
     76		return ERR_PTR(-EINVAL);
     77	if (((reiserfs_acl_header *) value)->a_version !=
     78	    cpu_to_le32(REISERFS_ACL_VERSION))
     79		return ERR_PTR(-EINVAL);
     80	value = (char *)value + sizeof(reiserfs_acl_header);
     81	count = reiserfs_acl_count(size);
     82	if (count < 0)
     83		return ERR_PTR(-EINVAL);
     84	if (count == 0)
     85		return NULL;
     86	acl = posix_acl_alloc(count, GFP_NOFS);
     87	if (!acl)
     88		return ERR_PTR(-ENOMEM);
     89	for (n = 0; n < count; n++) {
     90		reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value;
     91		if ((char *)value + sizeof(reiserfs_acl_entry_short) > end)
     92			goto fail;
     93		acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);
     94		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
     95		switch (acl->a_entries[n].e_tag) {
     96		case ACL_USER_OBJ:
     97		case ACL_GROUP_OBJ:
     98		case ACL_MASK:
     99		case ACL_OTHER:
    100			value = (char *)value +
    101			    sizeof(reiserfs_acl_entry_short);
    102			break;
    103
    104		case ACL_USER:
    105			value = (char *)value + sizeof(reiserfs_acl_entry);
    106			if ((char *)value > end)
    107				goto fail;
    108			acl->a_entries[n].e_uid = 
    109				make_kuid(&init_user_ns,
    110					  le32_to_cpu(entry->e_id));
    111			break;
    112		case ACL_GROUP:
    113			value = (char *)value + sizeof(reiserfs_acl_entry);
    114			if ((char *)value > end)
    115				goto fail;
    116			acl->a_entries[n].e_gid =
    117				make_kgid(&init_user_ns,
    118					  le32_to_cpu(entry->e_id));
    119			break;
    120
    121		default:
    122			goto fail;
    123		}
    124	}
    125	if (value != end)
    126		goto fail;
    127	return acl;
    128
    129fail:
    130	posix_acl_release(acl);
    131	return ERR_PTR(-EINVAL);
    132}
    133
    134/*
    135 * Convert from in-memory to filesystem representation.
    136 */
    137static void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
    138{
    139	reiserfs_acl_header *ext_acl;
    140	char *e;
    141	int n;
    142
    143	*size = reiserfs_acl_size(acl->a_count);
    144	ext_acl = kmalloc(sizeof(reiserfs_acl_header) +
    145						  acl->a_count *
    146						  sizeof(reiserfs_acl_entry),
    147						  GFP_NOFS);
    148	if (!ext_acl)
    149		return ERR_PTR(-ENOMEM);
    150	ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION);
    151	e = (char *)ext_acl + sizeof(reiserfs_acl_header);
    152	for (n = 0; n < acl->a_count; n++) {
    153		const struct posix_acl_entry *acl_e = &acl->a_entries[n];
    154		reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e;
    155		entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag);
    156		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
    157		switch (acl->a_entries[n].e_tag) {
    158		case ACL_USER:
    159			entry->e_id = cpu_to_le32(
    160				from_kuid(&init_user_ns, acl_e->e_uid));
    161			e += sizeof(reiserfs_acl_entry);
    162			break;
    163		case ACL_GROUP:
    164			entry->e_id = cpu_to_le32(
    165				from_kgid(&init_user_ns, acl_e->e_gid));
    166			e += sizeof(reiserfs_acl_entry);
    167			break;
    168
    169		case ACL_USER_OBJ:
    170		case ACL_GROUP_OBJ:
    171		case ACL_MASK:
    172		case ACL_OTHER:
    173			e += sizeof(reiserfs_acl_entry_short);
    174			break;
    175
    176		default:
    177			goto fail;
    178		}
    179	}
    180	return (char *)ext_acl;
    181
    182fail:
    183	kfree(ext_acl);
    184	return ERR_PTR(-EINVAL);
    185}
    186
    187/*
    188 * Inode operation get_posix_acl().
    189 *
    190 * inode->i_mutex: down
    191 * BKL held [before 2.5.x]
    192 */
    193struct posix_acl *reiserfs_get_acl(struct inode *inode, int type, bool rcu)
    194{
    195	char *name, *value;
    196	struct posix_acl *acl;
    197	int size;
    198	int retval;
    199
    200	if (rcu)
    201		return ERR_PTR(-ECHILD);
    202
    203	switch (type) {
    204	case ACL_TYPE_ACCESS:
    205		name = XATTR_NAME_POSIX_ACL_ACCESS;
    206		break;
    207	case ACL_TYPE_DEFAULT:
    208		name = XATTR_NAME_POSIX_ACL_DEFAULT;
    209		break;
    210	default:
    211		BUG();
    212	}
    213
    214	size = reiserfs_xattr_get(inode, name, NULL, 0);
    215	if (size < 0) {
    216		if (size == -ENODATA || size == -ENOSYS)
    217			return NULL;
    218		return ERR_PTR(size);
    219	}
    220
    221	value = kmalloc(size, GFP_NOFS);
    222	if (!value)
    223		return ERR_PTR(-ENOMEM);
    224
    225	retval = reiserfs_xattr_get(inode, name, value, size);
    226	if (retval == -ENODATA || retval == -ENOSYS) {
    227		/*
    228		 * This shouldn't actually happen as it should have
    229		 * been caught above.. but just in case
    230		 */
    231		acl = NULL;
    232	} else if (retval < 0) {
    233		acl = ERR_PTR(retval);
    234	} else {
    235		acl = reiserfs_posix_acl_from_disk(value, retval);
    236	}
    237
    238	kfree(value);
    239	return acl;
    240}
    241
    242/*
    243 * Inode operation set_posix_acl().
    244 *
    245 * inode->i_mutex: down
    246 * BKL held [before 2.5.x]
    247 */
    248static int
    249__reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
    250		 int type, struct posix_acl *acl)
    251{
    252	char *name;
    253	void *value = NULL;
    254	size_t size = 0;
    255	int error;
    256
    257	switch (type) {
    258	case ACL_TYPE_ACCESS:
    259		name = XATTR_NAME_POSIX_ACL_ACCESS;
    260		break;
    261	case ACL_TYPE_DEFAULT:
    262		name = XATTR_NAME_POSIX_ACL_DEFAULT;
    263		if (!S_ISDIR(inode->i_mode))
    264			return acl ? -EACCES : 0;
    265		break;
    266	default:
    267		return -EINVAL;
    268	}
    269
    270	if (acl) {
    271		value = reiserfs_posix_acl_to_disk(acl, &size);
    272		if (IS_ERR(value))
    273			return (int)PTR_ERR(value);
    274	}
    275
    276	error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
    277
    278	/*
    279	 * Ensure that the inode gets dirtied if we're only using
    280	 * the mode bits and an old ACL didn't exist. We don't need
    281	 * to check if the inode is hashed here since we won't get
    282	 * called by reiserfs_inherit_default_acl().
    283	 */
    284	if (error == -ENODATA) {
    285		error = 0;
    286		if (type == ACL_TYPE_ACCESS) {
    287			inode->i_ctime = current_time(inode);
    288			mark_inode_dirty(inode);
    289		}
    290	}
    291
    292	kfree(value);
    293
    294	if (!error)
    295		set_cached_acl(inode, type, acl);
    296
    297	return error;
    298}
    299
    300/*
    301 * dir->i_mutex: locked,
    302 * inode is new and not released into the wild yet
    303 */
    304int
    305reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
    306			     struct inode *dir, struct dentry *dentry,
    307			     struct inode *inode)
    308{
    309	struct posix_acl *default_acl, *acl;
    310	int err = 0;
    311
    312	/* ACLs only get applied to files and directories */
    313	if (S_ISLNK(inode->i_mode))
    314		return 0;
    315
    316	/*
    317	 * ACLs can only be used on "new" objects, so if it's an old object
    318	 * there is nothing to inherit from
    319	 */
    320	if (get_inode_sd_version(dir) == STAT_DATA_V1)
    321		goto apply_umask;
    322
    323	/*
    324	 * Don't apply ACLs to objects in the .reiserfs_priv tree.. This
    325	 * would be useless since permissions are ignored, and a pain because
    326	 * it introduces locking cycles
    327	 */
    328	if (IS_PRIVATE(inode))
    329		goto apply_umask;
    330
    331	err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
    332	if (err)
    333		return err;
    334
    335	if (default_acl) {
    336		err = __reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
    337					 default_acl);
    338		posix_acl_release(default_acl);
    339	}
    340	if (acl) {
    341		if (!err)
    342			err = __reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS,
    343						 acl);
    344		posix_acl_release(acl);
    345	}
    346
    347	return err;
    348
    349apply_umask:
    350	/* no ACL, apply umask */
    351	inode->i_mode &= ~current_umask();
    352	return err;
    353}
    354
    355/* This is used to cache the default acl before a new object is created.
    356 * The biggest reason for this is to get an idea of how many blocks will
    357 * actually be required for the create operation if we must inherit an ACL.
    358 * An ACL write can add up to 3 object creations and an additional file write
    359 * so we'd prefer not to reserve that many blocks in the journal if we can.
    360 * It also has the advantage of not loading the ACL with a transaction open,
    361 * this may seem silly, but if the owner of the directory is doing the
    362 * creation, the ACL may not be loaded since the permissions wouldn't require
    363 * it.
    364 * We return the number of blocks required for the transaction.
    365 */
    366int reiserfs_cache_default_acl(struct inode *inode)
    367{
    368	struct posix_acl *acl;
    369	int nblocks = 0;
    370
    371	if (IS_PRIVATE(inode))
    372		return 0;
    373
    374	acl = get_acl(inode, ACL_TYPE_DEFAULT);
    375
    376	if (acl && !IS_ERR(acl)) {
    377		int size = reiserfs_acl_size(acl->a_count);
    378
    379		/* Other xattrs can be created during inode creation. We don't
    380		 * want to claim too many blocks, so we check to see if we
    381		 * need to create the tree to the xattrs, and then we
    382		 * just want two files. */
    383		nblocks = reiserfs_xattr_jcreate_nblocks(inode);
    384		nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
    385
    386		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
    387
    388		/* We need to account for writes + bitmaps for two files */
    389		nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
    390		posix_acl_release(acl);
    391	}
    392
    393	return nblocks;
    394}
    395
    396/*
    397 * Called under i_mutex
    398 */
    399int reiserfs_acl_chmod(struct inode *inode)
    400{
    401	if (IS_PRIVATE(inode))
    402		return 0;
    403	if (get_inode_sd_version(inode) == STAT_DATA_V1 ||
    404	    !reiserfs_posixacl(inode->i_sb))
    405		return 0;
    406
    407	return posix_acl_chmod(&init_user_ns, inode, inode->i_mode);
    408}