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

inode.c (10950B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  linux/fs/affs/inode.c
      4 *
      5 *  (c) 1996  Hans-Joachim Widmaier - Rewritten
      6 *
      7 *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
      8 *
      9 *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
     10 *
     11 *  (C) 1991  Linus Torvalds - minix filesystem
     12 */
     13#include <linux/sched.h>
     14#include <linux/cred.h>
     15#include <linux/gfp.h>
     16#include "affs.h"
     17
     18struct inode *affs_iget(struct super_block *sb, unsigned long ino)
     19{
     20	struct affs_sb_info	*sbi = AFFS_SB(sb);
     21	struct buffer_head	*bh;
     22	struct affs_tail	*tail;
     23	struct inode		*inode;
     24	u32			 block;
     25	u32			 size;
     26	u32			 prot;
     27	u16			 id;
     28
     29	inode = iget_locked(sb, ino);
     30	if (!inode)
     31		return ERR_PTR(-ENOMEM);
     32	if (!(inode->i_state & I_NEW))
     33		return inode;
     34
     35	pr_debug("affs_iget(%lu)\n", inode->i_ino);
     36
     37	block = inode->i_ino;
     38	bh = affs_bread(sb, block);
     39	if (!bh) {
     40		affs_warning(sb, "read_inode", "Cannot read block %d", block);
     41		goto bad_inode;
     42	}
     43	if (affs_checksum_block(sb, bh) || be32_to_cpu(AFFS_HEAD(bh)->ptype) != T_SHORT) {
     44		affs_warning(sb,"read_inode",
     45			   "Checksum or type (ptype=%d) error on inode %d",
     46			   AFFS_HEAD(bh)->ptype, block);
     47		goto bad_inode;
     48	}
     49
     50	tail = AFFS_TAIL(sb, bh);
     51	prot = be32_to_cpu(tail->protect);
     52
     53	inode->i_size = 0;
     54	set_nlink(inode, 1);
     55	inode->i_mode = 0;
     56	AFFS_I(inode)->i_extcnt = 1;
     57	AFFS_I(inode)->i_ext_last = ~1;
     58	AFFS_I(inode)->i_protect = prot;
     59	atomic_set(&AFFS_I(inode)->i_opencnt, 0);
     60	AFFS_I(inode)->i_blkcnt = 0;
     61	AFFS_I(inode)->i_lc = NULL;
     62	AFFS_I(inode)->i_lc_size = 0;
     63	AFFS_I(inode)->i_lc_shift = 0;
     64	AFFS_I(inode)->i_lc_mask = 0;
     65	AFFS_I(inode)->i_ac = NULL;
     66	AFFS_I(inode)->i_ext_bh = NULL;
     67	AFFS_I(inode)->mmu_private = 0;
     68	AFFS_I(inode)->i_lastalloc = 0;
     69	AFFS_I(inode)->i_pa_cnt = 0;
     70
     71	if (affs_test_opt(sbi->s_flags, SF_SETMODE))
     72		inode->i_mode = sbi->s_mode;
     73	else
     74		inode->i_mode = affs_prot_to_mode(prot);
     75
     76	id = be16_to_cpu(tail->uid);
     77	if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETUID))
     78		inode->i_uid = sbi->s_uid;
     79	else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
     80		i_uid_write(inode, 0);
     81	else
     82		i_uid_write(inode, id);
     83
     84	id = be16_to_cpu(tail->gid);
     85	if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETGID))
     86		inode->i_gid = sbi->s_gid;
     87	else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
     88		i_gid_write(inode, 0);
     89	else
     90		i_gid_write(inode, id);
     91
     92	switch (be32_to_cpu(tail->stype)) {
     93	case ST_ROOT:
     94		inode->i_uid = sbi->s_uid;
     95		inode->i_gid = sbi->s_gid;
     96		fallthrough;
     97	case ST_USERDIR:
     98		if (be32_to_cpu(tail->stype) == ST_USERDIR ||
     99		    affs_test_opt(sbi->s_flags, SF_SETMODE)) {
    100			if (inode->i_mode & S_IRUSR)
    101				inode->i_mode |= S_IXUSR;
    102			if (inode->i_mode & S_IRGRP)
    103				inode->i_mode |= S_IXGRP;
    104			if (inode->i_mode & S_IROTH)
    105				inode->i_mode |= S_IXOTH;
    106			inode->i_mode |= S_IFDIR;
    107		} else
    108			inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;
    109		/* Maybe it should be controlled by mount parameter? */
    110		//inode->i_mode |= S_ISVTX;
    111		inode->i_op = &affs_dir_inode_operations;
    112		inode->i_fop = &affs_dir_operations;
    113		break;
    114	case ST_LINKDIR:
    115#if 0
    116		affs_warning(sb, "read_inode", "inode is LINKDIR");
    117		goto bad_inode;
    118#else
    119		inode->i_mode |= S_IFDIR;
    120		/* ... and leave ->i_op and ->i_fop pointing to empty */
    121		break;
    122#endif
    123	case ST_LINKFILE:
    124		affs_warning(sb, "read_inode", "inode is LINKFILE");
    125		goto bad_inode;
    126	case ST_FILE:
    127		size = be32_to_cpu(tail->size);
    128		inode->i_mode |= S_IFREG;
    129		AFFS_I(inode)->mmu_private = inode->i_size = size;
    130		if (inode->i_size) {
    131			AFFS_I(inode)->i_blkcnt = (size - 1) /
    132					       sbi->s_data_blksize + 1;
    133			AFFS_I(inode)->i_extcnt = (AFFS_I(inode)->i_blkcnt - 1) /
    134					       sbi->s_hashsize + 1;
    135		}
    136		if (tail->link_chain)
    137			set_nlink(inode, 2);
    138		inode->i_mapping->a_ops = affs_test_opt(sbi->s_flags, SF_OFS) ?
    139					  &affs_aops_ofs : &affs_aops;
    140		inode->i_op = &affs_file_inode_operations;
    141		inode->i_fop = &affs_file_operations;
    142		break;
    143	case ST_SOFTLINK:
    144		inode->i_size = strlen((char *)AFFS_HEAD(bh)->table);
    145		inode->i_mode |= S_IFLNK;
    146		inode_nohighmem(inode);
    147		inode->i_op = &affs_symlink_inode_operations;
    148		inode->i_data.a_ops = &affs_symlink_aops;
    149		break;
    150	}
    151
    152	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec
    153		       = (be32_to_cpu(tail->change.days) * 86400LL +
    154		         be32_to_cpu(tail->change.mins) * 60 +
    155			 be32_to_cpu(tail->change.ticks) / 50 +
    156			 AFFS_EPOCH_DELTA) +
    157			 sys_tz.tz_minuteswest * 60;
    158	inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
    159	affs_brelse(bh);
    160	unlock_new_inode(inode);
    161	return inode;
    162
    163bad_inode:
    164	affs_brelse(bh);
    165	iget_failed(inode);
    166	return ERR_PTR(-EIO);
    167}
    168
    169int
    170affs_write_inode(struct inode *inode, struct writeback_control *wbc)
    171{
    172	struct super_block	*sb = inode->i_sb;
    173	struct buffer_head	*bh;
    174	struct affs_tail	*tail;
    175	uid_t			 uid;
    176	gid_t			 gid;
    177
    178	pr_debug("write_inode(%lu)\n", inode->i_ino);
    179
    180	if (!inode->i_nlink)
    181		// possibly free block
    182		return 0;
    183	bh = affs_bread(sb, inode->i_ino);
    184	if (!bh) {
    185		affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
    186		return -EIO;
    187	}
    188	tail = AFFS_TAIL(sb, bh);
    189	if (tail->stype == cpu_to_be32(ST_ROOT)) {
    190		affs_secs_to_datestamp(inode->i_mtime.tv_sec,
    191				       &AFFS_ROOT_TAIL(sb, bh)->root_change);
    192	} else {
    193		tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
    194		tail->size = cpu_to_be32(inode->i_size);
    195		affs_secs_to_datestamp(inode->i_mtime.tv_sec, &tail->change);
    196		if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) {
    197			uid = i_uid_read(inode);
    198			gid = i_gid_read(inode);
    199			if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_MUFS)) {
    200				if (uid == 0 || uid == 0xFFFF)
    201					uid = uid ^ ~0;
    202				if (gid == 0 || gid == 0xFFFF)
    203					gid = gid ^ ~0;
    204			}
    205			if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETUID))
    206				tail->uid = cpu_to_be16(uid);
    207			if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETGID))
    208				tail->gid = cpu_to_be16(gid);
    209		}
    210	}
    211	affs_fix_checksum(sb, bh);
    212	mark_buffer_dirty_inode(bh, inode);
    213	affs_brelse(bh);
    214	affs_free_prealloc(inode);
    215	return 0;
    216}
    217
    218int
    219affs_notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
    220		   struct iattr *attr)
    221{
    222	struct inode *inode = d_inode(dentry);
    223	int error;
    224
    225	pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
    226
    227	error = setattr_prepare(&init_user_ns, dentry, attr);
    228	if (error)
    229		goto out;
    230
    231	if (((attr->ia_valid & ATTR_UID) &&
    232	      affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETUID)) ||
    233	    ((attr->ia_valid & ATTR_GID) &&
    234	      affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETGID)) ||
    235	    ((attr->ia_valid & ATTR_MODE) &&
    236	     (AFFS_SB(inode->i_sb)->s_flags &
    237	      (AFFS_MOUNT_SF_SETMODE | AFFS_MOUNT_SF_IMMUTABLE)))) {
    238		if (!affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_QUIET))
    239			error = -EPERM;
    240		goto out;
    241	}
    242
    243	if ((attr->ia_valid & ATTR_SIZE) &&
    244	    attr->ia_size != i_size_read(inode)) {
    245		error = inode_newsize_ok(inode, attr->ia_size);
    246		if (error)
    247			return error;
    248
    249		truncate_setsize(inode, attr->ia_size);
    250		affs_truncate(inode);
    251	}
    252
    253	setattr_copy(&init_user_ns, inode, attr);
    254	mark_inode_dirty(inode);
    255
    256	if (attr->ia_valid & ATTR_MODE)
    257		affs_mode_to_prot(inode);
    258out:
    259	return error;
    260}
    261
    262void
    263affs_evict_inode(struct inode *inode)
    264{
    265	unsigned long cache_page;
    266	pr_debug("evict_inode(ino=%lu, nlink=%u)\n",
    267		 inode->i_ino, inode->i_nlink);
    268	truncate_inode_pages_final(&inode->i_data);
    269
    270	if (!inode->i_nlink) {
    271		inode->i_size = 0;
    272		affs_truncate(inode);
    273	}
    274
    275	invalidate_inode_buffers(inode);
    276	clear_inode(inode);
    277	affs_free_prealloc(inode);
    278	cache_page = (unsigned long)AFFS_I(inode)->i_lc;
    279	if (cache_page) {
    280		pr_debug("freeing ext cache\n");
    281		AFFS_I(inode)->i_lc = NULL;
    282		AFFS_I(inode)->i_ac = NULL;
    283		free_page(cache_page);
    284	}
    285	affs_brelse(AFFS_I(inode)->i_ext_bh);
    286	AFFS_I(inode)->i_ext_last = ~1;
    287	AFFS_I(inode)->i_ext_bh = NULL;
    288
    289	if (!inode->i_nlink)
    290		affs_free_block(inode->i_sb, inode->i_ino);
    291}
    292
    293struct inode *
    294affs_new_inode(struct inode *dir)
    295{
    296	struct super_block	*sb = dir->i_sb;
    297	struct inode		*inode;
    298	u32			 block;
    299	struct buffer_head	*bh;
    300
    301	if (!(inode = new_inode(sb)))
    302		goto err_inode;
    303
    304	if (!(block = affs_alloc_block(dir, dir->i_ino)))
    305		goto err_block;
    306
    307	bh = affs_getzeroblk(sb, block);
    308	if (!bh)
    309		goto err_bh;
    310	mark_buffer_dirty_inode(bh, inode);
    311	affs_brelse(bh);
    312
    313	inode->i_uid     = current_fsuid();
    314	inode->i_gid     = current_fsgid();
    315	inode->i_ino     = block;
    316	set_nlink(inode, 1);
    317	inode->i_mtime   = inode->i_atime = inode->i_ctime = current_time(inode);
    318	atomic_set(&AFFS_I(inode)->i_opencnt, 0);
    319	AFFS_I(inode)->i_blkcnt = 0;
    320	AFFS_I(inode)->i_lc = NULL;
    321	AFFS_I(inode)->i_lc_size = 0;
    322	AFFS_I(inode)->i_lc_shift = 0;
    323	AFFS_I(inode)->i_lc_mask = 0;
    324	AFFS_I(inode)->i_ac = NULL;
    325	AFFS_I(inode)->i_ext_bh = NULL;
    326	AFFS_I(inode)->mmu_private = 0;
    327	AFFS_I(inode)->i_protect = 0;
    328	AFFS_I(inode)->i_lastalloc = 0;
    329	AFFS_I(inode)->i_pa_cnt = 0;
    330	AFFS_I(inode)->i_extcnt = 1;
    331	AFFS_I(inode)->i_ext_last = ~1;
    332
    333	insert_inode_hash(inode);
    334
    335	return inode;
    336
    337err_bh:
    338	affs_free_block(sb, block);
    339err_block:
    340	iput(inode);
    341err_inode:
    342	return NULL;
    343}
    344
    345/*
    346 * Add an entry to a directory. Create the header block
    347 * and insert it into the hash table.
    348 */
    349
    350int
    351affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type)
    352{
    353	struct super_block *sb = dir->i_sb;
    354	struct buffer_head *inode_bh = NULL;
    355	struct buffer_head *bh;
    356	u32 block = 0;
    357	int retval;
    358
    359	pr_debug("%s(dir=%lu, inode=%lu, \"%pd\", type=%d)\n", __func__,
    360		 dir->i_ino, inode->i_ino, dentry, type);
    361
    362	retval = -EIO;
    363	bh = affs_bread(sb, inode->i_ino);
    364	if (!bh)
    365		goto done;
    366
    367	affs_lock_link(inode);
    368	switch (type) {
    369	case ST_LINKFILE:
    370	case ST_LINKDIR:
    371		retval = -ENOSPC;
    372		block = affs_alloc_block(dir, dir->i_ino);
    373		if (!block)
    374			goto err;
    375		retval = -EIO;
    376		inode_bh = bh;
    377		bh = affs_getzeroblk(sb, block);
    378		if (!bh)
    379			goto err;
    380		break;
    381	default:
    382		break;
    383	}
    384
    385	AFFS_HEAD(bh)->ptype = cpu_to_be32(T_SHORT);
    386	AFFS_HEAD(bh)->key = cpu_to_be32(bh->b_blocknr);
    387	affs_copy_name(AFFS_TAIL(sb, bh)->name, dentry);
    388	AFFS_TAIL(sb, bh)->stype = cpu_to_be32(type);
    389	AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
    390
    391	if (inode_bh) {
    392		__be32 chain;
    393	       	chain = AFFS_TAIL(sb, inode_bh)->link_chain;
    394		AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
    395		AFFS_TAIL(sb, bh)->link_chain = chain;
    396		AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
    397		affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
    398		mark_buffer_dirty_inode(inode_bh, inode);
    399		set_nlink(inode, 2);
    400		ihold(inode);
    401	}
    402	affs_fix_checksum(sb, bh);
    403	mark_buffer_dirty_inode(bh, inode);
    404	dentry->d_fsdata = (void *)(long)bh->b_blocknr;
    405
    406	affs_lock_dir(dir);
    407	retval = affs_insert_hash(dir, bh);
    408	mark_buffer_dirty_inode(bh, inode);
    409	affs_unlock_dir(dir);
    410	affs_unlock_link(inode);
    411
    412	d_instantiate(dentry, inode);
    413done:
    414	affs_brelse(inode_bh);
    415	affs_brelse(bh);
    416	return retval;
    417err:
    418	if (block)
    419		affs_free_block(sb, block);
    420	affs_unlock_link(inode);
    421	goto done;
    422}