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

namei.c (10232B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * linux/fs/ext2/namei.c
      4 *
      5 * Rewrite to pagecache. Almost all code had been changed, so blame me
      6 * if the things go wrong. Please, send bug reports to
      7 * viro@parcelfarce.linux.theplanet.co.uk
      8 *
      9 * Stuff here is basically a glue between the VFS and generic UNIXish
     10 * filesystem that keeps everything in pagecache. All knowledge of the
     11 * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable
     12 * and it's easier to debug that way. In principle we might want to
     13 * generalize that a bit and turn it into a library. Or not.
     14 *
     15 * The only non-static object here is ext2_dir_inode_operations.
     16 *
     17 * TODO: get rid of kmap() use, add readahead.
     18 *
     19 * Copyright (C) 1992, 1993, 1994, 1995
     20 * Remy Card (card@masi.ibp.fr)
     21 * Laboratoire MASI - Institut Blaise Pascal
     22 * Universite Pierre et Marie Curie (Paris VI)
     23 *
     24 *  from
     25 *
     26 *  linux/fs/minix/namei.c
     27 *
     28 *  Copyright (C) 1991, 1992  Linus Torvalds
     29 *
     30 *  Big-endian to little-endian byte-swapping/bitmaps by
     31 *        David S. Miller (davem@caip.rutgers.edu), 1995
     32 */
     33
     34#include <linux/pagemap.h>
     35#include <linux/quotaops.h>
     36#include "ext2.h"
     37#include "xattr.h"
     38#include "acl.h"
     39
     40static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
     41{
     42	int err = ext2_add_link(dentry, inode);
     43	if (!err) {
     44		d_instantiate_new(dentry, inode);
     45		return 0;
     46	}
     47	inode_dec_link_count(inode);
     48	discard_new_inode(inode);
     49	return err;
     50}
     51
     52/*
     53 * Methods themselves.
     54 */
     55
     56static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
     57{
     58	struct inode * inode;
     59	ino_t ino;
     60	int res;
     61	
     62	if (dentry->d_name.len > EXT2_NAME_LEN)
     63		return ERR_PTR(-ENAMETOOLONG);
     64
     65	res = ext2_inode_by_name(dir, &dentry->d_name, &ino);
     66	if (res) {
     67		if (res != -ENOENT)
     68			return ERR_PTR(res);
     69		inode = NULL;
     70	} else {
     71		inode = ext2_iget(dir->i_sb, ino);
     72		if (inode == ERR_PTR(-ESTALE)) {
     73			ext2_error(dir->i_sb, __func__,
     74					"deleted inode referenced: %lu",
     75					(unsigned long) ino);
     76			return ERR_PTR(-EIO);
     77		}
     78	}
     79	return d_splice_alias(inode, dentry);
     80}
     81
     82struct dentry *ext2_get_parent(struct dentry *child)
     83{
     84	ino_t ino;
     85	int res;
     86
     87	res = ext2_inode_by_name(d_inode(child), &dotdot_name, &ino);
     88	if (res)
     89		return ERR_PTR(res);
     90
     91	return d_obtain_alias(ext2_iget(child->d_sb, ino));
     92} 
     93
     94/*
     95 * By the time this is called, we already have created
     96 * the directory cache entry for the new file, but it
     97 * is so far negative - it has no inode.
     98 *
     99 * If the create succeeds, we fill in the inode information
    100 * with d_instantiate(). 
    101 */
    102static int ext2_create (struct user_namespace * mnt_userns,
    103			struct inode * dir, struct dentry * dentry,
    104			umode_t mode, bool excl)
    105{
    106	struct inode *inode;
    107	int err;
    108
    109	err = dquot_initialize(dir);
    110	if (err)
    111		return err;
    112
    113	inode = ext2_new_inode(dir, mode, &dentry->d_name);
    114	if (IS_ERR(inode))
    115		return PTR_ERR(inode);
    116
    117	ext2_set_file_ops(inode);
    118	mark_inode_dirty(inode);
    119	return ext2_add_nondir(dentry, inode);
    120}
    121
    122static int ext2_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
    123			struct dentry *dentry, umode_t mode)
    124{
    125	struct inode *inode = ext2_new_inode(dir, mode, NULL);
    126	if (IS_ERR(inode))
    127		return PTR_ERR(inode);
    128
    129	ext2_set_file_ops(inode);
    130	mark_inode_dirty(inode);
    131	d_tmpfile(dentry, inode);
    132	unlock_new_inode(inode);
    133	return 0;
    134}
    135
    136static int ext2_mknod (struct user_namespace * mnt_userns, struct inode * dir,
    137	struct dentry *dentry, umode_t mode, dev_t rdev)
    138{
    139	struct inode * inode;
    140	int err;
    141
    142	err = dquot_initialize(dir);
    143	if (err)
    144		return err;
    145
    146	inode = ext2_new_inode (dir, mode, &dentry->d_name);
    147	err = PTR_ERR(inode);
    148	if (!IS_ERR(inode)) {
    149		init_special_inode(inode, inode->i_mode, rdev);
    150		inode->i_op = &ext2_special_inode_operations;
    151		mark_inode_dirty(inode);
    152		err = ext2_add_nondir(dentry, inode);
    153	}
    154	return err;
    155}
    156
    157static int ext2_symlink (struct user_namespace * mnt_userns, struct inode * dir,
    158	struct dentry * dentry, const char * symname)
    159{
    160	struct super_block * sb = dir->i_sb;
    161	int err = -ENAMETOOLONG;
    162	unsigned l = strlen(symname)+1;
    163	struct inode * inode;
    164
    165	if (l > sb->s_blocksize)
    166		goto out;
    167
    168	err = dquot_initialize(dir);
    169	if (err)
    170		goto out;
    171
    172	inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name);
    173	err = PTR_ERR(inode);
    174	if (IS_ERR(inode))
    175		goto out;
    176
    177	if (l > sizeof (EXT2_I(inode)->i_data)) {
    178		/* slow symlink */
    179		inode->i_op = &ext2_symlink_inode_operations;
    180		inode_nohighmem(inode);
    181		if (test_opt(inode->i_sb, NOBH))
    182			inode->i_mapping->a_ops = &ext2_nobh_aops;
    183		else
    184			inode->i_mapping->a_ops = &ext2_aops;
    185		err = page_symlink(inode, symname, l);
    186		if (err)
    187			goto out_fail;
    188	} else {
    189		/* fast symlink */
    190		inode->i_op = &ext2_fast_symlink_inode_operations;
    191		inode->i_link = (char*)EXT2_I(inode)->i_data;
    192		memcpy(inode->i_link, symname, l);
    193		inode->i_size = l-1;
    194	}
    195	mark_inode_dirty(inode);
    196
    197	err = ext2_add_nondir(dentry, inode);
    198out:
    199	return err;
    200
    201out_fail:
    202	inode_dec_link_count(inode);
    203	discard_new_inode(inode);
    204	goto out;
    205}
    206
    207static int ext2_link (struct dentry * old_dentry, struct inode * dir,
    208	struct dentry *dentry)
    209{
    210	struct inode *inode = d_inode(old_dentry);
    211	int err;
    212
    213	err = dquot_initialize(dir);
    214	if (err)
    215		return err;
    216
    217	inode->i_ctime = current_time(inode);
    218	inode_inc_link_count(inode);
    219	ihold(inode);
    220
    221	err = ext2_add_link(dentry, inode);
    222	if (!err) {
    223		d_instantiate(dentry, inode);
    224		return 0;
    225	}
    226	inode_dec_link_count(inode);
    227	iput(inode);
    228	return err;
    229}
    230
    231static int ext2_mkdir(struct user_namespace * mnt_userns,
    232	struct inode * dir, struct dentry * dentry, umode_t mode)
    233{
    234	struct inode * inode;
    235	int err;
    236
    237	err = dquot_initialize(dir);
    238	if (err)
    239		return err;
    240
    241	inode_inc_link_count(dir);
    242
    243	inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name);
    244	err = PTR_ERR(inode);
    245	if (IS_ERR(inode))
    246		goto out_dir;
    247
    248	inode->i_op = &ext2_dir_inode_operations;
    249	inode->i_fop = &ext2_dir_operations;
    250	if (test_opt(inode->i_sb, NOBH))
    251		inode->i_mapping->a_ops = &ext2_nobh_aops;
    252	else
    253		inode->i_mapping->a_ops = &ext2_aops;
    254
    255	inode_inc_link_count(inode);
    256
    257	err = ext2_make_empty(inode, dir);
    258	if (err)
    259		goto out_fail;
    260
    261	err = ext2_add_link(dentry, inode);
    262	if (err)
    263		goto out_fail;
    264
    265	d_instantiate_new(dentry, inode);
    266out:
    267	return err;
    268
    269out_fail:
    270	inode_dec_link_count(inode);
    271	inode_dec_link_count(inode);
    272	discard_new_inode(inode);
    273out_dir:
    274	inode_dec_link_count(dir);
    275	goto out;
    276}
    277
    278static int ext2_unlink(struct inode * dir, struct dentry *dentry)
    279{
    280	struct inode * inode = d_inode(dentry);
    281	struct ext2_dir_entry_2 * de;
    282	struct page * page;
    283	void *page_addr;
    284	int err;
    285
    286	err = dquot_initialize(dir);
    287	if (err)
    288		goto out;
    289
    290	de = ext2_find_entry(dir, &dentry->d_name, &page, &page_addr);
    291	if (IS_ERR(de)) {
    292		err = PTR_ERR(de);
    293		goto out;
    294	}
    295
    296	err = ext2_delete_entry (de, page, page_addr);
    297	ext2_put_page(page, page_addr);
    298	if (err)
    299		goto out;
    300
    301	inode->i_ctime = dir->i_ctime;
    302	inode_dec_link_count(inode);
    303	err = 0;
    304out:
    305	return err;
    306}
    307
    308static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
    309{
    310	struct inode * inode = d_inode(dentry);
    311	int err = -ENOTEMPTY;
    312
    313	if (ext2_empty_dir(inode)) {
    314		err = ext2_unlink(dir, dentry);
    315		if (!err) {
    316			inode->i_size = 0;
    317			inode_dec_link_count(inode);
    318			inode_dec_link_count(dir);
    319		}
    320	}
    321	return err;
    322}
    323
    324static int ext2_rename (struct user_namespace * mnt_userns,
    325			struct inode * old_dir, struct dentry * old_dentry,
    326			struct inode * new_dir, struct dentry * new_dentry,
    327			unsigned int flags)
    328{
    329	struct inode * old_inode = d_inode(old_dentry);
    330	struct inode * new_inode = d_inode(new_dentry);
    331	struct page * dir_page = NULL;
    332	void *dir_page_addr;
    333	struct ext2_dir_entry_2 * dir_de = NULL;
    334	struct page * old_page;
    335	void *old_page_addr;
    336	struct ext2_dir_entry_2 * old_de;
    337	int err;
    338
    339	if (flags & ~RENAME_NOREPLACE)
    340		return -EINVAL;
    341
    342	err = dquot_initialize(old_dir);
    343	if (err)
    344		goto out;
    345
    346	err = dquot_initialize(new_dir);
    347	if (err)
    348		goto out;
    349
    350	old_de = ext2_find_entry(old_dir, &old_dentry->d_name, &old_page,
    351				 &old_page_addr);
    352	if (IS_ERR(old_de)) {
    353		err = PTR_ERR(old_de);
    354		goto out;
    355	}
    356
    357	if (S_ISDIR(old_inode->i_mode)) {
    358		err = -EIO;
    359		dir_de = ext2_dotdot(old_inode, &dir_page, &dir_page_addr);
    360		if (!dir_de)
    361			goto out_old;
    362	}
    363
    364	if (new_inode) {
    365		void *page_addr;
    366		struct page *new_page;
    367		struct ext2_dir_entry_2 *new_de;
    368
    369		err = -ENOTEMPTY;
    370		if (dir_de && !ext2_empty_dir (new_inode))
    371			goto out_dir;
    372
    373		new_de = ext2_find_entry(new_dir, &new_dentry->d_name,
    374					 &new_page, &page_addr);
    375		if (IS_ERR(new_de)) {
    376			err = PTR_ERR(new_de);
    377			goto out_dir;
    378		}
    379		ext2_set_link(new_dir, new_de, new_page, page_addr, old_inode, 1);
    380		ext2_put_page(new_page, page_addr);
    381		new_inode->i_ctime = current_time(new_inode);
    382		if (dir_de)
    383			drop_nlink(new_inode);
    384		inode_dec_link_count(new_inode);
    385	} else {
    386		err = ext2_add_link(new_dentry, old_inode);
    387		if (err)
    388			goto out_dir;
    389		if (dir_de)
    390			inode_inc_link_count(new_dir);
    391	}
    392
    393	/*
    394	 * Like most other Unix systems, set the ctime for inodes on a
    395 	 * rename.
    396	 */
    397	old_inode->i_ctime = current_time(old_inode);
    398	mark_inode_dirty(old_inode);
    399
    400	ext2_delete_entry(old_de, old_page, old_page_addr);
    401
    402	if (dir_de) {
    403		if (old_dir != new_dir)
    404			ext2_set_link(old_inode, dir_de, dir_page,
    405				      dir_page_addr, new_dir, 0);
    406
    407		ext2_put_page(dir_page, dir_page_addr);
    408		inode_dec_link_count(old_dir);
    409	}
    410
    411	ext2_put_page(old_page, old_page_addr);
    412	return 0;
    413
    414out_dir:
    415	if (dir_de)
    416		ext2_put_page(dir_page, dir_page_addr);
    417out_old:
    418	ext2_put_page(old_page, old_page_addr);
    419out:
    420	return err;
    421}
    422
    423const struct inode_operations ext2_dir_inode_operations = {
    424	.create		= ext2_create,
    425	.lookup		= ext2_lookup,
    426	.link		= ext2_link,
    427	.unlink		= ext2_unlink,
    428	.symlink	= ext2_symlink,
    429	.mkdir		= ext2_mkdir,
    430	.rmdir		= ext2_rmdir,
    431	.mknod		= ext2_mknod,
    432	.rename		= ext2_rename,
    433	.listxattr	= ext2_listxattr,
    434	.getattr	= ext2_getattr,
    435	.setattr	= ext2_setattr,
    436	.get_acl	= ext2_get_acl,
    437	.set_acl	= ext2_set_acl,
    438	.tmpfile	= ext2_tmpfile,
    439	.fileattr_get	= ext2_fileattr_get,
    440	.fileattr_set	= ext2_fileattr_set,
    441};
    442
    443const struct inode_operations ext2_special_inode_operations = {
    444	.listxattr	= ext2_listxattr,
    445	.getattr	= ext2_getattr,
    446	.setattr	= ext2_setattr,
    447	.get_acl	= ext2_get_acl,
    448	.set_acl	= ext2_set_acl,
    449};