xref: /openbmc/linux/fs/9p/acl.c (revision 7a4566b0b8fa67c7cd7be9f2969a085920356abb)
185ff872dSAneesh Kumar K.V /*
285ff872dSAneesh Kumar K.V  * Copyright IBM Corporation, 2010
385ff872dSAneesh Kumar K.V  * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
485ff872dSAneesh Kumar K.V  *
585ff872dSAneesh Kumar K.V  * This program is free software; you can redistribute it and/or modify it
685ff872dSAneesh Kumar K.V  * under the terms of version 2.1 of the GNU Lesser General Public License
785ff872dSAneesh Kumar K.V  * as published by the Free Software Foundation.
885ff872dSAneesh Kumar K.V  *
985ff872dSAneesh Kumar K.V  * This program is distributed in the hope that it would be useful, but
1085ff872dSAneesh Kumar K.V  * WITHOUT ANY WARRANTY; without even the implied warranty of
1185ff872dSAneesh Kumar K.V  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1285ff872dSAneesh Kumar K.V  *
1385ff872dSAneesh Kumar K.V  */
1485ff872dSAneesh Kumar K.V 
1585ff872dSAneesh Kumar K.V #include <linux/module.h>
1685ff872dSAneesh Kumar K.V #include <linux/fs.h>
1785ff872dSAneesh Kumar K.V #include <net/9p/9p.h>
1885ff872dSAneesh Kumar K.V #include <net/9p/client.h>
1985ff872dSAneesh Kumar K.V #include <linux/slab.h>
2085ff872dSAneesh Kumar K.V #include <linux/posix_acl_xattr.h>
2185ff872dSAneesh Kumar K.V #include "xattr.h"
2285ff872dSAneesh Kumar K.V #include "acl.h"
2385ff872dSAneesh Kumar K.V 
2485ff872dSAneesh Kumar K.V static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
2585ff872dSAneesh Kumar K.V {
2685ff872dSAneesh Kumar K.V 	ssize_t size;
2785ff872dSAneesh Kumar K.V 	void *value = NULL;
2885ff872dSAneesh Kumar K.V 	struct posix_acl *acl = NULL;;
2985ff872dSAneesh Kumar K.V 
3085ff872dSAneesh Kumar K.V 	size = v9fs_fid_xattr_get(fid, name, NULL, 0);
3185ff872dSAneesh Kumar K.V 	if (size > 0) {
3285ff872dSAneesh Kumar K.V 		value = kzalloc(size, GFP_NOFS);
3385ff872dSAneesh Kumar K.V 		if (!value)
3485ff872dSAneesh Kumar K.V 			return ERR_PTR(-ENOMEM);
3585ff872dSAneesh Kumar K.V 		size = v9fs_fid_xattr_get(fid, name, value, size);
3685ff872dSAneesh Kumar K.V 		if (size > 0) {
3785ff872dSAneesh Kumar K.V 			acl = posix_acl_from_xattr(value, size);
3885ff872dSAneesh Kumar K.V 			if (IS_ERR(acl))
3985ff872dSAneesh Kumar K.V 				goto err_out;
4085ff872dSAneesh Kumar K.V 		}
4185ff872dSAneesh Kumar K.V 	} else if (size == -ENODATA || size == 0 ||
4285ff872dSAneesh Kumar K.V 		   size == -ENOSYS || size == -EOPNOTSUPP) {
4385ff872dSAneesh Kumar K.V 		acl = NULL;
4485ff872dSAneesh Kumar K.V 	} else
4585ff872dSAneesh Kumar K.V 		acl = ERR_PTR(-EIO);
4685ff872dSAneesh Kumar K.V 
4785ff872dSAneesh Kumar K.V err_out:
4885ff872dSAneesh Kumar K.V 	kfree(value);
4985ff872dSAneesh Kumar K.V 	return acl;
5085ff872dSAneesh Kumar K.V }
5185ff872dSAneesh Kumar K.V 
5285ff872dSAneesh Kumar K.V int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
5385ff872dSAneesh Kumar K.V {
5485ff872dSAneesh Kumar K.V 	int retval = 0;
5585ff872dSAneesh Kumar K.V 	struct posix_acl *pacl, *dacl;
5685ff872dSAneesh Kumar K.V 
5785ff872dSAneesh Kumar K.V 	/* get the default/access acl values and cache them */
5885ff872dSAneesh Kumar K.V 	dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT);
5985ff872dSAneesh Kumar K.V 	pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS);
6085ff872dSAneesh Kumar K.V 
6185ff872dSAneesh Kumar K.V 	if (!IS_ERR(dacl) && !IS_ERR(pacl)) {
6285ff872dSAneesh Kumar K.V 		set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl);
6385ff872dSAneesh Kumar K.V 		set_cached_acl(inode, ACL_TYPE_ACCESS, pacl);
6485ff872dSAneesh Kumar K.V 		posix_acl_release(dacl);
6585ff872dSAneesh Kumar K.V 		posix_acl_release(pacl);
6685ff872dSAneesh Kumar K.V 	} else
6785ff872dSAneesh Kumar K.V 		retval = -EIO;
6885ff872dSAneesh Kumar K.V 
6985ff872dSAneesh Kumar K.V 	return retval;
7085ff872dSAneesh Kumar K.V }
7185ff872dSAneesh Kumar K.V 
7285ff872dSAneesh Kumar K.V static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)
7385ff872dSAneesh Kumar K.V {
7485ff872dSAneesh Kumar K.V 	struct posix_acl *acl;
7585ff872dSAneesh Kumar K.V 	/*
7685ff872dSAneesh Kumar K.V 	 * 9p Always cache the acl value when
7785ff872dSAneesh Kumar K.V 	 * instantiating the inode (v9fs_inode_from_fid)
7885ff872dSAneesh Kumar K.V 	 */
7985ff872dSAneesh Kumar K.V 	acl = get_cached_acl(inode, type);
8085ff872dSAneesh Kumar K.V 	BUG_ON(acl == ACL_NOT_CACHED);
8185ff872dSAneesh Kumar K.V 	return acl;
8285ff872dSAneesh Kumar K.V }
8385ff872dSAneesh Kumar K.V 
8485ff872dSAneesh Kumar K.V int v9fs_check_acl(struct inode *inode, int mask)
8585ff872dSAneesh Kumar K.V {
8685ff872dSAneesh Kumar K.V 	struct posix_acl *acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
8785ff872dSAneesh Kumar K.V 
8885ff872dSAneesh Kumar K.V 	if (IS_ERR(acl))
8985ff872dSAneesh Kumar K.V 		return PTR_ERR(acl);
9085ff872dSAneesh Kumar K.V 	if (acl) {
9185ff872dSAneesh Kumar K.V 		int error = posix_acl_permission(inode, acl, mask);
9285ff872dSAneesh Kumar K.V 		posix_acl_release(acl);
9385ff872dSAneesh Kumar K.V 		return error;
9485ff872dSAneesh Kumar K.V 	}
9585ff872dSAneesh Kumar K.V 	return -EAGAIN;
9685ff872dSAneesh Kumar K.V }
97*7a4566b0SAneesh Kumar K.V 
98*7a4566b0SAneesh Kumar K.V static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
99*7a4566b0SAneesh Kumar K.V 			      void *buffer, size_t size, int type)
100*7a4566b0SAneesh Kumar K.V {
101*7a4566b0SAneesh Kumar K.V 	struct posix_acl *acl;
102*7a4566b0SAneesh Kumar K.V 	int error;
103*7a4566b0SAneesh Kumar K.V 
104*7a4566b0SAneesh Kumar K.V 	if (strcmp(name, "") != 0)
105*7a4566b0SAneesh Kumar K.V 		return -EINVAL;
106*7a4566b0SAneesh Kumar K.V 
107*7a4566b0SAneesh Kumar K.V 	acl = v9fs_get_cached_acl(dentry->d_inode, type);
108*7a4566b0SAneesh Kumar K.V 	if (IS_ERR(acl))
109*7a4566b0SAneesh Kumar K.V 		return PTR_ERR(acl);
110*7a4566b0SAneesh Kumar K.V 	if (acl == NULL)
111*7a4566b0SAneesh Kumar K.V 		return -ENODATA;
112*7a4566b0SAneesh Kumar K.V 	error = posix_acl_to_xattr(acl, buffer, size);
113*7a4566b0SAneesh Kumar K.V 	posix_acl_release(acl);
114*7a4566b0SAneesh Kumar K.V 
115*7a4566b0SAneesh Kumar K.V 	return error;
116*7a4566b0SAneesh Kumar K.V }
117*7a4566b0SAneesh Kumar K.V 
118*7a4566b0SAneesh Kumar K.V static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
119*7a4566b0SAneesh Kumar K.V 			      const void *value, size_t size,
120*7a4566b0SAneesh Kumar K.V 			      int flags, int type)
121*7a4566b0SAneesh Kumar K.V {
122*7a4566b0SAneesh Kumar K.V 	return 0;
123*7a4566b0SAneesh Kumar K.V }
124*7a4566b0SAneesh Kumar K.V 
125*7a4566b0SAneesh Kumar K.V const struct xattr_handler v9fs_xattr_acl_access_handler = {
126*7a4566b0SAneesh Kumar K.V 	.prefix	= POSIX_ACL_XATTR_ACCESS,
127*7a4566b0SAneesh Kumar K.V 	.flags	= ACL_TYPE_ACCESS,
128*7a4566b0SAneesh Kumar K.V 	.get	= v9fs_xattr_get_acl,
129*7a4566b0SAneesh Kumar K.V 	.set	= v9fs_xattr_set_acl,
130*7a4566b0SAneesh Kumar K.V };
131*7a4566b0SAneesh Kumar K.V 
132*7a4566b0SAneesh Kumar K.V const struct xattr_handler v9fs_xattr_acl_default_handler = {
133*7a4566b0SAneesh Kumar K.V 	.prefix	= POSIX_ACL_XATTR_DEFAULT,
134*7a4566b0SAneesh Kumar K.V 	.flags	= ACL_TYPE_DEFAULT,
135*7a4566b0SAneesh Kumar K.V 	.get	= v9fs_xattr_get_acl,
136*7a4566b0SAneesh Kumar K.V 	.set	= v9fs_xattr_set_acl,
137*7a4566b0SAneesh Kumar K.V };
138