Пример #1
0
static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
{
	ssize_t buflen;

	buflen = vfs_getxattr(dentry, key, NULL, 0);
	if (buflen <= 0)
		return buflen;

	*buf = kmalloc(buflen, GFP_KERNEL);
	if (!*buf)
		return -ENOMEM;

	return vfs_getxattr(dentry, key, *buf, buflen);
}
Пример #2
0
int ovl_removexattr(struct dentry *dentry, const char *name)
{
	int err;
	struct path realpath;
	enum ovl_path_type type = ovl_path_real(dentry, &realpath);

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

	err = -ENODATA;
	if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
		goto out_drop_write;

	if (!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;

		ovl_path_upper(dentry, &realpath);
	}

	err = vfs_removexattr(realpath.dentry, name);
out_drop_write:
	ovl_drop_write(dentry);
out:
	return err;
}
Пример #3
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;
}
Пример #4
0
int ovl_removexattr(struct dentry *dentry, const char *name)
{
	int err;
	struct path realpath;
	enum ovl_path_type type;

	if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE &&
	    ovl_is_private_xattr(name))
		return -ENODATA;

	type = ovl_path_real(dentry, &realpath);
	if (type == OVL_PATH_LOWER) {
		err = vfs_getxattr(realpath.dentry, name, NULL, 0);
		if (err < 0)
			return err;

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

		ovl_path_upper(dentry, &realpath);
	}

	return vfs_removexattr(realpath.dentry, name);
}
Пример #5
0
/*
 * Extended attribute GET operations
 */
static ssize_t
getxattr(struct dentry *d, const char __user *name, void __user *value,
	 size_t size)
{
	ssize_t error;
	void *kvalue = NULL;
	char kname[XATTR_NAME_MAX + 1];

	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)
			size = XATTR_SIZE_MAX;
		kvalue = kzalloc(size, GFP_KERNEL);
		if (!kvalue)
			return -ENOMEM;
	}

	error = vfs_getxattr(d, kname, kvalue, size);
	if (error > 0) {
		if (size && copy_to_user(value, kvalue, error))
			error = -EFAULT;
	} else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
		/* The file system tried to returned a value bigger
		   than XATTR_SIZE_MAX bytes. Not possible. */
		error = -E2BIG;
	}
	kfree(kvalue);
	return error;
}
Пример #6
0
int ovl_removexattr(struct dentry *dentry, const char *name)
{
	int err;
	struct path realpath;
	enum ovl_path_type type;

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

	if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE &&
	    ovl_is_private_xattr(name))
		goto out_drop_write;

	type = ovl_path_real(dentry, &realpath);
	if (type == OVL_PATH_LOWER) {
		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;

		ovl_path_upper(dentry, &realpath);
	}

	err = vfs_removexattr(realpath.dentry, name);
out_drop_write:
	ovl_drop_write(dentry);
out:
	return err;
}
Пример #7
0
/*
 * BKL held by caller.
 * dentry->d_inode->i_mutex locked
 */
ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value,
			 size_t size)
{
	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_getxattr(lower_dentry, (char *) name, value, size);

out:
	unionfs_check_dentry(dentry);
	unionfs_unlock_dentry(dentry);
	unionfs_unlock_parent(dentry, parent);
	unionfs_read_unlock(dentry->d_sb);
	return err;
}
Пример #8
0
ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
		     void *value, size_t size)
{
	if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE &&
	    ovl_is_private_xattr(name))
		return -ENODATA;

	return vfs_getxattr(ovl_dentry_real(dentry), name, value, size);
}
Пример #9
0
ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
		     const char *name, void *value, size_t size)
{
	struct dentry *realdentry = ovl_dentry_real(dentry);

	if (ovl_is_private_xattr(name))
		return -ENODATA;

	return vfs_getxattr(realdentry, name, value, size);
}
Пример #10
0
ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
		     void *value, size_t size)
{
	struct path realpath;
	enum ovl_path_type type = ovl_path_real(dentry, &realpath);

	if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
		return -ENODATA;

	return vfs_getxattr(realpath.dentry, name, value, size);
}
Пример #11
0
int ovl_xattr_get(struct dentry *dentry, const char *name,
		  void *value, size_t size)
{
	struct dentry *realdentry = ovl_dentry_real(dentry);
	ssize_t res;
	const struct cred *old_cred;

	old_cred = ovl_override_creds(dentry->d_sb);
	res = vfs_getxattr(realdentry, name, value, size);
	revert_creds(old_cred);
	return res;
}
Пример #12
0
int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
		  void *value, size_t size)
{
	ssize_t res;
	const struct cred *old_cred;
	struct dentry *realdentry =
		ovl_i_dentry_upper(inode) ?: ovl_dentry_lower(dentry);

	old_cred = ovl_override_creds(dentry->d_sb);
	res = vfs_getxattr(realdentry, name, value, size);
	revert_creds(old_cred);
	return res;
}
Пример #13
0
static bool ovl_is_opaquedir(struct dentry *dentry)
{
	int res;
	char val;

	if (!S_ISDIR(dentry->d_inode->i_mode))
		return false;

	res = vfs_getxattr(dentry, ovl_opaque_xattr, &val, 1);
	if (res == 1 && val == 'y')
		return true;

	return false;
}
Пример #14
0
bool ovl_is_whiteout(struct dentry *dentry)
{
	int res;
	char val;

	if (!dentry)
		return false;
	if (!dentry->d_inode)
		return false;
	if (!S_ISLNK(dentry->d_inode->i_mode))
		return false;

	res = vfs_getxattr(dentry, ovl_whiteout_xattr, &val, 1);
	if (res == 1 && val == 'y')
		return true;

	return false;
}
Пример #15
0
static ssize_t diaryfs_getxattr(struct dentry *dentry, const char * name, void *buffer, size_t size) {
	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->getxattr) {
		err = -EOPNOTSUPP;
		goto out;
	}
	err = vfs_getxattr(lower_dentry, name, buffer, size);
	if (err)
		goto out;
	fsstack_copy_attr_atime(dentry->d_inode, lower_path.dentry->d_inode);

out:
	diaryfs_put_lower_path(dentry, &lower_path);
	return err;
}
Пример #16
0
ssize_t
amfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
		size_t size)
{
	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->getxattr) {
		err = -EINVAL;
		goto out;
	}

	err = vfs_getxattr(lower_dentry, name, buffer, size);
out:
	amfs_put_lower_path(dentry, &lower_path);
	return err;
}
Пример #17
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;
}
Пример #18
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;
}
Пример #19
0
unsigned int ovl_get_nlink(struct dentry *lowerdentry,
			   struct dentry *upperdentry,
			   unsigned int fallback)
{
	int nlink_diff;
	int nlink;
	char buf[13];
	int err;

	if (!lowerdentry || !upperdentry || d_inode(lowerdentry)->i_nlink == 1)
		return fallback;

	err = vfs_getxattr(upperdentry, OVL_XATTR_NLINK, &buf, sizeof(buf) - 1);
	if (err < 0)
		goto fail;

	buf[err] = '\0';
	if ((buf[0] != 'L' && buf[0] != 'U') ||
	    (buf[1] != '+' && buf[1] != '-'))
		goto fail;

	err = kstrtoint(buf + 1, 10, &nlink_diff);
	if (err < 0)
		goto fail;

	nlink = d_inode(buf[0] == 'L' ? lowerdentry : upperdentry)->i_nlink;
	nlink += nlink_diff;

	if (nlink <= 0)
		goto fail;

	return nlink;

fail:
	pr_warn_ratelimited("overlayfs: failed to get index nlink (%pd2, err=%i)\n",
			    upperdentry, err);
	return fallback;
}
Пример #20
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;
	}
Пример #21
0
	int calculate_integrity(struct file *filp,
						char *ibuf,
						int ilen)
	{
	int r = -1 , ret = -1;
	ssize_t vfs_read_retval = 0;
	loff_t file_offset = 0;
	mm_segment_t oldfs = get_fs();

	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);

	struct scatterlist sg;
	struct crypto_hash *tfm = NULL;
	struct hash_desc desc;
	char *algo = kmalloc(1024, GFP_KERNEL);
	if (!algo) {
		ret = -ENOMEM;
		goto out;
	}
	__initialize_with_null(algo, 1024);

#ifdef EXTRA_CREDIT
	ret = vfs_getxattr(filp->f_path.dentry,
				 INT_TYPE_XATTR,
				 algo,
				 1024);
	if (ret <= 0)
		__initialize_with_null(algo, 1024);

#endif
	if (*algo == '\0')
		strcpy(algo, DEFAULT_ALGO);


	if (!buf)
		goto out;
	__initialize_with_null(ibuf, ilen);

	if (!filp->f_op->read) {
		r = -2;
		goto out;
	}
	filp->f_pos = 0;
	set_fs(KERNEL_DS);

	tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
	if (IS_ERR(tfm)) {
		r = -EINVAL;
		goto out;
	}
	desc.tfm = tfm;
	desc.flags = 0;

	if (crypto_hash_digestsize(tfm) > ilen) {
		r = -EINVAL;
		goto out;
	}
	crypto_hash_setkey(tfm, key, strlen(key));
	ret = crypto_hash_init(&desc);
	if (ret) {
		r = ret;
		goto out;
	}
	sg_init_table(&sg, 1);
	file_offset = 0;
	do {
		vfs_read_retval = vfs_read(filp, buf, PAGE_SIZE, &file_offset);

		if (vfs_read_retval < 0) {
			ret = vfs_read_retval;
			goto out;
		}
		sg_set_buf(&sg, (u8 *)buf, vfs_read_retval);
		ret = crypto_hash_update(&desc, &sg, sg.length);

		if (ret) {
			r = ret;
			goto out;
		}
		if (vfs_read_retval < ksize(buf))
			break;
	} while (1);
	ret = crypto_hash_final(&desc, ibuf);
	if (ret) {
		r = ret;
		goto out;
	}
out:
	kfree(buf);
	kfree(algo);
	if (!IS_ERR(tfm))
		crypto_free_hash(tfm);
	set_fs(oldfs);
	return ret;
	}
Пример #22
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;
}
Пример #23
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;
}
Пример #24
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;
}
Пример #25
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
	int CHKSUM_SIZE =0;
	char *algo = kmalloc(sizeof(char)*10,GFP_KERNEL);
	int *algo_len = kmalloc(sizeof(char)*1,GFP_KERNEL);
	char *chkbuf = kmalloc(sizeof(char)*32,GFP_KERNEL);
	char *getchkbuf = kmalloc(sizeof(char)*32,GFP_KERNEL);
#else	
	char *chkbuf = kmalloc(sizeof(char)*CHKSUM_SIZE,GFP_KERNEL);
	char *getchkbuf = kmalloc(sizeof(char)*CHKSUM_SIZE,GFP_KERNEL);
#endif
	char *has_integrity = kmalloc(sizeof(char)*1,GFP_KERNEL);
	int rc = 0;

	if(!chkbuf || !has_integrity || !getchkbuf)
	{
		err = -ENOMEM;
		goto out_err;
	}
	/* 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 {
#ifdef EXTRA_CREDIT
		CHKSUM_SIZE = get_default_chksum_size(lower_path.dentry,algo,algo_len);
#endif
		rc = vfs_getxattr(lower_path.dentry,XATTR_HAS_INTEGRITY,has_integrity,1);
		if(rc > 0 && !S_ISDIR(lower_path.dentry->d_inode->i_mode))
		{
			wrapfs_set_lower_file(file,lower_file);

			if(lower_file->f_mode == O_TRUNC)
				wrapfs_set_write_dirty(inode,WRITE_DIRTY_BIT);
			
			if(!memcmp(has_integrity,"1",1) && wrapfs_get_write_dirty(inode)!=WRITE_DIRTY_BIT && rc ==1)
			{	
				if(vfs_getxattr(lower_path.dentry,XATTR_INTEGRITY_VAL,chkbuf,CHKSUM_SIZE)>0)
				{
					//mutex_lock(&lower_path.dentry->d_inode->i_mutex);
					calculate_checksum(lower_file,getchkbuf,CHKSUM_SIZE);
					if(memcmp(chkbuf,getchkbuf,CHKSUM_SIZE))
					{
						printk("Integrity mismatch\n");
						err = -EPERM;
						wrapfs_set_lower_file(file,NULL);
						fput(lower_file);
					}
					//mutex_unlock(&lower_path.dentry->d_inode->i_mutex);							
				}
			}
			else if(!memcmp(has_integrity,"0",1) && rc ==1)
			{
				if(vfs_getxattr(lower_path.dentry,XATTR_INTEGRITY_VAL,chkbuf,CHKSUM_SIZE)>0)
				{
					err = -EIO;
					wrapfs_set_lower_file(file,NULL);
					fput(lower_file);
				}
				else
					wrapfs_set_lower_file(file,lower_file);
			}
			else
			{
				printk("File corrupted.Unexpected value for has_integrity attribute\n");
				err = -EPERM;
				wrapfs_set_lower_file(file,NULL);
				fput(lower_file);
			}
		}
		else if(vfs_getxattr(lower_path.dentry,XATTR_HAS_INTEGRITY,has_integrity,1)<=0 && vfs_getxattr(lower_path.dentry,XATTR_INTEGRITY_VAL,chkbuf,CHKSUM_SIZE)>0)
		{
			err = -EIO;
			wrapfs_set_lower_file(file,NULL);
			fput(lower_file);
		}			
		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:
	kfree(chkbuf);
	kfree(getchkbuf);
	kfree(has_integrity);
#ifdef EXTRA_CREDIT
	kfree(algo);
	kfree(algo_len);
#endif
	return err;
}
Пример #26
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;
}
Пример #27
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;
}