コード例 #1
0
ファイル: xattr.c プロジェクト: kizukukoto/WDN900_GPL
/*
 * BKL held by caller.
 * dentry->d_inode->i_mutex locked
 */
ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
{
	struct dentry *lower_dentry = NULL;
	struct dentry *parent;
	int err = -EOPNOTSUPP;
	char *encoded_list = NULL;
	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);

	encoded_list = list;
	err = vfs_listxattr(lower_dentry, encoded_list, size);

out:
	unionfs_check_dentry(dentry);
	unionfs_unlock_dentry(dentry);
	unionfs_unlock_parent(dentry, parent);
	unionfs_read_unlock(dentry->d_sb);
	return err;
}
コード例 #2
0
ファイル: xattr.c プロジェクト: khenam/ardrone-kernel
/*
 * Extended attribute LIST operations
 */
static ssize_t
listxattr(struct dentry *d, char __user *list, size_t size)
{
	ssize_t error;
	char *klist = NULL;

	if (size) {
		if (size > XATTR_LIST_MAX)
			size = XATTR_LIST_MAX;
		klist = kmalloc(size, GFP_KERNEL);
		if (!klist)
			return -ENOMEM;
	}

	error = vfs_listxattr(d, klist, size);
	if (error > 0) {
		if (size && copy_to_user(list, klist, error))
			error = -EFAULT;
	} else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
		/* The file system tried to returned a list bigger
		   than XATTR_LIST_MAX bytes. Not possible. */
		error = -E2BIG;
	}
	kfree(klist);
	return error;
}
コード例 #3
0
ファイル: inode.c プロジェクト: AdityaChaudhary/linux
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
	ssize_t res;
	int off;

	res = vfs_listxattr(ovl_dentry_real(dentry), list, size);
	if (res <= 0 || size == 0)
		return res;

	if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE)
		return res;

	/* filter out private xattrs */
	for (off = 0; off < res;) {
		char *s = list + off;
		size_t slen = strlen(s) + 1;

		BUG_ON(off + slen > res);

		if (ovl_is_private_xattr(s)) {
			res -= slen;
			memmove(s, s + slen, res - off);
		} else {
			off += slen;
		}
	}

	return res;
}
コード例 #4
0
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
	struct path realpath;
	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
	ssize_t res;
	size_t len;
	char *s;

	res = vfs_listxattr(realpath.dentry, list, size);
	if (res <= 0 || size == 0)
		return res;

	if (!ovl_need_xattr_filter(dentry, type))
		return res;

	/* filter out private xattrs */
	for (s = list, len = res; len;) {
		size_t slen = strnlen(s, len) + 1;

		/* underlying fs providing us with an broken xattr list? */
		if (WARN_ON(slen > len))
			return -EIO;

		len -= slen;
		if (ovl_is_private_xattr(s)) {
			res -= slen;
			memmove(s, s + slen, len);
		} else {
			s += slen;
		}
	}

	return res;
}
コード例 #5
0
ファイル: inode.c プロジェクト: mkrufky/linux
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
	struct dentry *realdentry = ovl_dentry_real(dentry);
	ssize_t res;
	size_t len;
	char *s;
	const struct cred *old_cred;

	old_cred = ovl_override_creds(dentry->d_sb);
	res = vfs_listxattr(realdentry, list, size);
	revert_creds(old_cred);
	if (res <= 0 || size == 0)
		return res;

	/* filter out private xattrs */
	for (s = list, len = res; len;) {
		size_t slen = strnlen(s, len) + 1;

		/* underlying fs providing us with an broken xattr list? */
		if (WARN_ON(slen > len))
			return -EIO;

		len -= slen;
		if (!ovl_can_list(s)) {
			res -= slen;
			memmove(s, s + slen, len);
		} else {
			s += slen;
		}
	}

	return res;
}
コード例 #6
0
ファイル: inode.c プロジェクト: rootwzrd/linux
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
	struct path realpath;
	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
	ssize_t res;
	int off;

	res = vfs_listxattr(realpath.dentry, list, size);
	if (res <= 0 || size == 0)
		return res;

	if (!ovl_need_xattr_filter(dentry, type))
		return res;

	/* filter out private xattrs */
	for (off = 0; off < res;) {
		char *s = list + off;
		size_t slen = strlen(s) + 1;

		BUG_ON(off + slen > res);

		if (ovl_is_private_xattr(s)) {
			res -= slen;
			memmove(s, s + slen, res - off);
		} else {
			off += slen;
		}
	}

	return res;
}
コード例 #7
0
ファイル: inode.c プロジェクト: jameswhang/DiaryFS
static ssize_t diaryfs_listxattr(struct dentry * dentry, char * buffer, size_t buffer_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->listxattr) {
		err = -EOPNOTSUPP;
		goto out;
	}
	err = vfs_listxattr(lower_dentry, buffer, 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;
}
コード例 #8
0
static ssize_t
amfs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_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->listxattr) {
		err = -EINVAL;
		goto out;
	}

	err = vfs_listxattr(lower_dentry,
				     buffer, buffer_size);
out:
	amfs_put_lower_path(dentry, &lower_path);
	return err;
}
コード例 #9
0
ファイル: copyup.c プロジェクト: kizukukoto/WDN900_GPL
/* 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;
}
コード例 #10
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;
}