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

dir.c (9204B)


      1/*
      2 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
      3 */
      4
      5#include <linux/string.h>
      6#include <linux/errno.h>
      7#include <linux/fs.h>
      8#include "reiserfs.h"
      9#include <linux/stat.h>
     10#include <linux/buffer_head.h>
     11#include <linux/slab.h>
     12#include <linux/uaccess.h>
     13
     14extern const struct reiserfs_key MIN_KEY;
     15
     16static int reiserfs_readdir(struct file *, struct dir_context *);
     17static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
     18			      int datasync);
     19
     20const struct file_operations reiserfs_dir_operations = {
     21	.llseek = generic_file_llseek,
     22	.read = generic_read_dir,
     23	.iterate_shared = reiserfs_readdir,
     24	.fsync = reiserfs_dir_fsync,
     25	.unlocked_ioctl = reiserfs_ioctl,
     26#ifdef CONFIG_COMPAT
     27	.compat_ioctl = reiserfs_compat_ioctl,
     28#endif
     29};
     30
     31static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
     32			      int datasync)
     33{
     34	struct inode *inode = filp->f_mapping->host;
     35	int err;
     36
     37	err = file_write_and_wait_range(filp, start, end);
     38	if (err)
     39		return err;
     40
     41	inode_lock(inode);
     42	reiserfs_write_lock(inode->i_sb);
     43	err = reiserfs_commit_for_inode(inode);
     44	reiserfs_write_unlock(inode->i_sb);
     45	inode_unlock(inode);
     46	if (err < 0)
     47		return err;
     48	return 0;
     49}
     50
     51#define store_ih(where,what) copy_item_head (where, what)
     52
     53static inline bool is_privroot_deh(struct inode *dir, struct reiserfs_de_head *deh)
     54{
     55	struct dentry *privroot = REISERFS_SB(dir->i_sb)->priv_root;
     56	return (d_really_is_positive(privroot) &&
     57	        deh->deh_objectid == INODE_PKEY(d_inode(privroot))->k_objectid);
     58}
     59
     60int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
     61{
     62
     63	/* key of current position in the directory (key of directory entry) */
     64	struct cpu_key pos_key;
     65
     66	INITIALIZE_PATH(path_to_entry);
     67	struct buffer_head *bh;
     68	int item_num, entry_num;
     69	const struct reiserfs_key *rkey;
     70	struct item_head *ih, tmp_ih;
     71	int search_res;
     72	char *local_buf;
     73	loff_t next_pos;
     74	char small_buf[32];	/* avoid kmalloc if we can */
     75	struct reiserfs_dir_entry de;
     76	int ret = 0;
     77	int depth;
     78
     79	reiserfs_write_lock(inode->i_sb);
     80
     81	reiserfs_check_lock_depth(inode->i_sb, "readdir");
     82
     83	/*
     84	 * form key for search the next directory entry using
     85	 * f_pos field of file structure
     86	 */
     87	make_cpu_key(&pos_key, inode, ctx->pos ?: DOT_OFFSET, TYPE_DIRENTRY, 3);
     88	next_pos = cpu_key_k_offset(&pos_key);
     89
     90	path_to_entry.reada = PATH_READA;
     91	while (1) {
     92research:
     93		/*
     94		 * search the directory item, containing entry with
     95		 * specified key
     96		 */
     97		search_res =
     98		    search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry,
     99					&de);
    100		if (search_res == IO_ERROR) {
    101			/*
    102			 * FIXME: we could just skip part of directory
    103			 * which could not be read
    104			 */
    105			ret = -EIO;
    106			goto out;
    107		}
    108		entry_num = de.de_entry_num;
    109		bh = de.de_bh;
    110		item_num = de.de_item_num;
    111		ih = de.de_ih;
    112		store_ih(&tmp_ih, ih);
    113
    114		/* we must have found item, that is item of this directory, */
    115		RFALSE(COMP_SHORT_KEYS(&ih->ih_key, &pos_key),
    116		       "vs-9000: found item %h does not match to dir we readdir %K",
    117		       ih, &pos_key);
    118		RFALSE(item_num > B_NR_ITEMS(bh) - 1,
    119		       "vs-9005 item_num == %d, item amount == %d",
    120		       item_num, B_NR_ITEMS(bh));
    121
    122		/*
    123		 * and entry must be not more than number of entries
    124		 * in the item
    125		 */
    126		RFALSE(ih_entry_count(ih) < entry_num,
    127		       "vs-9010: entry number is too big %d (%d)",
    128		       entry_num, ih_entry_count(ih));
    129
    130		/*
    131		 * go through all entries in the directory item beginning
    132		 * from the entry, that has been found
    133		 */
    134		if (search_res == POSITION_FOUND
    135		    || entry_num < ih_entry_count(ih)) {
    136			struct reiserfs_de_head *deh =
    137			    B_I_DEH(bh, ih) + entry_num;
    138
    139			for (; entry_num < ih_entry_count(ih);
    140			     entry_num++, deh++) {
    141				int d_reclen;
    142				char *d_name;
    143				ino_t d_ino;
    144				loff_t cur_pos = deh_offset(deh);
    145
    146				/* it is hidden entry */
    147				if (!de_visible(deh))
    148					continue;
    149				d_reclen = entry_length(bh, ih, entry_num);
    150				d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh);
    151
    152				if (d_reclen <= 0 ||
    153				    d_name + d_reclen > bh->b_data + bh->b_size) {
    154					/*
    155					 * There is corrupted data in entry,
    156					 * We'd better stop here
    157					 */
    158					pathrelse(&path_to_entry);
    159					ret = -EIO;
    160					goto out;
    161				}
    162
    163				if (!d_name[d_reclen - 1])
    164					d_reclen = strlen(d_name);
    165
    166				/* too big to send back to VFS */
    167				if (d_reclen >
    168				    REISERFS_MAX_NAME(inode->i_sb->
    169						      s_blocksize)) {
    170					continue;
    171				}
    172
    173				/* Ignore the .reiserfs_priv entry */
    174				if (is_privroot_deh(inode, deh))
    175					continue;
    176
    177				ctx->pos = deh_offset(deh);
    178				d_ino = deh_objectid(deh);
    179				if (d_reclen <= 32) {
    180					local_buf = small_buf;
    181				} else {
    182					local_buf = kmalloc(d_reclen,
    183							    GFP_NOFS);
    184					if (!local_buf) {
    185						pathrelse(&path_to_entry);
    186						ret = -ENOMEM;
    187						goto out;
    188					}
    189					if (item_moved(&tmp_ih, &path_to_entry)) {
    190						kfree(local_buf);
    191						goto research;
    192					}
    193				}
    194
    195				/*
    196				 * Note, that we copy name to user space via
    197				 * temporary buffer (local_buf) because
    198				 * filldir will block if user space buffer is
    199				 * swapped out. At that time entry can move to
    200				 * somewhere else
    201				 */
    202				memcpy(local_buf, d_name, d_reclen);
    203
    204				/*
    205				 * Since filldir might sleep, we can release
    206				 * the write lock here for other waiters
    207				 */
    208				depth = reiserfs_write_unlock_nested(inode->i_sb);
    209				if (!dir_emit
    210				    (ctx, local_buf, d_reclen, d_ino,
    211				     DT_UNKNOWN)) {
    212					reiserfs_write_lock_nested(inode->i_sb, depth);
    213					if (local_buf != small_buf) {
    214						kfree(local_buf);
    215					}
    216					goto end;
    217				}
    218				reiserfs_write_lock_nested(inode->i_sb, depth);
    219				if (local_buf != small_buf) {
    220					kfree(local_buf);
    221				}
    222
    223				/* deh_offset(deh) may be invalid now. */
    224				next_pos = cur_pos + 1;
    225
    226				if (item_moved(&tmp_ih, &path_to_entry)) {
    227					set_cpu_key_k_offset(&pos_key,
    228							     next_pos);
    229					goto research;
    230				}
    231			}	/* for */
    232		}
    233
    234		/* end of directory has been reached */
    235		if (item_num != B_NR_ITEMS(bh) - 1)
    236			goto end;
    237
    238		/*
    239		 * item we went through is last item of node. Using right
    240		 * delimiting key check is it directory end
    241		 */
    242		rkey = get_rkey(&path_to_entry, inode->i_sb);
    243		if (!comp_le_keys(rkey, &MIN_KEY)) {
    244			/*
    245			 * set pos_key to key, that is the smallest and greater
    246			 * that key of the last entry in the item
    247			 */
    248			set_cpu_key_k_offset(&pos_key, next_pos);
    249			continue;
    250		}
    251
    252		/* end of directory has been reached */
    253		if (COMP_SHORT_KEYS(rkey, &pos_key)) {
    254			goto end;
    255		}
    256
    257		/* directory continues in the right neighboring block */
    258		set_cpu_key_k_offset(&pos_key,
    259				     le_key_k_offset(KEY_FORMAT_3_5, rkey));
    260
    261	}			/* while */
    262
    263end:
    264	ctx->pos = next_pos;
    265	pathrelse(&path_to_entry);
    266	reiserfs_check_path(&path_to_entry);
    267out:
    268	reiserfs_write_unlock(inode->i_sb);
    269	return ret;
    270}
    271
    272static int reiserfs_readdir(struct file *file, struct dir_context *ctx)
    273{
    274	return reiserfs_readdir_inode(file_inode(file), ctx);
    275}
    276
    277/*
    278 * compose directory item containing "." and ".." entries (entries are
    279 * not aligned to 4 byte boundary)
    280 */
    281void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid,
    282			    __le32 par_dirid, __le32 par_objid)
    283{
    284	struct reiserfs_de_head *dot, *dotdot;
    285
    286	memset(body, 0, EMPTY_DIR_SIZE_V1);
    287	dot = (struct reiserfs_de_head *)body;
    288	dotdot = dot + 1;
    289
    290	/* direntry header of "." */
    291	put_deh_offset(dot, DOT_OFFSET);
    292	/* these two are from make_le_item_head, and are LE */
    293	dot->deh_dir_id = dirid;
    294	dot->deh_objectid = objid;
    295	dot->deh_state = 0;	/* Endian safe if 0 */
    296	put_deh_location(dot, EMPTY_DIR_SIZE_V1 - strlen("."));
    297	mark_de_visible(dot);
    298
    299	/* direntry header of ".." */
    300	put_deh_offset(dotdot, DOT_DOT_OFFSET);
    301	/* key of ".." for the root directory */
    302	/* these two are from the inode, and are LE */
    303	dotdot->deh_dir_id = par_dirid;
    304	dotdot->deh_objectid = par_objid;
    305	dotdot->deh_state = 0;	/* Endian safe if 0 */
    306	put_deh_location(dotdot, deh_location(dot) - strlen(".."));
    307	mark_de_visible(dotdot);
    308
    309	/* copy ".." and "." */
    310	memcpy(body + deh_location(dot), ".", 1);
    311	memcpy(body + deh_location(dotdot), "..", 2);
    312}
    313
    314/* compose directory item containing "." and ".." entries */
    315void make_empty_dir_item(char *body, __le32 dirid, __le32 objid,
    316			 __le32 par_dirid, __le32 par_objid)
    317{
    318	struct reiserfs_de_head *dot, *dotdot;
    319
    320	memset(body, 0, EMPTY_DIR_SIZE);
    321	dot = (struct reiserfs_de_head *)body;
    322	dotdot = dot + 1;
    323
    324	/* direntry header of "." */
    325	put_deh_offset(dot, DOT_OFFSET);
    326	/* these two are from make_le_item_head, and are LE */
    327	dot->deh_dir_id = dirid;
    328	dot->deh_objectid = objid;
    329	dot->deh_state = 0;	/* Endian safe if 0 */
    330	put_deh_location(dot, EMPTY_DIR_SIZE - ROUND_UP(strlen(".")));
    331	mark_de_visible(dot);
    332
    333	/* direntry header of ".." */
    334	put_deh_offset(dotdot, DOT_DOT_OFFSET);
    335	/* key of ".." for the root directory */
    336	/* these two are from the inode, and are LE */
    337	dotdot->deh_dir_id = par_dirid;
    338	dotdot->deh_objectid = par_objid;
    339	dotdot->deh_state = 0;	/* Endian safe if 0 */
    340	put_deh_location(dotdot, deh_location(dot) - ROUND_UP(strlen("..")));
    341	mark_de_visible(dotdot);
    342
    343	/* copy ".." and "." */
    344	memcpy(body + deh_location(dot), ".", 1);
    345	memcpy(body + deh_location(dotdot), "..", 2);
    346}