Beispiel #1
0
/* this @nd *IS* still used */
static void wrapfs_put_link(struct dentry *dentry, struct nameidata *nd,
			    void *cookie)
{
	char *buf = nd_get_link(nd);

	if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	if (!IS_ERR(buf))	/* free the char* */
		kfree(buf);

	if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE)
		DEBUG_MESG("Exit");
}
Beispiel #2
0
static int wrapfs_readdir(struct file *file, void *dirent, filldir_t filldir)
{
	int err = 0;
	struct file *lower_file = NULL;
	struct dentry *wrapfs_dentry = file->f_path.dentry;
#ifdef EXTRA_CREDIT
	struct wrapfs_getdents_callback buf;
	
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

	lower_file = wrapfs_lower_file(file);
	// lower_file->f_pos = file->f_pos;

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_OTHER)
		DEBUG_MESG("Encrypting and Decrypting filenames");

	memset(&buf, 0, sizeof(buf));
	buf.dirent = dirent;
	buf.dentry = wrapfs_dentry;
	buf.filldir = filldir;
	buf.filldir_called = 0;
	buf.entries_written = 0;

	err = vfs_readdir(lower_file, wrapfs_filldir, (void *)&buf);

	if(err<0)
		goto out;
	if(buf.filldir_called && !buf.entries_written) {
		printk(KERN_ERR "wrapfs_readdir: filldir called but entries not written\n");
		goto out;
	}
#else
	err = vfs_readdir(lower_file, filldir, dirent);
#endif

	file->f_pos = lower_file->f_pos;
	if (err >= 0)		/* copy the atime */
		fsstack_copy_attr_atime(wrapfs_dentry->d_inode, lower_file->f_path.dentry->d_inode);

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);

out:
#endif
	return err;
}
Beispiel #3
0
static int wrapfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
{
	int err;
	struct dentry *lower_dentry;
	struct path lower_path;

	if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	if (!lower_dentry->d_inode->i_op ||
	    !lower_dentry->d_inode->i_op->readlink) {
		err = -EINVAL;
		goto out;
	}

	err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
						    buf, bufsiz);
	if (err < 0)
		goto out;
	fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);

out:
	wrapfs_put_lower_path(dentry, &lower_path);

	if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #4
0
static int wrapfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
	int err;
	struct file *lower_file;
	struct path lower_path;
	struct dentry *dentry = file->f_path.dentry;

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

	err = generic_file_fsync(file, start, end, datasync);
	if (err)
		goto out;
	lower_file = wrapfs_lower_file(file);
	wrapfs_get_lower_path(dentry, &lower_path);
	err = vfs_fsync_range(lower_file, start, end, datasync);
	wrapfs_put_lower_path(dentry, &lower_path);
out:

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);
#endif

	return err;
}
Beispiel #5
0
static ssize_t wrapfs_write(struct file *file, const char __user *buf,
			    size_t count, loff_t *ppos)
{
	int err = 0;
	struct file *lower_file;
	struct dentry *dentry = file->f_path.dentry;

	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");

	// printk("wrapfs_write: Writing '%s'\n", file->f_dentry->d_iname);

	lower_file = wrapfs_lower_file(file);
	err = vfs_write(lower_file, buf, count, ppos);
	/* update our inode times+sizes upon a successful lower write */
	if (err >= 0) {
		fsstack_copy_inode_size(dentry->d_inode,
					lower_file->f_path.dentry->d_inode);
		fsstack_copy_attr_times(dentry->d_inode,
					lower_file->f_path.dentry->d_inode);
	}

	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #6
0
static long wrapfs_compat_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{
	long err = -ENOTTY;
	struct file *lower_file;

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

	lower_file = wrapfs_lower_file(file);

	/* XXX: use vfs_ioctl if/when VFS exports it */
	if (!lower_file || !lower_file->f_op)
		goto out;
	if (lower_file->f_op->compat_ioctl)
		err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);

out:

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);
#endif

	return err;
}
Beispiel #7
0
struct dentry *wrapfs_mount(struct file_system_type *fs_type, int flags,
			    const char *dev_name, void *raw_data)
{
	void *lower_path_name = (void *) dev_name;
	struct dentry *sb_dentry;
	struct wrapfs_mnt_opt mount_options;
	int retval=0;

	DEBUG_MESG("Enter");
	retval = wrapfs_parse_options(raw_data, &mount_options);
	if(retval<0)
	{
		printk("wrapfs_mount: Error parsing options\n");
		goto out;
	}
    
	sb_dentry = mount_nodev(fs_type, flags, lower_path_name, wrapfs_read_super);

	if(!sb_dentry)
		printk(KERN_ERR "sb_dentry is null\n");
	
	printk("**********************************************\n");

	wrapfs_set_mount_options(sb_dentry->d_sb, mount_options);

#ifdef WRAPFS_CRYPTO
	WRAPFS_SB(sb_dentry->d_sb)->has_key = FALSE; // make sure to set it to FALSE ???
#endif
	

	// printk("%d\n", wrapfs_get_debug(sb_dentry->d_sb));

	//memset(((struct wrapfs_sb_info *)(sb)->s_fs_info)->key, '0', KEYLEN + 1);
	//((struct wrapfs_sb_info *)(sb)->s_fs_info)->key[KEYLEN] = '\0';
	
	DEBUG_MESG("Exit");

	return sb_dentry;

out:
	return ERR_PTR(retval);
}
Beispiel #8
0
static int wrapfs_create(struct inode *dir, struct dentry *dentry,
			 int mode, struct nameidata *nd)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path, saved_path;

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;

	/* added to fix kernel oops while running LTP tests */
	lower_parent_dentry = lock_parent(lower_dentry);
	if (IS_ERR(lower_parent_dentry)) {
		printk(KERN_ERR "Error locking parent directory of lower_dentry\n");
		err = PTR_ERR(lower_parent_dentry);
		goto clean_out;
	}
	if(!lower_parent_dentry)
		goto clean_out;

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;

	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);
	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd);
	pathcpy(&nd->path, &saved_path);
	if (err)
		goto out;

	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
clean_out:
	wrapfs_put_lower_path(dentry, &lower_path);
	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);
	return err;
}
Beispiel #9
0
static int wrapfs_open(struct inode *inode, struct file *file)
{
	int err = 0;
	struct file *lower_file = NULL;
	struct path lower_path;

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

	/* don't open unhashed/deleted files */
	if (d_unhashed(file->f_path.dentry)) {
		err = -ENOENT;
		goto out_err;
	}

	file->private_data = kzalloc(sizeof(struct wrapfs_file_info), GFP_KERNEL);
	if (!WRAPFS_F(file)) {
		err = -ENOMEM;
		goto out_err;
	}

	/* open lower object and link wrapfs's file struct to lower's */
	wrapfs_get_lower_path(file->f_path.dentry, &lower_path);
	lower_file = dentry_open(lower_path.dentry, lower_path.mnt,
				 file->f_flags, current_cred());
	if (IS_ERR(lower_file)) {
		err = PTR_ERR(lower_file);
		lower_file = wrapfs_lower_file(file);
		if (lower_file) {
			wrapfs_set_lower_file(file, NULL);
			fput(lower_file); /* fput calls dput for lower_dentry */
		}
	} else {
		wrapfs_set_lower_file(file, lower_file);
	}

	if (err)
		kfree(WRAPFS_F(file));
	else
		fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode));
out_err:

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);
#endif

	return err;
}
Beispiel #10
0
/* release all lower object references & free the file info structure */
static int wrapfs_file_release(struct inode *inode, struct file *file)
{
	struct file *lower_file;

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

	lower_file = wrapfs_lower_file(file);
	if (lower_file) {
		wrapfs_set_lower_file(file, NULL);
		fput(lower_file);
	}

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Exit");
#endif 

	kfree(WRAPFS_F(file));
	return 0;
}
Beispiel #11
0
static int wrapfs_unlink(struct inode *dir, struct dentry *dentry)
{
	int err;
	struct dentry *lower_dentry;
	struct inode *lower_dir_inode = wrapfs_lower_inode(dir);
	struct dentry *lower_dir_dentry;
	struct path lower_path;

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	dget(lower_dentry);
	lower_dir_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;
	err = vfs_unlink(lower_dir_inode, lower_dentry);

	/*
	 * Note: unlinking on top of NFS can cause silly-renamed files.
	 * Trying to delete such files results in EBUSY from NFS
	 * below.  Silly-renamed files will get deleted by NFS later on, so
	 * we just need to detect them here and treat such EBUSY errors as
	 * if the upper file was successfully deleted.
	 */
	if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED)
		err = 0;
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, lower_dir_inode);
	fsstack_copy_inode_size(dir, lower_dir_inode);
	set_nlink(dentry->d_inode,
		  wrapfs_lower_inode(dentry->d_inode)->i_nlink);
	dentry->d_inode->i_ctime = dir->i_ctime;
	d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */
out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_dir_dentry);
	dput(lower_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #12
0
static int wrapfs_link(struct dentry *old_dentry, struct inode *dir,
		       struct dentry *new_dentry)
{
	struct dentry *lower_old_dentry;
	struct dentry *lower_new_dentry;
	struct dentry *lower_dir_dentry;
	u64 file_size_save;
	int err;
	struct path lower_old_path, lower_new_path;

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	file_size_save = i_size_read(old_dentry->d_inode);
	wrapfs_get_lower_path(old_dentry, &lower_old_path);
	wrapfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_dir_dentry = lock_parent(lower_new_dentry);

	err = mnt_want_write(lower_new_path.mnt);
	if (err)
		goto out_unlock;

	err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
		       lower_new_dentry);
	if (err || !lower_new_dentry->d_inode)
		goto out;

	err = wrapfs_interpose(new_dentry, dir->i_sb, &lower_new_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, lower_new_dentry->d_inode);
	fsstack_copy_inode_size(dir, lower_new_dentry->d_inode);
	set_nlink(old_dentry->d_inode,
		  wrapfs_lower_inode(old_dentry->d_inode)->i_nlink);
	i_size_write(new_dentry->d_inode, file_size_save);
out:
	mnt_drop_write(lower_new_path.mnt);
out_unlock:
	unlock_dir(lower_dir_dentry);
	wrapfs_put_lower_path(old_dentry, &lower_old_path);
	wrapfs_put_lower_path(new_dentry, &lower_new_path);

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #13
0
static void *wrapfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *buf;
	int len = PAGE_SIZE, err;
	mm_segment_t old_fs;


	if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	/* This is freed by the put_link method assuming a successful call. */
	buf = kmalloc(len, GFP_KERNEL);
	if (!buf) {
		buf = ERR_PTR(-ENOMEM);
		goto out;
	}

	/* read the symlink, and then we will follow it */
	old_fs = get_fs();
	set_fs(KERNEL_DS);
	err = wrapfs_readlink(dentry, buf, len);
	set_fs(old_fs);
	if (err < 0) {
		kfree(buf);
		buf = ERR_PTR(err);
	} else {
		buf[err] = '\0';
	}
out:
	nd_set_link(nd, buf);

	if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE)
		DEBUG_MESG("Exit");

	return NULL;
}
Beispiel #14
0
/**
tList*  read_tList_file(const char* fname, int mode) 

ファイルから一行づつ読み込んでリストのキー部に格納.空行はリストに加えない.

@param  fname  ファイル名. 
@param  mode   0: ファイルをそのまま読み込む.
@param  mode   1: 先頭が # の行はリストに加えない.また前後の空白を削除し,その他の連続する空白も1つの空白に変換する.
                  さらにタブは一個の空白として処理される.
@param  mode   2: 1の場合に加えて,途中の # 以降も無視する

@return 格納したリストへのポインタ.
*/
tList*  read_tList_file(const char* fname, int mode) 
{
	tList* lp = NULL;
	FILE* fp;

	fp = fopen(fname, "rb");
	if (fp!=NULL) {
		lp = read_tList_fp(fp, mode);
		fclose(fp);
	}
	else {
		DEBUG_MESG("READ_TLIST_FILE: cannot file open [%s]\n", fname);
	}

	return lp;
}
Beispiel #15
0
static int wrapfs_permission(struct inode *inode, int mask)
{
	struct inode *lower_inode;
	int err;

	if(wrapfs_get_debug(inode->i_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	lower_inode = wrapfs_lower_inode(inode);
	err = inode_permission(lower_inode, mask);

	if(wrapfs_get_debug(inode->i_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #16
0
/*
 * loop through the delimited strings and parse the tokens
 * if parsing is not successful default mount options are loaded
 */
int wrapfs_parse_options(char *raw_data, struct wrapfs_mnt_opt *mount_options) {
	char *split;
	substring_t matched_str[MAX_OPT_ARGS];
	int matched_token;
	int value;
	int retval=0;

	if(mount_options == NULL) {
		DEBUG_MESG("mount_options cannot be NULL");
		retval = -EINVAL;
		goto out;
	}

	mount_options->mmap = FALSE;
	mount_options->debug = DEBUG_NONE;

	while((split = strsep(&raw_data, ",")) != NULL) {
		matched_token = match_token(split, tokens, matched_str);
		// printk("split: %s, matched_token: %d\n", split, matched_token);
		switch(matched_token) {
			case mmap:
				mount_options->mmap = TRUE;
				break;
			case debug:
				if(match_int(matched_str, &value)) {
					pr_err("Debug value should be an integer %s\n", split);
					retval = -EINVAL;
					goto out;
				}
				mount_options->debug = value;
				break;
			default:
				pr_err("Specified option '%s' is not valid\n", split);
				// retval = -EINVAL;
				// goto out;
		}
	}

	printk("Mount options: mmap=%c, debug=%x\n", mount_options->mmap, mount_options->debug);

out:
	return retval;
}
Beispiel #17
0
static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path;

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;
	err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode);
	if (err)
		goto out;

	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;

	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
	/* update number of links on parent directory */
	set_nlink(dir, wrapfs_lower_inode(dir)->i_nlink);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #18
0
static int wrapfs_flush(struct file *file, fl_owner_t id)
{
	int err = 0;
	struct file *lower_file = NULL;

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

	lower_file = wrapfs_lower_file(file);
	if (lower_file && lower_file->f_op && lower_file->f_op->flush)
		err = lower_file->f_op->flush(lower_file, id);

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);
#endif

	return err;
}
Beispiel #19
0
static int wrapfs_fasync(int fd, struct file *file, int flag)
{
	int err = 0;
	struct file *lower_file = NULL;

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

	lower_file = wrapfs_lower_file(file);
	if (lower_file->f_op && lower_file->f_op->fasync)
		err = lower_file->f_op->fasync(fd, lower_file, flag);

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);
#endif

	return err;
}
Beispiel #20
0
static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry)
{
	struct dentry *lower_dentry;
	struct dentry *lower_dir_dentry;
	int err;
	struct path lower_path;

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_dir_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;
	err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
	if (err)
		goto out;

	d_drop(dentry);	/* drop our dentry on success (why not VFS's job?) */
	if (dentry->d_inode)
		clear_nlink(dentry->d_inode);
	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_dir_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #21
0
static ssize_t wrapfs_read(struct file *file, char __user *buf,
			   size_t count, loff_t *ppos)
{
	int err;
	struct file *lower_file;
	struct dentry *dentry = file->f_path.dentry;

	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");

	// printk("wrapfs_read: Read '%s' using vfs_read\n", file->f_dentry->d_iname);

	lower_file = wrapfs_lower_file(file);
    err = vfs_read(lower_file, buf, count, ppos);
	/* update our inode atime upon a successful lower read */
	if (err >= 0)
		fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode);

	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #22
0
/*
 * file: file pointer passed from user space, points to inode and inturn contains device info
 * cmd: is the ioctl command that was called from the user space
 * arg: are the arguments passed from the user space
 */
static long wrapfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long args)
{
	long err = -ENOTTY;
	struct file *lower_file;

#ifdef WRAPFS_CRYPTO
	char key[KEYLEN];
	struct wrapfs_key_info *kargs=NULL;
#endif

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

#ifdef WRAPFS_CRYPTO
	err = verify_and_copy_args(&kargs, (struct wrapfs_key_info*)args);
	if(err) {
		printk("wrapfs_unlocked_ioctl: invalid arguments\n");
		goto out;
	}

	if(cmd == WRAPFS_IO_SETKEY) {
		// printk("wrapfs_unlocked_ioctl: WRAPFS_IO_SETKEY command passed\n");
		if(kargs->key_len==strlen(RESET_KEY) 
			&& memcmp(kargs->key, RESET_KEY, kargs->key_len)==0) {
			WRAPFS_SB(file->f_dentry->d_sb)->has_key = FALSE;
			printk("wrapfs_unlocked_ioctl: key is reset\n");
		}
		/* Only set the key if mmap option is enabled
		 * we cannot perform encryption if different pages aren't available
		 * at different layers, this is achived by enabling
		 * the address_space ops.
		 */
		else if(WRAPFS_SB(file->f_dentry->d_sb)->mount_options.mmap == FALSE) {
			printk("wrapfs_unlocked_ioctl: Cannot set the key if mmap option is disabled\n");
		}
		else {
			WRAPFS_SB(file->f_dentry->d_sb)->has_key = TRUE;
			memset(key, '0', sizeof(key));
			err = get_md5_hash(key, kargs->key, kargs->key_len);
			if(err)
				goto out;
			memcpy(WRAPFS_SB(file->f_dentry->d_sb)->key, key, sizeof(key));
			printk("wrapfs_unlocked_ioctl: key is set\n");
		}
		
	}
#endif

	lower_file = wrapfs_lower_file(file);

	/* XXX: use vfs_ioctl if/when VFS exports it */
	if (!lower_file || !lower_file->f_op)
		goto out;
	if (lower_file->f_op->unlocked_ioctl)
		err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, args);

out:

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", (int)err);
#endif

	return err;
}
Beispiel #23
0
static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct inode *inode;
	struct inode *lower_inode;
	struct path lower_path;
	struct iattr lower_ia;

	if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	inode = dentry->d_inode;

	/*
	 * Check if user has permission to change inode.  We don't check if
	 * this user can change the lower inode: that should happen when
	 * calling notify_change on the lower inode.
	 */
	err = inode_change_ok(inode, ia);
	if (err)
		goto out_err;

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_inode = wrapfs_lower_inode(inode);

	/* prepare our own lower struct iattr (with the lower file) */
	memcpy(&lower_ia, ia, sizeof(lower_ia));
	if (ia->ia_valid & ATTR_FILE)
		lower_ia.ia_file = wrapfs_lower_file(ia->ia_file);

	/*
	 * If shrinking, first truncate upper level to cancel writing dirty
	 * pages beyond the new eof; and also if its' maxbytes is more
	 * limiting (fail with -EFBIG before making any change to the lower
	 * level).  There is no need to vmtruncate the upper level
	 * afterwards in the other cases: we fsstack_copy_inode_size from
	 * the lower level.
	 */
	if (ia->ia_valid & ATTR_SIZE) {
		err = inode_newsize_ok(inode, ia->ia_size);
		if (err)
			goto out;
		truncate_setsize(inode, ia->ia_size);
	}

	/*
	 * mode change is for clearing setuid/setgid bits. Allow lower fs
	 * to interpret this in its own way.
	 */
	if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
		lower_ia.ia_valid &= ~ATTR_MODE;

	/* notify the (possibly copied-up) lower inode */
	/*
	 * Note: we use lower_dentry->d_inode, because lower_inode may be
	 * unlinked (no inode->i_sb and i_ino==0.  This happens if someone
	 * tries to open(), unlink(), then ftruncate() a file.
	 */
	mutex_lock(&lower_dentry->d_inode->i_mutex);
	err = notify_change(lower_dentry, &lower_ia); /* note: lower_ia */
	mutex_unlock(&lower_dentry->d_inode->i_mutex);
	if (err)
		goto out;

	/* get attributes from the lower inode */
	fsstack_copy_attr_all(inode, lower_inode);
	/*
	 * Not running fsstack_copy_inode_size(inode, lower_inode), because
	 * VFS should update our inode size, and notify_change on
	 * lower_inode should update its size.
	 */

out:
	wrapfs_put_lower_path(dentry, &lower_path);
out_err:
	
	if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);

	return err;
}
Beispiel #24
0
static int wrapfs_mmap(struct file *file, struct vm_area_struct *vma)
{
	int err = 0;
	bool willwrite;
	struct file *lower_file;
	const struct vm_operations_struct *saved_vm_ops = NULL;
	
	printk("wrapfs_mmap: '%s'\n", file->f_dentry->d_iname);

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_MESG("Enter");
#endif

	/* this might be deferred to mmap's writepage */
	willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);

	/*
	 * File systems which do not implement ->writepage may use
	 * generic_file_readonly_mmap as their ->mmap op.  If you call
	 * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
	 * But we cannot call the lower ->mmap op, so we can't tell that
	 * writeable mappings won't work.  Therefore, our only choice is to
	 * check if the lower file system supports the ->writepage, and if
	 * not, return EINVAL (the same error that
	 * generic_file_readonly_mmap returns in that case).
	 */
	lower_file = wrapfs_lower_file(file);
	if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
		err = -EINVAL;
		printk(KERN_ERR "wrapfs: lower file system does not "
		       "support writeable mmap\n");
		goto out;
	}

	/*
	 * find and save lower vm_ops.
	 *
	 * XXX: the VFS should have a cleaner way of finding the lower vm_ops
	 */
	if (!WRAPFS_F(file)->lower_vm_ops) {
		err = lower_file->f_op->mmap(lower_file, vma);
		if (err) {
			printk(KERN_ERR "wrapfs: lower mmap failed %d\n", err);
			goto out;
		}
		saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */
		err = do_munmap(current->mm, vma->vm_start, vma->vm_end - vma->vm_start);
		if (err) {
			printk(KERN_ERR "wrapfs: do_munmap failed %d\n", err);
			goto out;
		}
	}

	/*
	 * Next 3 lines are all I need from generic_file_mmap.  I definitely
	 * don't want its test for ->readpage which returns -ENOEXEC.
	 */
	file_accessed(file);
	vma->vm_ops = &wrapfs_vm_ops;
	vma->vm_flags |= VM_CAN_NONLINEAR;

	if(WRAPFS_SB(file->f_dentry->d_sb)->mount_options.mmap == TRUE)
		file->f_mapping->a_ops = &wrapfs_mmap_aops; /* set mmap address_ops */
	else
		file->f_mapping->a_ops = &wrapfs_dummy_aops; /* set dummy address_aops */


	if (!WRAPFS_F(file)->lower_vm_ops) /* save for our ->fault */
		WRAPFS_F(file)->lower_vm_ops = saved_vm_ops;

out:

#ifdef EXTRA_CREDIT
	if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE)
		DEBUG_RETURN("Exit", err);
#endif

	return err;
}
Beispiel #25
0
/*
 * The locking rules in wrapfs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct path lower_old_path, lower_new_path;

	if(wrapfs_get_debug(new_dir->i_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	wrapfs_get_lower_path(old_dentry, &lower_old_path);
	wrapfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = mnt_want_write(lower_old_path.mnt);
	if (err)
		goto out;
	err = mnt_want_write(lower_new_path.mnt);
	if (err)
		goto out_drop_old_write;

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (err)
		goto out_err;

	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir,
				      lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir,
					lower_old_dir_dentry->d_inode);
	}

out_err:
	mnt_drop_write(lower_new_path.mnt);
out_drop_old_write:
	mnt_drop_write(lower_old_path.mnt);
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	wrapfs_put_lower_path(old_dentry, &lower_old_path);
	wrapfs_put_lower_path(new_dentry, &lower_new_path);

	if(wrapfs_get_debug(new_dir->i_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);

	return err;
}