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

file.c (10893B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
      4 */
      5
      6#include <linux/slab.h>
      7#include <linux/compat.h>
      8#include <linux/cred.h>
      9#include <linux/buffer_head.h>
     10#include <linux/blkdev.h>
     11
     12#include "exfat_raw.h"
     13#include "exfat_fs.h"
     14
     15static int exfat_cont_expand(struct inode *inode, loff_t size)
     16{
     17	struct address_space *mapping = inode->i_mapping;
     18	loff_t start = i_size_read(inode), count = size - i_size_read(inode);
     19	int err, err2;
     20
     21	err = generic_cont_expand_simple(inode, size);
     22	if (err)
     23		return err;
     24
     25	inode->i_ctime = inode->i_mtime = current_time(inode);
     26	mark_inode_dirty(inode);
     27
     28	if (!IS_SYNC(inode))
     29		return 0;
     30
     31	err = filemap_fdatawrite_range(mapping, start, start + count - 1);
     32	err2 = sync_mapping_buffers(mapping);
     33	if (!err)
     34		err = err2;
     35	err2 = write_inode_now(inode, 1);
     36	if (!err)
     37		err = err2;
     38	if (err)
     39		return err;
     40
     41	return filemap_fdatawait_range(mapping, start, start + count - 1);
     42}
     43
     44static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)
     45{
     46	mode_t allow_utime = sbi->options.allow_utime;
     47
     48	if (!uid_eq(current_fsuid(), inode->i_uid)) {
     49		if (in_group_p(inode->i_gid))
     50			allow_utime >>= 3;
     51		if (allow_utime & MAY_WRITE)
     52			return true;
     53	}
     54
     55	/* use a default check */
     56	return false;
     57}
     58
     59static int exfat_sanitize_mode(const struct exfat_sb_info *sbi,
     60		struct inode *inode, umode_t *mode_ptr)
     61{
     62	mode_t i_mode, mask, perm;
     63
     64	i_mode = inode->i_mode;
     65
     66	mask = (S_ISREG(i_mode) || S_ISLNK(i_mode)) ?
     67		sbi->options.fs_fmask : sbi->options.fs_dmask;
     68	perm = *mode_ptr & ~(S_IFMT | mask);
     69
     70	/* Of the r and x bits, all (subject to umask) must be present.*/
     71	if ((perm & 0555) != (i_mode & 0555))
     72		return -EPERM;
     73
     74	if (exfat_mode_can_hold_ro(inode)) {
     75		/*
     76		 * Of the w bits, either all (subject to umask) or none must
     77		 * be present.
     78		 */
     79		if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask)))
     80			return -EPERM;
     81	} else {
     82		/*
     83		 * If exfat_mode_can_hold_ro(inode) is false, can't change
     84		 * w bits.
     85		 */
     86		if ((perm & 0222) != (0222 & ~mask))
     87			return -EPERM;
     88	}
     89
     90	*mode_ptr &= S_IFMT | perm;
     91
     92	return 0;
     93}
     94
     95/* resize the file length */
     96int __exfat_truncate(struct inode *inode, loff_t new_size)
     97{
     98	unsigned int num_clusters_new, num_clusters_phys;
     99	unsigned int last_clu = EXFAT_FREE_CLUSTER;
    100	struct exfat_chain clu;
    101	struct super_block *sb = inode->i_sb;
    102	struct exfat_sb_info *sbi = EXFAT_SB(sb);
    103	struct exfat_inode_info *ei = EXFAT_I(inode);
    104	int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0;
    105
    106	/* check if the given file ID is opened */
    107	if (ei->type != TYPE_FILE && ei->type != TYPE_DIR)
    108		return -EPERM;
    109
    110	exfat_set_volume_dirty(sb);
    111
    112	num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi);
    113	num_clusters_phys = EXFAT_B_TO_CLU_ROUND_UP(ei->i_size_ondisk, sbi);
    114
    115	exfat_chain_set(&clu, ei->start_clu, num_clusters_phys, ei->flags);
    116
    117	if (new_size > 0) {
    118		/*
    119		 * Truncate FAT chain num_clusters after the first cluster
    120		 * num_clusters = min(new, phys);
    121		 */
    122		unsigned int num_clusters =
    123			min(num_clusters_new, num_clusters_phys);
    124
    125		/*
    126		 * Follow FAT chain
    127		 * (defensive coding - works fine even with corrupted FAT table
    128		 */
    129		if (clu.flags == ALLOC_NO_FAT_CHAIN) {
    130			clu.dir += num_clusters;
    131			clu.size -= num_clusters;
    132		} else {
    133			while (num_clusters > 0) {
    134				last_clu = clu.dir;
    135				if (exfat_get_next_cluster(sb, &(clu.dir)))
    136					return -EIO;
    137
    138				num_clusters--;
    139				clu.size--;
    140			}
    141		}
    142	} else {
    143		ei->flags = ALLOC_NO_FAT_CHAIN;
    144		ei->start_clu = EXFAT_EOF_CLUSTER;
    145	}
    146
    147	i_size_write(inode, new_size);
    148
    149	if (ei->type == TYPE_FILE)
    150		ei->attr |= ATTR_ARCHIVE;
    151
    152	/* update the directory entry */
    153	if (!evict) {
    154		struct timespec64 ts;
    155		struct exfat_dentry *ep, *ep2;
    156		struct exfat_entry_set_cache *es;
    157		int err;
    158
    159		es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
    160				ES_ALL_ENTRIES);
    161		if (!es)
    162			return -EIO;
    163		ep = exfat_get_dentry_cached(es, 0);
    164		ep2 = exfat_get_dentry_cached(es, 1);
    165
    166		ts = current_time(inode);
    167		exfat_set_entry_time(sbi, &ts,
    168				&ep->dentry.file.modify_tz,
    169				&ep->dentry.file.modify_time,
    170				&ep->dentry.file.modify_date,
    171				&ep->dentry.file.modify_time_cs);
    172		ep->dentry.file.attr = cpu_to_le16(ei->attr);
    173
    174		/* File size should be zero if there is no cluster allocated */
    175		if (ei->start_clu == EXFAT_EOF_CLUSTER) {
    176			ep2->dentry.stream.valid_size = 0;
    177			ep2->dentry.stream.size = 0;
    178		} else {
    179			ep2->dentry.stream.valid_size = cpu_to_le64(new_size);
    180			ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
    181		}
    182
    183		if (new_size == 0) {
    184			/* Any directory can not be truncated to zero */
    185			WARN_ON(ei->type != TYPE_FILE);
    186
    187			ep2->dentry.stream.flags = ALLOC_FAT_CHAIN;
    188			ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
    189		}
    190
    191		exfat_update_dir_chksum_with_entry_set(es);
    192		err = exfat_free_dentry_set(es, inode_needs_sync(inode));
    193		if (err)
    194			return err;
    195	}
    196
    197	/* cut off from the FAT chain */
    198	if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER &&
    199			last_clu != EXFAT_EOF_CLUSTER) {
    200		if (exfat_ent_set(sb, last_clu, EXFAT_EOF_CLUSTER))
    201			return -EIO;
    202	}
    203
    204	/* invalidate cache and free the clusters */
    205	/* clear exfat cache */
    206	exfat_cache_inval_inode(inode);
    207
    208	/* hint information */
    209	ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
    210	ei->hint_bmap.clu = EXFAT_EOF_CLUSTER;
    211
    212	/* hint_stat will be used if this is directory. */
    213	ei->hint_stat.eidx = 0;
    214	ei->hint_stat.clu = ei->start_clu;
    215	ei->hint_femp.eidx = EXFAT_HINT_NONE;
    216
    217	/* free the clusters */
    218	if (exfat_free_cluster(inode, &clu))
    219		return -EIO;
    220
    221	return 0;
    222}
    223
    224void exfat_truncate(struct inode *inode, loff_t size)
    225{
    226	struct super_block *sb = inode->i_sb;
    227	struct exfat_sb_info *sbi = EXFAT_SB(sb);
    228	struct exfat_inode_info *ei = EXFAT_I(inode);
    229	unsigned int blocksize = i_blocksize(inode);
    230	loff_t aligned_size;
    231	int err;
    232
    233	mutex_lock(&sbi->s_lock);
    234	if (ei->start_clu == 0) {
    235		/*
    236		 * Empty start_clu != ~0 (not allocated)
    237		 */
    238		exfat_fs_error(sb, "tried to truncate zeroed cluster.");
    239		goto write_size;
    240	}
    241
    242	err = __exfat_truncate(inode, i_size_read(inode));
    243	if (err)
    244		goto write_size;
    245
    246	inode->i_ctime = inode->i_mtime = current_time(inode);
    247	if (IS_DIRSYNC(inode))
    248		exfat_sync_inode(inode);
    249	else
    250		mark_inode_dirty(inode);
    251
    252	inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >>
    253				inode->i_blkbits;
    254write_size:
    255	aligned_size = i_size_read(inode);
    256	if (aligned_size & (blocksize - 1)) {
    257		aligned_size |= (blocksize - 1);
    258		aligned_size++;
    259	}
    260
    261	if (ei->i_size_ondisk > i_size_read(inode))
    262		ei->i_size_ondisk = aligned_size;
    263
    264	if (ei->i_size_aligned > i_size_read(inode))
    265		ei->i_size_aligned = aligned_size;
    266	mutex_unlock(&sbi->s_lock);
    267}
    268
    269int exfat_getattr(struct user_namespace *mnt_uerns, const struct path *path,
    270		  struct kstat *stat, unsigned int request_mask,
    271		  unsigned int query_flags)
    272{
    273	struct inode *inode = d_backing_inode(path->dentry);
    274	struct exfat_inode_info *ei = EXFAT_I(inode);
    275
    276	generic_fillattr(&init_user_ns, inode, stat);
    277	exfat_truncate_atime(&stat->atime);
    278	stat->result_mask |= STATX_BTIME;
    279	stat->btime.tv_sec = ei->i_crtime.tv_sec;
    280	stat->btime.tv_nsec = ei->i_crtime.tv_nsec;
    281	stat->blksize = EXFAT_SB(inode->i_sb)->cluster_size;
    282	return 0;
    283}
    284
    285int exfat_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
    286		  struct iattr *attr)
    287{
    288	struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb);
    289	struct inode *inode = dentry->d_inode;
    290	unsigned int ia_valid;
    291	int error;
    292
    293	if ((attr->ia_valid & ATTR_SIZE) &&
    294	    attr->ia_size > i_size_read(inode)) {
    295		error = exfat_cont_expand(inode, attr->ia_size);
    296		if (error || attr->ia_valid == ATTR_SIZE)
    297			return error;
    298		attr->ia_valid &= ~ATTR_SIZE;
    299	}
    300
    301	/* Check for setting the inode time. */
    302	ia_valid = attr->ia_valid;
    303	if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) &&
    304	    exfat_allow_set_time(sbi, inode)) {
    305		attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET |
    306				ATTR_TIMES_SET);
    307	}
    308
    309	error = setattr_prepare(&init_user_ns, dentry, attr);
    310	attr->ia_valid = ia_valid;
    311	if (error)
    312		goto out;
    313
    314	if (((attr->ia_valid & ATTR_UID) &&
    315	     !uid_eq(attr->ia_uid, sbi->options.fs_uid)) ||
    316	    ((attr->ia_valid & ATTR_GID) &&
    317	     !gid_eq(attr->ia_gid, sbi->options.fs_gid)) ||
    318	    ((attr->ia_valid & ATTR_MODE) &&
    319	     (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) {
    320		error = -EPERM;
    321		goto out;
    322	}
    323
    324	/*
    325	 * We don't return -EPERM here. Yes, strange, but this is too
    326	 * old behavior.
    327	 */
    328	if (attr->ia_valid & ATTR_MODE) {
    329		if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0)
    330			attr->ia_valid &= ~ATTR_MODE;
    331	}
    332
    333	if (attr->ia_valid & ATTR_SIZE) {
    334		error = exfat_block_truncate_page(inode, attr->ia_size);
    335		if (error)
    336			goto out;
    337
    338		down_write(&EXFAT_I(inode)->truncate_lock);
    339		truncate_setsize(inode, attr->ia_size);
    340		exfat_truncate(inode, attr->ia_size);
    341		up_write(&EXFAT_I(inode)->truncate_lock);
    342	}
    343
    344	setattr_copy(&init_user_ns, inode, attr);
    345	exfat_truncate_atime(&inode->i_atime);
    346	mark_inode_dirty(inode);
    347
    348out:
    349	return error;
    350}
    351
    352static int exfat_ioctl_fitrim(struct inode *inode, unsigned long arg)
    353{
    354	struct fstrim_range range;
    355	int ret = 0;
    356
    357	if (!capable(CAP_SYS_ADMIN))
    358		return -EPERM;
    359
    360	if (!bdev_max_discard_sectors(inode->i_sb->s_bdev))
    361		return -EOPNOTSUPP;
    362
    363	if (copy_from_user(&range, (struct fstrim_range __user *)arg, sizeof(range)))
    364		return -EFAULT;
    365
    366	range.minlen = max_t(unsigned int, range.minlen,
    367				bdev_discard_granularity(inode->i_sb->s_bdev));
    368
    369	ret = exfat_trim_fs(inode, &range);
    370	if (ret < 0)
    371		return ret;
    372
    373	if (copy_to_user((struct fstrim_range __user *)arg, &range, sizeof(range)))
    374		return -EFAULT;
    375
    376	return 0;
    377}
    378
    379long exfat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    380{
    381	struct inode *inode = file_inode(filp);
    382
    383	switch (cmd) {
    384	case FITRIM:
    385		return exfat_ioctl_fitrim(inode, arg);
    386	default:
    387		return -ENOTTY;
    388	}
    389}
    390
    391#ifdef CONFIG_COMPAT
    392long exfat_compat_ioctl(struct file *filp, unsigned int cmd,
    393				unsigned long arg)
    394{
    395	return exfat_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
    396}
    397#endif
    398
    399int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
    400{
    401	struct inode *inode = filp->f_mapping->host;
    402	int err;
    403
    404	err = __generic_file_fsync(filp, start, end, datasync);
    405	if (err)
    406		return err;
    407
    408	err = sync_blockdev(inode->i_sb->s_bdev);
    409	if (err)
    410		return err;
    411
    412	return blkdev_issue_flush(inode->i_sb->s_bdev);
    413}
    414
    415const struct file_operations exfat_file_operations = {
    416	.llseek		= generic_file_llseek,
    417	.read_iter	= generic_file_read_iter,
    418	.write_iter	= generic_file_write_iter,
    419	.unlocked_ioctl = exfat_ioctl,
    420#ifdef CONFIG_COMPAT
    421	.compat_ioctl = exfat_compat_ioctl,
    422#endif
    423	.mmap		= generic_file_mmap,
    424	.fsync		= exfat_file_fsync,
    425	.splice_read	= generic_file_splice_read,
    426	.splice_write	= iter_file_splice_write,
    427};
    428
    429const struct inode_operations exfat_file_inode_operations = {
    430	.setattr     = exfat_setattr,
    431	.getattr     = exfat_getattr,
    432};