Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e72a1a8b authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Al Viro
Browse files

kernfs: Switch to generic xattr handlers

parent b8020eff
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1126,9 +1126,9 @@ const struct inode_operations kernfs_dir_iops = {
	.permission	= kernfs_iop_permission,
	.setattr	= kernfs_iop_setattr,
	.getattr	= kernfs_iop_getattr,
	.setxattr	= kernfs_iop_setxattr,
	.removexattr	= kernfs_iop_removexattr,
	.getxattr	= kernfs_iop_getxattr,
	.setxattr	= generic_setxattr,
	.removexattr	= generic_removexattr,
	.getxattr	= generic_getxattr,
	.listxattr	= kernfs_iop_listxattr,

	.mkdir		= kernfs_iop_mkdir,
+84 −74
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@ static const struct inode_operations kernfs_iops = {
	.permission	= kernfs_iop_permission,
	.setattr	= kernfs_iop_setattr,
	.getattr	= kernfs_iop_getattr,
	.setxattr	= kernfs_iop_setxattr,
	.removexattr	= kernfs_iop_removexattr,
	.getxattr	= kernfs_iop_getxattr,
	.setxattr	= generic_setxattr,
	.removexattr	= generic_removexattr,
	.getxattr	= generic_getxattr,
	.listxattr	= kernfs_iop_listxattr,
};

@@ -138,17 +138,12 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
	return error;
}

static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
				  u32 *secdata_len)
{
	struct kernfs_iattrs *attrs;
	void *old_secdata;
	size_t old_secdata_len;

	attrs = kernfs_iattrs(kn);
	if (!attrs)
		return -ENOMEM;

	old_secdata = attrs->ia_secdata;
	old_secdata_len = attrs->ia_secdata_len;

@@ -160,71 +155,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
	return 0;
}

int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
			const char *name, const void *value,
			size_t size, int flags)
{
	struct kernfs_node *kn = inode->i_private;
	struct kernfs_iattrs *attrs;
	void *secdata;
	int error;
	u32 secdata_len = 0;

	attrs = kernfs_iattrs(kn);
	if (!attrs)
		return -ENOMEM;

	if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
		error = security_inode_setsecurity(inode, suffix,
						value, size, flags);
		if (error)
			return error;
		error = security_inode_getsecctx(inode,
						&secdata, &secdata_len);
		if (error)
			return error;

		mutex_lock(&kernfs_mutex);
		error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
		mutex_unlock(&kernfs_mutex);

		if (secdata)
			security_release_secctx(secdata, secdata_len);
		return error;
	} else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
		return simple_xattr_set(&attrs->xattrs, name, value, size,
					flags);
	}

	return -EINVAL;
}

int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
{
	struct kernfs_node *kn = dentry->d_fsdata;
	struct kernfs_iattrs *attrs;

	attrs = kernfs_iattrs(kn);
	if (!attrs)
		return -ENOMEM;

	return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
}

ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode,
			    const char *name, void *buf, size_t size)
{
	struct kernfs_node *kn = inode->i_private;
	struct kernfs_iattrs *attrs;

	attrs = kernfs_iattrs(kn);
	if (!attrs)
		return -ENOMEM;

	return simple_xattr_get(&attrs->xattrs, name, buf, size);
}

ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
{
	struct kernfs_node *kn = dentry->d_fsdata;
@@ -376,3 +306,83 @@ int kernfs_iop_permission(struct inode *inode, int mask)

	return generic_permission(inode, mask);
}

static int kernfs_xattr_get(const struct xattr_handler *handler,
			    struct dentry *unused, struct inode *inode,
			    const char *suffix, void *value, size_t size)
{
	const char *name = xattr_full_name(handler, suffix);
	struct kernfs_node *kn = inode->i_private;
	struct kernfs_iattrs *attrs;

	attrs = kernfs_iattrs(kn);
	if (!attrs)
		return -ENOMEM;

	return simple_xattr_get(&attrs->xattrs, name, value, size);
}

static int kernfs_xattr_set(const struct xattr_handler *handler,
			    struct dentry *unused, struct inode *inode,
			    const char *suffix, const void *value,
			    size_t size, int flags)
{
	const char *name = xattr_full_name(handler, suffix);
	struct kernfs_node *kn = inode->i_private;
	struct kernfs_iattrs *attrs;

	attrs = kernfs_iattrs(kn);
	if (!attrs)
		return -ENOMEM;

	return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
}

const struct xattr_handler kernfs_trusted_xattr_handler = {
	.prefix = XATTR_TRUSTED_PREFIX,
	.get = kernfs_xattr_get,
	.set = kernfs_xattr_set,
};

static int kernfs_security_xattr_set(const struct xattr_handler *handler,
				     struct dentry *unused, struct inode *inode,
				     const char *suffix, const void *value,
				     size_t size, int flags)
{
	struct kernfs_node *kn = inode->i_private;
	struct kernfs_iattrs *attrs;
	void *secdata;
	u32 secdata_len = 0;
	int error;

	attrs = kernfs_iattrs(kn);
	if (!attrs)
		return -ENOMEM;

	error = security_inode_setsecurity(inode, suffix, value, size, flags);
	if (error)
		return error;
	error = security_inode_getsecctx(inode, &secdata, &secdata_len);
	if (error)
		return error;

	mutex_lock(&kernfs_mutex);
	error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
	mutex_unlock(&kernfs_mutex);

	if (secdata)
		security_release_secctx(secdata, secdata_len);
	return error;
}

const struct xattr_handler kernfs_security_xattr_handler = {
	.prefix = XATTR_SECURITY_PREFIX,
	.get = kernfs_xattr_get,
	.set = kernfs_security_xattr_set,
};

const struct xattr_handler *kernfs_xattr_handlers[] = {
	&kernfs_trusted_xattr_handler,
	&kernfs_security_xattr_handler,
	NULL
};
+1 −6
Original line number Diff line number Diff line
@@ -76,17 +76,12 @@ extern struct kmem_cache *kernfs_node_cache;
/*
 * inode.c
 */
extern const struct xattr_handler *kernfs_xattr_handlers[];
void kernfs_evict_inode(struct inode *inode);
int kernfs_iop_permission(struct inode *inode, int mask);
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
		       struct kstat *stat);
int kernfs_iop_setxattr(struct dentry *dentry, struct inode *inode,
			const char *name, const void *value,
			size_t size, int flags);
int kernfs_iop_removexattr(struct dentry *dentry, const char *name);
ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode,
			    const char *name, void *buf, size_t size);
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);

/*
+1 −0
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
	sb->s_blocksize_bits = PAGE_SHIFT;
	sb->s_magic = magic;
	sb->s_op = &kernfs_sops;
	sb->s_xattr = kernfs_xattr_handlers;
	sb->s_time_gran = 1;

	/* get root inode, initialize and unlock it */
+3 −3
Original line number Diff line number Diff line
@@ -134,9 +134,9 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
}

const struct inode_operations kernfs_symlink_iops = {
	.setxattr	= kernfs_iop_setxattr,
	.removexattr	= kernfs_iop_removexattr,
	.getxattr	= kernfs_iop_getxattr,
	.setxattr	= generic_setxattr,
	.removexattr	= generic_removexattr,
	.getxattr	= generic_getxattr,
	.listxattr	= kernfs_iop_listxattr,
	.readlink	= generic_readlink,
	.get_link	= kernfs_iop_get_link,