Пример #1
0
ssize_t
vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
{
	struct inode *inode = dentry->d_inode;
	int error;

	error = xattr_permission(inode, name, MAY_READ);
	if (error)
		return error;

	error = security_inode_getxattr(dentry, name);
	if (error)
		return error;

	if (!strncmp(name, XATTR_SECURITY_PREFIX,
				XATTR_SECURITY_PREFIX_LEN)) {
		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
		int ret = xattr_getsecurity(inode, suffix, value, size);
		/*
		 * Only overwrite the return value if a security module
		 * is actually active.
		 */
		if (ret == -EOPNOTSUPP)
			goto nolsm;
		return ret;
	}
nolsm:
	if (inode->i_op->getxattr)
		error = inode->i_op->getxattr(dentry, name, value, size);
	else
		error = -EOPNOTSUPP;

	return error;
}
Пример #2
0
static struct posix_acl *
_get_posix_acl(struct dentry *dentry, char *key)
{
	struct inode *inode = dentry->d_inode;
	char *buf = NULL;
	int buflen, error = 0;
	struct posix_acl *pacl = NULL;

	error = -EOPNOTSUPP;
	if (inode->i_op == NULL)
		goto out_err;
	if (inode->i_op->getxattr == NULL)
		goto out_err;

	error = security_inode_getxattr(dentry, key);
	if (error)
		goto out_err;

	buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
	if (buflen <= 0) {
		error = buflen < 0 ? buflen : -ENODATA;
		goto out_err;
	}

	buf = kmalloc(buflen, GFP_KERNEL);
	if (buf == NULL) {
		error = -ENOMEM;
		goto out_err;
	}

	error = inode->i_op->getxattr(dentry, key, buf, buflen);
	if (error < 0)
		goto out_err;

	pacl = posix_acl_from_xattr(buf, buflen);
 out:
	kfree(buf);
	return pacl;
 out_err:
	pacl = ERR_PTR(error);
	goto out;
}
Пример #3
0
/*
 * Extended attribute GET operations
 */
static ssize_t
getxattr(struct dentry *d, 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 = kmalloc(size, GFP_KERNEL);
		if (!kvalue)
			return -ENOMEM;
	}

	error = -EOPNOTSUPP;
	if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
		error = security_inode_getxattr(d, kname);
		if (error)
			goto out;
		error = d->d_inode->i_op->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;
		}
	}
out:
	if (kvalue)
		kfree(kvalue);
	return error;
}
Пример #4
0
/*Not Working Yet*/
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;

	print_entry_location();

	PASSERT(old_hidden_dentry);
	PASSERT(old_hidden_dentry->d_inode);
	PASSERT(old_hidden_dentry->d_inode->i_op);
	PASSERT(new_hidden_dentry);
	PASSERT(new_hidden_dentry->d_inode);
	PASSERT(new_hidden_dentry->d_inode->i_op);

	if (!old_hidden_dentry->d_inode->i_op->getxattr ||
	    !old_hidden_dentry->d_inode->i_op->listxattr ||
	    !new_hidden_dentry->d_inode->i_op->setxattr) {
		err = -ENOTSUPP;
		goto out;
	}

	list_size =
	    old_hidden_dentry->d_inode->i_op->listxattr(old_hidden_dentry, NULL,
							0);
	if (list_size <= 0) {
		err = list_size;
		goto out;
	}

	name_list = xattr_alloc(list_size + 1, XATTR_LIST_MAX);
	if (!name_list || IS_ERR(name_list)) {
		err = PTR_ERR(name_list);
		goto out;
	}
	list_size =
	    old_hidden_dentry->d_inode->i_op->listxattr(old_hidden_dentry,
							name_list, list_size);
	attr_value = 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;
		down(&old_hidden_dentry->d_inode->i_sem);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
		err = security_inode_getxattr(old_hidden_dentry, name_list);
		if (err)
			size = err;
		else
#endif
			size =
			    old_hidden_dentry->d_inode->i_op->
			    getxattr(old_hidden_dentry, name_list, attr_value,
				     XATTR_SIZE_MAX);
		up(&old_hidden_dentry->d_inode->i_sem);
		if (size < 0) {
			err = size;
			goto out;
		}

		if (size > XATTR_SIZE_MAX) {
			err = -E2BIG;
			goto out;
		}

		down(&new_hidden_dentry->d_inode->i_sem);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
		err =
		    security_inode_setxattr(old_hidden_dentry, name_list,
					    attr_value, size, 0);

		if (!err) {
#endif
			err =
			    new_hidden_dentry->d_inode->i_op->
			    setxattr(new_hidden_dentry, name_list, attr_value,
				     size, 0);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
			if (!err)
				security_inode_post_setxattr(old_hidden_dentry,
							     name_list,
							     attr_value, size,
							     0);
		}
#endif
		up(&new_hidden_dentry->d_inode->i_sem);

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

	if (name_list)
		xattr_free(name_list, list_size + 1);
	if (attr_value)
		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 = 0;
	return err;
}