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

Commit f2963d45 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Al Viro
Browse files

jffs2: use generic posix ACL infrastructure



Also don't bother to set up a .get_acl method for symlinks as we do not
support access control (ACLs or even mode bits) for symlinks in Linux.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent b0a7ab57
Loading
Loading
Loading
Loading
+11 −130
Original line number Diff line number Diff line
@@ -178,10 +178,6 @@ struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
	char *value = NULL;
	int rc, xprefix;

	acl = get_cached_acl(inode, type);
	if (acl != ACL_NOT_CACHED)
		return acl;

	switch (type) {
	case ACL_TYPE_ACCESS:
		xprefix = JFFS2_XPREFIX_ACL_ACCESS;
@@ -232,13 +228,10 @@ static int __jffs2_set_acl(struct inode *inode, int xprefix, struct posix_acl *a
	return rc;
}

static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	int rc, xprefix;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;

	switch (type) {
	case ACL_TYPE_ACCESS:
		xprefix = JFFS2_XPREFIX_ACL_ACCESS;
@@ -277,30 +270,21 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)

int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, umode_t *i_mode)
{
	struct posix_acl *acl;
	struct posix_acl *default_acl, *acl;
	int rc;

	cache_no_acl(inode);

	if (S_ISLNK(*i_mode))
		return 0;	/* Symlink always has no-ACL */

	acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT);
	if (IS_ERR(acl))
		return PTR_ERR(acl);

	if (!acl) {
		*i_mode &= ~current_umask();
	} else {
		if (S_ISDIR(*i_mode))
			set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);

		rc = __posix_acl_create(&acl, GFP_KERNEL, i_mode);
		if (rc < 0)
	rc = posix_acl_create(dir_i, i_mode, &default_acl, &acl);
	if (rc)
		return rc;
		if (rc > 0)
			set_cached_acl(inode, ACL_TYPE_ACCESS, acl);

	if (default_acl) {
		set_cached_acl(inode, ACL_TYPE_DEFAULT, default_acl);
		posix_acl_release(default_acl);
	}
	if (acl) {
		set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
		posix_acl_release(acl);
	}
	return 0;
@@ -324,106 +308,3 @@ int jffs2_init_acl_post(struct inode *inode)

	return 0;
}

int jffs2_acl_chmod(struct inode *inode)
{
	struct posix_acl *acl;
	int rc;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;
	acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
	if (IS_ERR(acl) || !acl)
		return PTR_ERR(acl);
	rc = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
	if (rc)
		return rc;
	rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, acl);
	posix_acl_release(acl);
	return rc;
}

static size_t jffs2_acl_access_listxattr(struct dentry *dentry, char *list,
		size_t list_size, const char *name, size_t name_len, int type)
{
	const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);

	if (list && retlen <= list_size)
		strcpy(list, POSIX_ACL_XATTR_ACCESS);
	return retlen;
}

static size_t jffs2_acl_default_listxattr(struct dentry *dentry, char *list,
		size_t list_size, const char *name, size_t name_len, int type)
{
	const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);

	if (list && retlen <= list_size)
		strcpy(list, POSIX_ACL_XATTR_DEFAULT);
	return retlen;
}

static int jffs2_acl_getxattr(struct dentry *dentry, const char *name,
		void *buffer, size_t size, int type)
{
	struct posix_acl *acl;
	int rc;

	if (name[0] != '\0')
		return -EINVAL;

	acl = jffs2_get_acl(dentry->d_inode, type);
	if (IS_ERR(acl))
		return PTR_ERR(acl);
	if (!acl)
		return -ENODATA;
	rc = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
	posix_acl_release(acl);

	return rc;
}

static int jffs2_acl_setxattr(struct dentry *dentry, const char *name,
		const void *value, size_t size, int flags, int type)
{
	struct posix_acl *acl;
	int rc;

	if (name[0] != '\0')
		return -EINVAL;
	if (!inode_owner_or_capable(dentry->d_inode))
		return -EPERM;

	if (value) {
		acl = posix_acl_from_xattr(&init_user_ns, value, size);
		if (IS_ERR(acl))
			return PTR_ERR(acl);
		if (acl) {
			rc = posix_acl_valid(acl);
			if (rc)
				goto out;
		}
	} else {
		acl = NULL;
	}
	rc = jffs2_set_acl(dentry->d_inode, type, acl);
 out:
	posix_acl_release(acl);
	return rc;
}

const struct xattr_handler jffs2_acl_access_xattr_handler = {
	.prefix	= POSIX_ACL_XATTR_ACCESS,
	.flags	= ACL_TYPE_DEFAULT,
	.list	= jffs2_acl_access_listxattr,
	.get	= jffs2_acl_getxattr,
	.set	= jffs2_acl_setxattr,
};

const struct xattr_handler jffs2_acl_default_xattr_handler = {
	.prefix	= POSIX_ACL_XATTR_DEFAULT,
	.flags	= ACL_TYPE_DEFAULT,
	.list	= jffs2_acl_default_listxattr,
	.get	= jffs2_acl_getxattr,
	.set	= jffs2_acl_setxattr,
};
+2 −5
Original line number Diff line number Diff line
@@ -27,17 +27,14 @@ struct jffs2_acl_header {
#ifdef CONFIG_JFFS2_FS_POSIX_ACL

struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
extern int jffs2_acl_chmod(struct inode *);
int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
extern int jffs2_init_acl_pre(struct inode *, struct inode *, umode_t *);
extern int jffs2_init_acl_post(struct inode *);

extern const struct xattr_handler jffs2_acl_access_xattr_handler;
extern const struct xattr_handler jffs2_acl_default_xattr_handler;

#else

#define jffs2_get_acl				(NULL)
#define jffs2_acl_chmod(inode)			(0)
#define jffs2_set_acl				(NULL)
#define jffs2_init_acl_pre(dir_i,inode,mode)	(0)
#define jffs2_init_acl_post(inode)		(0)

+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ const struct inode_operations jffs2_dir_inode_operations =
	.mknod =	jffs2_mknod,
	.rename =	jffs2_rename,
	.get_acl =	jffs2_get_acl,
	.set_acl =	jffs2_set_acl,
	.setattr =	jffs2_setattr,
	.setxattr =	jffs2_setxattr,
	.getxattr =	jffs2_getxattr,
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ const struct file_operations jffs2_file_operations =
const struct inode_operations jffs2_file_inode_operations =
{
	.get_acl =	jffs2_get_acl,
	.set_acl =	jffs2_set_acl,
	.setattr =	jffs2_setattr,
	.setxattr =	jffs2_setxattr,
	.getxattr =	jffs2_getxattr,
+4 −3
Original line number Diff line number Diff line
@@ -190,15 +190,16 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)

int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
{
	struct inode *inode = dentry->d_inode;
	int rc;

	rc = inode_change_ok(dentry->d_inode, iattr);
	rc = inode_change_ok(inode, iattr);
	if (rc)
		return rc;

	rc = jffs2_do_setattr(dentry->d_inode, iattr);
	rc = jffs2_do_setattr(inode, iattr);
	if (!rc && (iattr->ia_valid & ATTR_MODE))
		rc = jffs2_acl_chmod(dentry->d_inode);
		rc = posix_acl_chmod(inode, inode->i_mode);

	return rc;
}
Loading