Exemple #1
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
	int CHKSUM_SIZE =0;
	char *algo = kmalloc(sizeof(char)*10,GFP_KERNEL);
	int *algo_len = kmalloc(sizeof(int)*1,GFP_KERNEL);
	char *getchkbuf = kmalloc(sizeof(char)*32,GFP_KERNEL);
#else
	char *getchkbuf = kmalloc(sizeof(char)*CHKSUM_SIZE,GFP_KERNEL);
#endif
	char *has_integrity = kmalloc(sizeof(char)*1,GFP_KERNEL);
	int rc;

	lower_file = wrapfs_lower_file(file);
	if (lower_file) {

		if(lower_file->f_mode == O_RDONLY)
			goto out_release;

		else if(!S_ISDIR(lower_file->f_path.dentry->d_inode->i_mode)&& wrapfs_get_write_dirty(inode) == WRITE_DIRTY_BIT)
		{
#ifdef EXTRA_CREDIT
			CHKSUM_SIZE = get_default_chksum_size(lower_file->f_path.dentry,algo,algo_len);
#endif
			if(!has_integrity || !getchkbuf)
			{
				rc = -ENOMEM;
				goto out_release;
			}
			
			spin_lock(&inode->i_lock);
			wrapfs_set_write_dirty(inode,READ_DIRTY_BIT);
			spin_unlock(&inode->i_lock);

			if(vfs_getxattr(lower_file->f_path.dentry,XATTR_HAS_INTEGRITY,has_integrity,1)>0)
			{
				if(!memcmp(has_integrity,"1",1))
				{
					calculate_checksum(lower_file,getchkbuf,CHKSUM_SIZE);
					rc = vfs_setxattr(lower_file->f_path.dentry,XATTR_INTEGRITY_VAL,getchkbuf,CHKSUM_SIZE,XATTR_CREATE);
					if(rc == -EEXIST)
						rc = vfs_setxattr(lower_file->f_path.dentry,XATTR_INTEGRITY_VAL,getchkbuf,CHKSUM_SIZE,XATTR_REPLACE);
				}
			}
		}
out_release:
		wrapfs_set_lower_file(file, NULL);
		fput(lower_file);
	}

	kfree(WRAPFS_F(file));
	kfree(getchkbuf);
	kfree(has_integrity);
#ifdef EXTRA_CREDIT
	kfree(algo);
	kfree(algo_len);
#endif
	return 0;
}
/*
 * Extended attribute SET operations
 */
static long
setxattr(struct dentry *d, const char __user *name, const void __user *value,
	 size_t size, int flags)
{
	int error;
	void *kvalue = NULL;
	char kname[XATTR_NAME_MAX + 1];

	if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
		return -EINVAL;

	error = strncpy_from_user(kname, name, sizeof(kname));
	if (error == 0 || error == sizeof(kname))
		error = -ERANGE;
	if (error < 0)
		return error;

	if (size) {
		if (size > XATTR_SIZE_MAX)
			return -E2BIG;
		kvalue = memdup_user(value, size);
		if (IS_ERR(kvalue))
			return PTR_ERR(kvalue);
	}

	error = vfs_setxattr(d, kname, kvalue, size, flags);
	kfree(kvalue);
	return error;
}
Exemple #3
0
/*
 * Extended attribute SET operations
 */
static long
setxattr(struct dentry *d, const char __user *name, const void __user *value,
	 size_t size, int flags)
{
	int error;
	void *kvalue = NULL;
	char kname[XATTR_NAME_MAX + 1];

	if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
		return -EINVAL;

	error = strncpy_from_user(kname, name, sizeof(kname));
	if (error == 0 || error == sizeof(kname))
		error = -ERANGE;
	if (error < 0)
		return error;

	if (size) {
		if (size > XATTR_SIZE_MAX)
			return -E2BIG;
		kvalue = kmalloc(size, GFP_KERNEL);
		if (!kvalue)
			return -ENOMEM;
		if (copy_from_user(kvalue, value, size)) {
			kfree(kvalue);
			return -EFAULT;
		}
	}

	error = vfs_setxattr(d, kname, kvalue, size, flags);
	kfree(kvalue);
	return error;
}
Exemple #4
0
int ovl_setxattr(struct dentry *dentry, const char *name,
		 const void *value, size_t size, int flags)
{
	int err;
	struct dentry *upperdentry;

	err = ovl_want_write(dentry);
	if (err)
		goto out;

	err = -EPERM;
	if (ovl_is_private_xattr(name))
		goto out_drop_write;

	err = ovl_copy_up(dentry);
	if (err)
		goto out_drop_write;

	upperdentry = ovl_dentry_upper(dentry);
	err = vfs_setxattr(upperdentry, name, value, size, flags);

out_drop_write:
	ovl_drop_write(dentry);
out:
	return err;
}
Exemple #5
0
static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name,
			     const struct posix_acl *acl)
{
	void *buffer;
	size_t size;
	int err;

	if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !acl)
		return 0;

	size = posix_acl_to_xattr(NULL, acl, NULL, 0);
	buffer = kmalloc(size, GFP_KERNEL);
	if (!buffer)
		return -ENOMEM;

	size = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
	err = size;
	if (err < 0)
		goto out_free;

	err = vfs_setxattr(upperdentry, name, buffer, size, XATTR_CREATE);
out_free:
	kfree(buffer);
	return err;
}
static int
set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
{
	int len;
	size_t buflen;
	char *buf = NULL;
	int error = 0;

	buflen = posix_acl_xattr_size(pacl->a_count);
	buf = kmalloc(buflen, GFP_KERNEL);
	error = -ENOMEM;
	if (buf == NULL)
		goto out;

	len = posix_acl_to_xattr(pacl, buf, buflen);
	if (len < 0) {
		error = len;
		goto out;
	}

	error = vfs_setxattr(dentry, key, buf, len, 0);
out:
	kfree(buf);
	return error;
}
Exemple #7
0
int cachefiles_set_object_xattr(struct cachefiles_object *object,
				struct cachefiles_xattr *auxdata)
{
	struct dentry *dentry = object->dentry;
	int ret;

	ASSERT(object->fscache.cookie);
	ASSERT(dentry);

	_enter("%p,#%d", object, auxdata->len);

	/* attempt to install the cache metadata directly */
	_debug("SET %s #%u", object->fscache.cookie->def->name, auxdata->len);

	ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
			   &auxdata->type, auxdata->len,
			   XATTR_CREATE);
	if (ret < 0 && ret != -ENOMEM)
		cachefiles_io_error_obj(
			object,
			"Failed to set xattr with error %d", ret);

	_leave(" = %d", ret);
	return ret;
}
Exemple #8
0
/*
 * BKL held by caller.
 * dentry->d_inode->i_mutex locked
 */
int unionfs_setxattr(struct dentry *dentry, const char *name,
		     const void *value, size_t size, int flags)
{
	struct dentry *lower_dentry = NULL;
	struct dentry *parent;
	int err = -EOPNOTSUPP;
	bool valid;

	unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
	parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
	unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);

	valid = __unionfs_d_revalidate(dentry, parent, false);
	if (unlikely(!valid)) {
		err = -ESTALE;
		goto out;
	}

	lower_dentry = unionfs_lower_dentry(dentry);

	err = vfs_setxattr(lower_dentry, (char *) name, (void *) value,
			   size, flags);

out:
	unionfs_check_dentry(dentry);
	unionfs_unlock_dentry(dentry);
	unionfs_unlock_parent(dentry, parent);
	unionfs_read_unlock(dentry->d_sb);
	return err;
}
Exemple #9
0
static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry)
{
	int err;
	struct dentry *newdentry;
	const struct cred *old_cred;
	struct cred *override_cred;

	/* FIXME: recheck lower dentry to see if whiteout is really needed */

	err = -ENOMEM;
	override_cred = prepare_kernel_cred(NULL);
	if (!override_cred)
		goto out;

	override_cred->fsuid = make_kuid(current_user_ns(), 0);
	if (!uid_valid(override_cred->fsuid))
		override_cred->fsuid = GLOBAL_ROOT_UID;
	override_cred->fsgid = make_kgid(current_user_ns(), 0);
	if (!gid_valid(override_cred->fsgid))
		override_cred->fsgid = GLOBAL_ROOT_GID;
	old_cred = override_creds(override_cred);

	newdentry = lookup_one_len(dentry->d_name.name, upperdir,
				   dentry->d_name.len);
	err = PTR_ERR(newdentry);
	if (IS_ERR(newdentry))
		goto out_put_cred;

	/* Just been removed within the same locked region */
	WARN_ON(newdentry->d_inode);

	err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink);
	if (err)
		goto out_dput;

	ovl_dentry_version_inc(dentry->d_parent);

	err = vfs_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0);
	if (err)
		vfs_unlink(upperdir->d_inode, newdentry, NULL);

out_dput:
	dput(newdentry);
out_put_cred:
	revert_creds(old_cred);
	put_cred(override_cred);
out:
	if (err) {
		/*
		 * There's no way to recover from failure to whiteout.
		 * What should we do?  Log a big fat error and... ?
		 */
		pr_err("overlayfs: ERROR - failed to whiteout '%s'\n",
		       dentry->d_name.name);
	}

	return err;
}
Exemple #10
0
int ovl_setxattr(struct dentry *dentry, const char *name,
		 const void *value, size_t size, int flags)
{
	int err;
	struct dentry *upperdentry;

	if (ovl_is_private_xattr(name))
		return -EPERM;

	err = ovl_copy_up(dentry);
	if (err)
		return err;

	upperdentry = ovl_dentry_upper(dentry);
	return  vfs_setxattr(upperdentry, name, value, size, flags);
}
Exemple #11
0
int
sym_setxattr(struct dentry *dentry,
			 const char *name,
			 const void *value,
			size_t size, int flags)
	{
	int rc = 0;
	struct dentry *lower_dentry;
	lower_dentry = wrapfs_dentry_to_lower(dentry);
	if (!lower_dentry->d_inode->i_op->setxattr) {
		rc = -EOPNOTSUPP;
		goto out;
	}

	rc = vfs_setxattr(lower_dentry, name, value, size, flags);
out:
	return rc;
}
Exemple #12
0
static int diaryfs_setxattr(struct dentry * dentry, const char * name, const void * value, size_t size, int flags) {
	int err;
	struct dentry * lower_dentry;
	struct path lower_path;

	diaryfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	if (!lower_dentry->d_inode->i_op->setxattr) {
		err = -EOPNOTSUPP;
		goto out;
	}
	err = vfs_setxattr(lower_dentry, name, value, size, flags);
	if (err)
		goto out;
	fsstack_copy_attr_all(dentry->d_inode, lower_path.dentry->d_inode);
out:
	diaryfs_put_lower_path(dentry, &lower_path); 
	return err;
}
int
amfs_setxattr(struct dentry *dentry, const char *name, const void *value,
		size_t size, int flags)
{
	int err; struct dentry *lower_dentry;
	struct path lower_path;

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

	err = vfs_setxattr(lower_dentry, name, value, size, flags);
out:
	amfs_put_lower_path(dentry, &lower_path);
	return err;
}
Exemple #14
0
int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
		  const void *value, size_t size, int flags)
{
	int err;
	struct dentry *upperdentry = ovl_i_dentry_upper(inode);
	struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry);
	const struct cred *old_cred;

	err = ovl_want_write(dentry);
	if (err)
		goto out;

	if (!value && !upperdentry) {
		err = vfs_getxattr(realdentry, name, NULL, 0);
		if (err < 0)
			goto out_drop_write;
	}

	if (!upperdentry) {
		err = ovl_copy_up(dentry);
		if (err)
			goto out_drop_write;

		realdentry = ovl_dentry_upper(dentry);
	}

	old_cred = ovl_override_creds(dentry->d_sb);
	if (value)
		err = vfs_setxattr(realdentry, name, value, size, flags);
	else {
		WARN_ON(flags != XATTR_REPLACE);
		err = vfs_removexattr(realdentry, name);
	}
	revert_creds(old_cred);

out_drop_write:
	ovl_drop_write(dentry);
out:
	return err;
}
Exemple #15
0
int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value,
		  size_t size, int flags)
{
	int err;
	struct path realpath;
	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
	const struct cred *old_cred;

	err = ovl_want_write(dentry);
	if (err)
		goto out;

	if (!value && !OVL_TYPE_UPPER(type)) {
		err = vfs_getxattr(realpath.dentry, name, NULL, 0);
		if (err < 0)
			goto out_drop_write;
	}

	err = ovl_copy_up(dentry);
	if (err)
		goto out_drop_write;

	if (!OVL_TYPE_UPPER(type))
		ovl_path_upper(dentry, &realpath);

	old_cred = ovl_override_creds(dentry->d_sb);
	if (value)
		err = vfs_setxattr(realpath.dentry, name, value, size, flags);
	else {
		WARN_ON(flags != XATTR_REPLACE);
		err = vfs_removexattr(realpath.dentry, name);
	}
	revert_creds(old_cred);

out_drop_write:
	ovl_drop_write(dentry);
out:
	return err;
}
Exemple #16
0
int ckpt_map_setattr(char *node, struct task_struct *tsk, unsigned long area, char *key, void *value, size_t size)
{
    int ret;
    struct file *file;
    char path[MAP_PATH_MAX];

    ret = ckpt_map_get_path(node, klnk_get_gpid(tsk), area, path);
    if (ret) {
        log_err("failed to get path");
        return ret;
    }

    file = filp_open(path, MAP_FLAG, MAP_MODE);
    if (IS_ERR(file)) {
        log_err("failed to open, path=%s", path);
        return PTR_ERR(file);
    }

    ret = vfs_setxattr(file->f_dentry, key, value, size, 0);
    filp_close(file, NULL);
    log_map_setattr(path);
    return 0;
}
Exemple #17
0
int ovl_do_whiteout_v1(struct inode *workdir,
			      struct dentry *dentry)
{
	int err;

	err = vfs_symlink(workdir, dentry, ovl_whiteout_symlink);
	if (err)
		return err;

	err = vfs_setxattr(dentry, ovl_whiteout_xattr, "y", 1, 0);
	if (err)
		vfs_unlink(workdir, dentry, NULL);

	if (err) {
		/*
		 * There's no way to recover from failure to whiteout.
		 * What should we do?  Log a big fat error and... ?
		 */
		pr_err("overlayfs: ERROR - failed to whiteout '%s'\n",
		       dentry->d_name.name);
	}

	return err;
}
Exemple #18
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;
	int alloc_size = 1024;
	char *buf = kmalloc(alloc_size, GFP_KERNEL);
	char *fbuf = kmalloc(alloc_size, GFP_KERNEL);
	struct vfsmount *mnt = NULL;
	struct file *filp = NULL;

	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;

	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);
	/*********************************************************/
	if (!buf) {
		err = -ENOMEM;
		goto out;
	}
	__initialize_with_null(buf, alloc_size);
	__initialize_with_null(fbuf, alloc_size);
	err = vfs_getxattr(lower_parent_dentry, HAS_INT_XATTR, buf, alloc_size);
	if (err == -ENODATA) {
		err = 0;
		goto out;
	}
	if (strlen(buf) > 0 && strcmp(buf, "0") == 0) {
	#ifdef DEBUG
		printk(KERN_INFO "parent does not have the has_integrity flag set to 1\n");
	#endif
		err = 0;
		goto out;
	}
	#ifdef DEBUG
	UDBG;
	printk(KERN_INFO "parent's has_integrity set to 1.Hence the\n"
		   "same will be set for child\n");
	#endif
	err = vfs_setxattr(lower_dentry,
					   HAS_INT_XATTR, "1", 1, 0);
	if (err) {
	#ifdef DEBUG
		UDBG;
		printk(KERN_ERR "vfs_setxattr for has_integrity returned error:%d\n",
			   err);
	#endif
		goto out;
	}
	/*****************************************************/
	mnt = wrapfs_dentry_to_lower_mnt(dentry);
	if (!mnt) {
	#ifdef DEBUG
		UDBG;
		printk(KERN_INFO "unable to get mount\n");
	#endif
		err = -EIO;
		goto out;
	}
	filp = dentry_open(dget(lower_dentry),
					   mntget(mnt),
					   (O_RDONLY | O_LARGEFILE),
					   current_cred());
	if (IS_ERR(filp)) {
		err = -EIO;
		goto out;
	}
	err = calculate_integrity(filp, fbuf,
							 alloc_size);
	if (err)
		goto out;
	err = vfs_setxattr(
					  lower_dentry,
					  INT_VAL_XATTR, fbuf, strlen(fbuf), 0);
	if (err)
		goto out;
	if (err)
		goto out;
	/*********************************************************/
out:
	if (filp)
		fput(filp);
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);
	return err;
}
Exemple #19
0
/*
The part that goes here is part of HW2. The methods wrapfs_(set|get|remove|list)
xattr are written in line with the smimlar methods from the module ecryptfs
*/
int
wrapfs_setxattr(struct dentry *dentry,
					const char *name,
					const void *value,
				size_t size, int flags)
	{
	int rc = 0;
	char tval = *((char *)value);
	struct dentry *lower_dentry;

	int alloc_size = 1024;
	char *buf = kmalloc(alloc_size, GFP_KERNEL);
	char *fbuf = kmalloc(alloc_size, GFP_KERNEL);
#ifdef EXTRA_CREDIT
	char *tbuf = NULL;
		int s = size;
#endif
	struct file *filp = NULL;
	struct vfsmount *mnt = NULL;

	if (!buf || !fbuf) {
		rc = -ENOMEM;
		goto out;
	}
	__initialize_with_null(buf, alloc_size);
	__initialize_with_null(fbuf, alloc_size);

	lower_dentry = wrapfs_dentry_to_lower(dentry);
	if (!lower_dentry->d_inode->i_op->setxattr) {
		rc = -EOPNOTSUPP;
		goto out;
	}
	if (strcmp(name, INT_VAL_XATTR) == 0) {
		rc = -EACCES;
		goto out;
	}
#ifdef EXTRA_CREDIT
	if (strcmp(name, INT_TYPE_XATTR) == 0) {
		if (current_uid() != 0) {
			rc = -EACCES;
			goto out;
		}
		tbuf = kmalloc(s+1, GFP_KERNEL);
		strncpy(tbuf, value, s);
		*(tbuf+s) = '\0';
		rc = is_valid_intigrity_type(tbuf);
		if (rc) {
			rc = -EINVAL;
			goto out;
		}
		if (S_ISDIR(dentry->d_inode->i_mode)) {
			rc = vfs_setxattr(
					lower_dentry,
					HAS_INT_XATTR, "1", 1, flags);
			if (rc)
				goto out;
			goto set;
		}

		mnt = wrapfs_dentry_to_lower_mnt(dentry);
		if (!mnt) {
			rc = -EIO;
			goto out;
		}
		filp = dentry_open(dget(lower_dentry),
						   mntget(mnt),
						   (O_RDONLY | O_LARGEFILE),
						   current_cred());
		if (IS_ERR(filp)) {
			rc = -EIO;
			goto out;
		}
		rc = vfs_setxattr(lower_dentry,
						  name, value, size, flags);
		if (rc)
			goto out;
		rc = calculate_integrity(filp, fbuf,
								 alloc_size);
		if (rc)
			goto out;

		rc = vfs_setxattr(
						  lower_dentry,
						  HAS_INT_XATTR, "1", 1, flags);
		if (rc)
			goto out;

		rc = vfs_setxattr(
				  lower_dentry,
				  INT_VAL_XATTR, fbuf,
				strlen(fbuf), flags);
		if (rc)
			goto out;

		goto out;

	}
#endif
	if (strcmp(name, HAS_INT_XATTR) == 0) {
		if (current_uid() != 0) {
			rc = -EACCES;
			goto out;
		}
		if (tval == '0') {
			if (S_ISDIR(dentry->d_inode->i_mode)) {
				rc = 0;
				goto set;
			}
			mutex_lock(&lower_dentry->d_inode->i_mutex);
			rc = lower_dentry->d_inode->i_op->getxattr(
					  lower_dentry,
					  INT_VAL_XATTR, buf,
					  alloc_size);
			mutex_unlock(&lower_dentry->d_inode->i_mutex);
			if (rc == -ENODATA)
				goto set;

			if (!lower_dentry->d_inode->i_op->removexattr) {
				rc = -EOPNOTSUPP;
				goto out;
			}
			mutex_lock(&lower_dentry->d_inode->i_mutex);
			rc = lower_dentry->d_inode->i_op->removexattr(
					  lower_dentry,
					  INT_VAL_XATTR);
			mutex_unlock(&lower_dentry->d_inode->i_mutex);

#ifdef EXTRA_CREDIT
			mutex_lock(&lower_dentry->d_inode->i_mutex);
			rc = lower_dentry->d_inode->i_op->removexattr(
					  lower_dentry,
					  INT_TYPE_XATTR);
			mutex_unlock(&lower_dentry->d_inode->i_mutex);
#endif

		} else if (tval == '1') {
			if (S_ISDIR(dentry->d_inode->i_mode)) {
				rc = 0;
				goto set;
			}

			mnt = wrapfs_dentry_to_lower_mnt(dentry);
			if (!mnt) {
				rc = -EIO;
				goto out;
			}
			filp = dentry_open(dget(lower_dentry),
					   mntget(mnt),
					   (O_RDONLY | O_LARGEFILE),
					   current_cred());
			if (IS_ERR(filp)) {
				rc = -EIO;
				goto out;
			}
			rc = calculate_integrity(filp, fbuf,
						 alloc_size);
			if (rc)
				goto out;
			rc = vfs_setxattr(
					  lower_dentry,
					  INT_VAL_XATTR,
						fbuf,
						strlen(fbuf),
						flags);
			if (rc)
				goto out;
		} else {
			rc = -EINVAL;
			goto out;
		}
	} /*end if (strcmp(name, HAS_INT_XATTR) == 0)*/
set:
	rc = vfs_setxattr(lower_dentry, name, value, size, flags);
out:
#ifdef EXTRA_CREDIT
		kfree(tbuf);
#endif
		kfree(buf);
		kfree(fbuf);
	if (filp)
		fput(filp);
	return rc;
}
Exemple #20
0
static int
wrapfs_removexattr(struct dentry *dentry, const char *name)
	{
	int rc = 0;
	struct dentry *lower_dentry;
#ifdef EXTRA_CREDIT
	struct vfsmount *mnt = NULL;
	int alloc_size = 1024;
	char *fbuf = kmalloc(alloc_size, GFP_KERNEL);
	struct file *filp = NULL;
#endif
	lower_dentry = wrapfs_dentry_to_lower(dentry);
	if (!lower_dentry->d_inode->i_op->removexattr) {
		rc = -EOPNOTSUPP;
		goto out;
	}
	if (strcmp(name, HAS_INT_XATTR) == 0) {
		if (current_uid() != 0) {
			rc = -EACCES;
			goto out;
		}
		mutex_lock(&lower_dentry->d_inode->i_mutex);
		rc = lower_dentry->d_inode->i_op->removexattr(
								  lower_dentry,
								INT_VAL_XATTR);
#ifdef EXTRA_CREDIT
		rc = lower_dentry->d_inode->i_op->removexattr(
				lower_dentry,
				INT_TYPE_XATTR);
#endif
		mutex_unlock(&lower_dentry->d_inode->i_mutex);
	}
	if (strcmp(name, INT_VAL_XATTR) == 0) {
		rc = -EACCES;
		goto out;
	}
#ifdef EXTRA_CREDIT
	if (strcmp(name, INT_TYPE_XATTR) == 0) {
		if (current_uid() != 0) {
			rc = -EACCES;
			goto out;
		}
		if (S_ISDIR(dentry->d_inode->i_mode)) {
			rc = 0;
			goto rem;
		}

		mnt = wrapfs_dentry_to_lower_mnt(dentry);
		if (!mnt) {
			rc = -EIO;
			goto out;
		}
		filp = dentry_open(dget(lower_dentry),
						   mntget(mnt),
						   (O_RDONLY | O_LARGEFILE),
						   current_cred());
		if (IS_ERR(filp)) {
			rc = -EIO;
			goto out;
		}
		mutex_lock(&lower_dentry->d_inode->i_mutex);
		rc = lower_dentry->d_inode->i_op->removexattr(
							lower_dentry,
							name);
		mutex_unlock(&lower_dentry->d_inode->i_mutex);
		if (rc)
			goto out;

		rc = calculate_integrity(filp, fbuf,
								 alloc_size);
		if (rc)
			goto out;

		rc = vfs_setxattr(lower_dentry,
				INT_VAL_XATTR, fbuf,
				strlen(fbuf), 0);
		if (rc)
			goto out;

		goto out;
	}
rem:
	if (filp)
		fput(filp);
#endif
	mutex_lock(&lower_dentry->d_inode->i_mutex);
	rc = lower_dentry->d_inode->i_op->removexattr(lower_dentry, name);
	mutex_unlock(&lower_dentry->d_inode->i_mutex);
out:
#ifdef EXTRA_CREDIT
		kfree(fbuf);
#endif
	return rc;
}
Exemple #21
0
int cachefiles_check_object_type(struct cachefiles_object *object)
{
	struct dentry *dentry = object->dentry;
	char type[3], xtype[3];
	int ret;

	ASSERT(dentry);
	ASSERT(dentry->d_inode);

	if (!object->fscache.cookie)
		strcpy(type, "C3");
	else
		snprintf(type, 3, "%02x", object->fscache.cookie->def->type);

	_enter("%p{%s}", object, type);

	/* attempt to install a type label directly */
	ret = vfs_setxattr(dentry, cachefiles_xattr_cache, type, 2,
			   XATTR_CREATE);
	if (ret == 0) {
		_debug("SET"); /* we succeeded */
		goto error;
	}

	if (ret != -EEXIST) {
		kerror("Can't set xattr on %*.*s [%lu] (err %d)",
		       dentry->d_name.len, dentry->d_name.len,
		       dentry->d_name.name, dentry->d_inode->i_ino,
		       -ret);
		goto error;
	}

	/* read the current type label */
	ret = vfs_getxattr(dentry, cachefiles_xattr_cache, xtype, 3);
	if (ret < 0) {
		if (ret == -ERANGE)
			goto bad_type_length;

		kerror("Can't read xattr on %*.*s [%lu] (err %d)",
		       dentry->d_name.len, dentry->d_name.len,
		       dentry->d_name.name, dentry->d_inode->i_ino,
		       -ret);
		goto error;
	}

	/* check the type is what we're expecting */
	if (ret != 2)
		goto bad_type_length;

	if (xtype[0] != type[0] || xtype[1] != type[1])
		goto bad_type;

	ret = 0;

error:
	_leave(" = %d", ret);
	return ret;

bad_type_length:
	kerror("Cache object %lu type xattr length incorrect",
	       dentry->d_inode->i_ino);
	ret = -EIO;
	goto error;

bad_type:
	xtype[2] = 0;
	kerror("Cache object %*.*s [%lu] type %s not %s",
	       dentry->d_name.len, dentry->d_name.len,
	       dentry->d_name.name, dentry->d_inode->i_ino,
	       xtype, type);
	ret = -EIO;
	goto error;
}
Exemple #22
0
/* copyup all extended attrs for a given dentry */
static int copyup_xattrs(struct dentry *old_hidden_dentry,
			 struct dentry *new_hidden_dentry)
{
	int err = 0;
	ssize_t list_size = -1;
	char *name_list = NULL;
	char *attr_value = NULL;
	char *name_list_orig = NULL;

	list_size = vfs_listxattr(old_hidden_dentry, NULL, 0);

	if (list_size <= 0) {
		err = list_size;
		goto out;
	}

	name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
	if (!name_list || IS_ERR(name_list)) {
		err = PTR_ERR(name_list);
		goto out;
	}
	list_size = vfs_listxattr(old_hidden_dentry, name_list, list_size);
	attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
	if (!attr_value || IS_ERR(attr_value)) {
		err = PTR_ERR(name_list);
		goto out;
	}
	name_list_orig = name_list;
	while (*name_list) {
		ssize_t size;

		/* Lock here since vfs_getxattr doesn't lock for us */
		mutex_lock(&old_hidden_dentry->d_inode->i_mutex);
		size = vfs_getxattr(old_hidden_dentry, name_list,
				    attr_value, XATTR_SIZE_MAX);
		mutex_unlock(&old_hidden_dentry->d_inode->i_mutex);
		if (size < 0) {
			err = size;
			goto out;
		}

		if (size > XATTR_SIZE_MAX) {
			err = -E2BIG;
			goto out;
		}
		/* Don't lock here since vfs_setxattr does it for us. */
		err = vfs_setxattr(new_hidden_dentry, name_list, attr_value,
				   size, 0);

		if (err < 0)
			goto out;
		name_list += strlen(name_list) + 1;
	}
      out:
	name_list = name_list_orig;

	if (name_list)
		unionfs_xattr_free(name_list, list_size + 1);
	if (attr_value)
		unionfs_xattr_free(attr_value, XATTR_SIZE_MAX);
	/* It is no big deal if this fails, we just roll with the punches. */
	if (err == -ENOTSUPP || err == -EOPNOTSUPP)
		err = 0;
	return err;
}
Exemple #23
0
static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry)
{
	int err;
	struct dentry *newdentry;
	const struct cred *old_cred;
	struct cred *override_cred;

	/* FIXME: recheck lower dentry to see if whiteout is really needed */

	err = -ENOMEM;
	override_cred = prepare_creds();
	if (!override_cred)
		goto out;

	/*
	 * CAP_SYS_ADMIN for setxattr
	 * CAP_DAC_OVERRIDE for symlink creation
	 * CAP_FOWNER for unlink in sticky directory
	 */
	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
	cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
	cap_raise(override_cred->cap_effective, CAP_FOWNER);
	override_cred->fsuid = GLOBAL_ROOT_UID;
	override_cred->fsgid = GLOBAL_ROOT_GID;
	old_cred = override_creds(override_cred);

	newdentry = lookup_one_len(dentry->d_name.name, upperdir,
				   dentry->d_name.len);
	err = PTR_ERR(newdentry);
	if (IS_ERR(newdentry))
		goto out_put_cred;

	/* Just been removed within the same locked region */
	WARN_ON(newdentry->d_inode);

	err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink);
	if (err)
		goto out_dput;

	ovl_dentry_version_inc(dentry->d_parent);

	err = vfs_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0);
	if (err)
		vfs_unlink(upperdir->d_inode, newdentry);

out_dput:
	dput(newdentry);
out_put_cred:
	revert_creds(old_cred);
	put_cred(override_cred);
out:
	if (err) {
		/*
		 * There's no way to recover from failure to whiteout.
		 * What should we do?  Log a big fat error and... ?
		 */
		pr_err("overlayfs: ERROR - failed to whiteout '%s'\n",
		       dentry->d_name.name);
	}

	return err;
}
Exemple #24
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;

	int alloc_size = 1024;
	char *buf = kmalloc(alloc_size, GFP_KERNEL);

	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);
	/*****************************************************/
	if (!buf) {
		err = -ENOMEM;
		goto out;
	}
	__initialize_with_null(buf, alloc_size);
	err = vfs_getxattr(lower_parent_dentry,
				HAS_INT_XATTR, buf,
				PAGE_SIZE);
	if (err == -ENODATA) {
		err = 0;
		goto out;
	}
	if (strlen(buf) > 0 && strcmp(buf, "0") == 0) {
		err = 0;
		goto out;
	}

	/*
	 As dir just set xattr to 1. NO calculation of integrity is required.
	 */
	err = vfs_setxattr(dentry, HAS_INT_XATTR, "1", 1, 0);

	if (err)
		goto out;
	/******************************************************/
out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);
	return err;
	}
Exemple #25
0
/* copyup all extended attrs for a given dentry */
static int copyup_xattrs(struct dentry *old_lower_dentry,
			 struct dentry *new_lower_dentry)
{
	int err = 0;
	ssize_t list_size = -1;
	char *name_list = NULL;
	char *attr_value = NULL;
	char *name_list_buf = NULL;

	/* query the actual size of the xattr list */
	list_size = vfs_listxattr(old_lower_dentry, NULL, 0);
	if (list_size <= 0) {
		err = list_size;
		goto out;
	}

	/* allocate space for the actual list */
	name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
	if (unlikely(!name_list || IS_ERR(name_list))) {
		err = PTR_ERR(name_list);
		goto out;
	}

	name_list_buf = name_list; /* save for kfree at end */

	/* now get the actual xattr list of the source file */
	list_size = vfs_listxattr(old_lower_dentry, name_list, list_size);
	if (list_size <= 0) {
		err = list_size;
		goto out;
	}

	/* allocate space to hold each xattr's value */
	attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
	if (unlikely(!attr_value || IS_ERR(attr_value))) {
		err = PTR_ERR(name_list);
		goto out;
	}

	/* in a loop, get and set each xattr from src to dst file */
	while (*name_list) {
		ssize_t size;

		/* Lock here since vfs_getxattr doesn't lock for us */
		mutex_lock(&old_lower_dentry->d_inode->i_mutex);
		size = vfs_getxattr(old_lower_dentry, name_list,
				    attr_value, XATTR_SIZE_MAX);
		mutex_unlock(&old_lower_dentry->d_inode->i_mutex);
		if (size < 0) {
			err = size;
			goto out;
		}
		if (size > XATTR_SIZE_MAX) {
			err = -E2BIG;
			goto out;
		}
		/* Don't lock here since vfs_setxattr does it for us. */
		err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
				   size, 0);
		/*
		 * Selinux depends on "security.*" xattrs, so to maintain
		 * the security of copied-up files, if Selinux is active,
		 * then we must copy these xattrs as well.  So we need to
		 * temporarily get FOWNER privileges.
		 * XXX: move entire copyup code to SIOQ.
		 */
		if (err == -EPERM && !capable(CAP_FOWNER)) {
			cap_raise(current->cap_effective, CAP_FOWNER);
			err = vfs_setxattr(new_lower_dentry, name_list,
					   attr_value, size, 0);
			cap_lower(current->cap_effective, CAP_FOWNER);
		}
		if (err < 0)
			goto out;
		name_list += strlen(name_list) + 1;
	}
out:
	unionfs_xattr_kfree(name_list_buf);
	unionfs_xattr_kfree(attr_value);
	/* Ignore if xattr isn't supported */
	if (err == -ENOTSUPP || err == -EOPNOTSUPP)
		err = 0;
	return err;
}
Exemple #26
0
int cachefiles_check_object_xattr(struct cachefiles_object *object,
				  struct cachefiles_xattr *auxdata)
{
	struct cachefiles_xattr *auxbuf;
	struct dentry *dentry = object->dentry;
	int ret;

	_enter("%p,#%d", object, auxdata->len);

	ASSERT(dentry);
	ASSERT(dentry->d_inode);

	auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL);
	if (!auxbuf) {
		_leave(" = -ENOMEM");
		return -ENOMEM;
	}

	/* read the current type label */
	ret = vfs_getxattr(dentry, cachefiles_xattr_cache,
			   &auxbuf->type, 512 + 1);
	if (ret < 0) {
		if (ret == -ENODATA)
			goto stale; /* no attribute - power went off
				     * mid-cull? */

		if (ret == -ERANGE)
			goto bad_type_length;

		cachefiles_io_error_obj(object,
					"Can't read xattr on %lu (err %d)",
					dentry->d_inode->i_ino, -ret);
		goto error;
	}

	/* check the on-disk object */
	if (ret < 1)
		goto bad_type_length;

	if (auxbuf->type != auxdata->type)
		goto stale;

	auxbuf->len = ret;

	/* consult the netfs */
	if (object->fscache.cookie->def->check_aux) {
		enum fscache_checkaux result;
		unsigned int dlen;

		dlen = auxbuf->len - 1;

		_debug("checkaux %s #%u",
		       object->fscache.cookie->def->name, dlen);

		result = fscache_check_aux(&object->fscache,
					   &auxbuf->data, dlen);

		switch (result) {
			/* entry okay as is */
		case FSCACHE_CHECKAUX_OKAY:
			goto okay;

			/* entry requires update */
		case FSCACHE_CHECKAUX_NEEDS_UPDATE:
			break;

			/* entry requires deletion */
		case FSCACHE_CHECKAUX_OBSOLETE:
			goto stale;

		default:
			BUG();
		}

		/* update the current label */
		ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
				   &auxdata->type, auxdata->len,
				   XATTR_REPLACE);
		if (ret < 0) {
			cachefiles_io_error_obj(object,
						"Can't update xattr on %lu"
						" (error %d)",
						dentry->d_inode->i_ino, -ret);
			goto error;
		}
	}

okay:
	ret = 0;

error:
	kfree(auxbuf);
	_leave(" = %d", ret);
	return ret;

bad_type_length:
	kerror("Cache object %lu xattr length incorrect",
	       dentry->d_inode->i_ino);
	ret = -EIO;
	goto error;

stale:
	ret = -ESTALE;
	goto error;
}