xref: /openbmc/linux/fs/9p/acl.c (revision 85ff872d3f4a62d076d698bd1fa15ca2a4d7c100)
1*85ff872dSAneesh Kumar K.V /*
2*85ff872dSAneesh Kumar K.V  * Copyright IBM Corporation, 2010
3*85ff872dSAneesh Kumar K.V  * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
4*85ff872dSAneesh Kumar K.V  *
5*85ff872dSAneesh Kumar K.V  * This program is free software; you can redistribute it and/or modify it
6*85ff872dSAneesh Kumar K.V  * under the terms of version 2.1 of the GNU Lesser General Public License
7*85ff872dSAneesh Kumar K.V  * as published by the Free Software Foundation.
8*85ff872dSAneesh Kumar K.V  *
9*85ff872dSAneesh Kumar K.V  * This program is distributed in the hope that it would be useful, but
10*85ff872dSAneesh Kumar K.V  * WITHOUT ANY WARRANTY; without even the implied warranty of
11*85ff872dSAneesh Kumar K.V  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12*85ff872dSAneesh Kumar K.V  *
13*85ff872dSAneesh Kumar K.V  */
14*85ff872dSAneesh Kumar K.V 
15*85ff872dSAneesh Kumar K.V #include <linux/module.h>
16*85ff872dSAneesh Kumar K.V #include <linux/fs.h>
17*85ff872dSAneesh Kumar K.V #include <net/9p/9p.h>
18*85ff872dSAneesh Kumar K.V #include <net/9p/client.h>
19*85ff872dSAneesh Kumar K.V #include <linux/slab.h>
20*85ff872dSAneesh Kumar K.V #include <linux/posix_acl_xattr.h>
21*85ff872dSAneesh Kumar K.V #include "xattr.h"
22*85ff872dSAneesh Kumar K.V #include "acl.h"
23*85ff872dSAneesh Kumar K.V 
24*85ff872dSAneesh Kumar K.V static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
25*85ff872dSAneesh Kumar K.V {
26*85ff872dSAneesh Kumar K.V 	ssize_t size;
27*85ff872dSAneesh Kumar K.V 	void *value = NULL;
28*85ff872dSAneesh Kumar K.V 	struct posix_acl *acl = NULL;;
29*85ff872dSAneesh Kumar K.V 
30*85ff872dSAneesh Kumar K.V 	size = v9fs_fid_xattr_get(fid, name, NULL, 0);
31*85ff872dSAneesh Kumar K.V 	if (size > 0) {
32*85ff872dSAneesh Kumar K.V 		value = kzalloc(size, GFP_NOFS);
33*85ff872dSAneesh Kumar K.V 		if (!value)
34*85ff872dSAneesh Kumar K.V 			return ERR_PTR(-ENOMEM);
35*85ff872dSAneesh Kumar K.V 		size = v9fs_fid_xattr_get(fid, name, value, size);
36*85ff872dSAneesh Kumar K.V 		if (size > 0) {
37*85ff872dSAneesh Kumar K.V 			acl = posix_acl_from_xattr(value, size);
38*85ff872dSAneesh Kumar K.V 			if (IS_ERR(acl))
39*85ff872dSAneesh Kumar K.V 				goto err_out;
40*85ff872dSAneesh Kumar K.V 		}
41*85ff872dSAneesh Kumar K.V 	} else if (size == -ENODATA || size == 0 ||
42*85ff872dSAneesh Kumar K.V 		   size == -ENOSYS || size == -EOPNOTSUPP) {
43*85ff872dSAneesh Kumar K.V 		acl = NULL;
44*85ff872dSAneesh Kumar K.V 	} else
45*85ff872dSAneesh Kumar K.V 		acl = ERR_PTR(-EIO);
46*85ff872dSAneesh Kumar K.V 
47*85ff872dSAneesh Kumar K.V err_out:
48*85ff872dSAneesh Kumar K.V 	kfree(value);
49*85ff872dSAneesh Kumar K.V 	return acl;
50*85ff872dSAneesh Kumar K.V }
51*85ff872dSAneesh Kumar K.V 
52*85ff872dSAneesh Kumar K.V int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
53*85ff872dSAneesh Kumar K.V {
54*85ff872dSAneesh Kumar K.V 	int retval = 0;
55*85ff872dSAneesh Kumar K.V 	struct posix_acl *pacl, *dacl;
56*85ff872dSAneesh Kumar K.V 
57*85ff872dSAneesh Kumar K.V 	/* get the default/access acl values and cache them */
58*85ff872dSAneesh Kumar K.V 	dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT);
59*85ff872dSAneesh Kumar K.V 	pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS);
60*85ff872dSAneesh Kumar K.V 
61*85ff872dSAneesh Kumar K.V 	if (!IS_ERR(dacl) && !IS_ERR(pacl)) {
62*85ff872dSAneesh Kumar K.V 		set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl);
63*85ff872dSAneesh Kumar K.V 		set_cached_acl(inode, ACL_TYPE_ACCESS, pacl);
64*85ff872dSAneesh Kumar K.V 		posix_acl_release(dacl);
65*85ff872dSAneesh Kumar K.V 		posix_acl_release(pacl);
66*85ff872dSAneesh Kumar K.V 	} else
67*85ff872dSAneesh Kumar K.V 		retval = -EIO;
68*85ff872dSAneesh Kumar K.V 
69*85ff872dSAneesh Kumar K.V 	return retval;
70*85ff872dSAneesh Kumar K.V }
71*85ff872dSAneesh Kumar K.V 
72*85ff872dSAneesh Kumar K.V static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)
73*85ff872dSAneesh Kumar K.V {
74*85ff872dSAneesh Kumar K.V 	struct posix_acl *acl;
75*85ff872dSAneesh Kumar K.V 	/*
76*85ff872dSAneesh Kumar K.V 	 * 9p Always cache the acl value when
77*85ff872dSAneesh Kumar K.V 	 * instantiating the inode (v9fs_inode_from_fid)
78*85ff872dSAneesh Kumar K.V 	 */
79*85ff872dSAneesh Kumar K.V 	acl = get_cached_acl(inode, type);
80*85ff872dSAneesh Kumar K.V 	BUG_ON(acl == ACL_NOT_CACHED);
81*85ff872dSAneesh Kumar K.V 	return acl;
82*85ff872dSAneesh Kumar K.V }
83*85ff872dSAneesh Kumar K.V 
84*85ff872dSAneesh Kumar K.V int v9fs_check_acl(struct inode *inode, int mask)
85*85ff872dSAneesh Kumar K.V {
86*85ff872dSAneesh Kumar K.V 	struct posix_acl *acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
87*85ff872dSAneesh Kumar K.V 
88*85ff872dSAneesh Kumar K.V 	if (IS_ERR(acl))
89*85ff872dSAneesh Kumar K.V 		return PTR_ERR(acl);
90*85ff872dSAneesh Kumar K.V 	if (acl) {
91*85ff872dSAneesh Kumar K.V 		int error = posix_acl_permission(inode, acl, mask);
92*85ff872dSAneesh Kumar K.V 		posix_acl_release(acl);
93*85ff872dSAneesh Kumar K.V 		return error;
94*85ff872dSAneesh Kumar K.V 	}
95*85ff872dSAneesh Kumar K.V 	return -EAGAIN;
96*85ff872dSAneesh Kumar K.V }
97