1#include <linux/fs.h>
2#include <linux/nfs.h>
3#include <linux/nfs3.h>
4#include <linux/nfs_fs.h>
5#include <linux/posix_acl_xattr.h>
6#include <linux/nfsacl.h>
7
8#define NFSDBG_FACILITY	NFSDBG_PROC
9
10ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
11{
12	struct inode *inode = dentry->d_inode;
13	struct posix_acl *acl;
14	int pos=0, len=0;
15
16#	define output(s) do {						\
17			if (pos + sizeof(s) <= size) {			\
18				memcpy(buffer + pos, s, sizeof(s));	\
19				pos += sizeof(s);			\
20			}						\
21			len += sizeof(s);				\
22		} while(0)
23
24	acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS);
25	if (IS_ERR(acl))
26		return PTR_ERR(acl);
27	if (acl) {
28		output("system.posix_acl_access");
29		posix_acl_release(acl);
30	}
31
32	if (S_ISDIR(inode->i_mode)) {
33		acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT);
34		if (IS_ERR(acl))
35			return PTR_ERR(acl);
36		if (acl) {
37			output("system.posix_acl_default");
38			posix_acl_release(acl);
39		}
40	}
41
42#	undef output
43
44	if (!buffer || len <= size)
45		return len;
46	return -ERANGE;
47}
48
49ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
50		void *buffer, size_t size)
51{
52	struct inode *inode = dentry->d_inode;
53	struct posix_acl *acl;
54	int type, error = 0;
55
56	if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
57		type = ACL_TYPE_ACCESS;
58	else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
59		type = ACL_TYPE_DEFAULT;
60	else
61		return -EOPNOTSUPP;
62
63	acl = nfs3_proc_getacl(inode, type);
64	if (IS_ERR(acl))
65		return PTR_ERR(acl);
66	else if (acl) {
67		if (type == ACL_TYPE_ACCESS && acl->a_count == 0)
68			error = -ENODATA;
69		else
70			error = posix_acl_to_xattr(acl, buffer, size);
71		posix_acl_release(acl);
72	} else
73		error = -ENODATA;
74
75	return error;
76}
77
78int nfs3_setxattr(struct dentry *dentry, const char *name,
79	     const void *value, size_t size, int flags)
80{
81	struct inode *inode = dentry->d_inode;
82	struct posix_acl *acl;
83	int type, error;
84
85	if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
86		type = ACL_TYPE_ACCESS;
87	else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
88		type = ACL_TYPE_DEFAULT;
89	else
90		return -EOPNOTSUPP;
91
92	acl = posix_acl_from_xattr(value, size);
93	if (IS_ERR(acl))
94		return PTR_ERR(acl);
95	error = nfs3_proc_setacl(inode, type, acl);
96	posix_acl_release(acl);
97
98	return error;
99}
100
101int nfs3_removexattr(struct dentry *dentry, const char *name)
102{
103	struct inode *inode = dentry->d_inode;
104	int type;
105
106	if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
107		type = ACL_TYPE_ACCESS;
108	else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
109		type = ACL_TYPE_DEFAULT;
110	else
111		return -EOPNOTSUPP;
112
113	return nfs3_proc_setacl(inode, type, NULL);
114}
115
116static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
117{
118	if (!IS_ERR(nfsi->acl_access)) {
119		posix_acl_release(nfsi->acl_access);
120		nfsi->acl_access = ERR_PTR(-EAGAIN);
121	}
122	if (!IS_ERR(nfsi->acl_default)) {
123		posix_acl_release(nfsi->acl_default);
124		nfsi->acl_default = ERR_PTR(-EAGAIN);
125	}
126}
127
128void nfs3_forget_cached_acls(struct inode *inode)
129{
130	dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id,
131		inode->i_ino);
132	spin_lock(&inode->i_lock);
133	__nfs3_forget_cached_acls(NFS_I(inode));
134	spin_unlock(&inode->i_lock);
135}
136
137static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type)
138{
139	struct nfs_inode *nfsi = NFS_I(inode);
140	struct posix_acl *acl = ERR_PTR(-EINVAL);
141
142	spin_lock(&inode->i_lock);
143	switch(type) {
144		case ACL_TYPE_ACCESS:
145			acl = nfsi->acl_access;
146			break;
147
148		case ACL_TYPE_DEFAULT:
149			acl = nfsi->acl_default;
150			break;
151
152		default:
153			goto out;
154	}
155	if (IS_ERR(acl))
156		acl = ERR_PTR(-EAGAIN);
157	else
158		acl = posix_acl_dup(acl);
159out:
160	spin_unlock(&inode->i_lock);
161	dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id,
162		inode->i_ino, type, acl);
163	return acl;
164}
165
166static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
167		    struct posix_acl *dfacl)
168{
169	struct nfs_inode *nfsi = NFS_I(inode);
170
171	dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id,
172		inode->i_ino, acl, dfacl);
173	spin_lock(&inode->i_lock);
174	__nfs3_forget_cached_acls(NFS_I(inode));
175	if (!IS_ERR(acl))
176		nfsi->acl_access = posix_acl_dup(acl);
177	if (!IS_ERR(dfacl))
178		nfsi->acl_default = posix_acl_dup(dfacl);
179	spin_unlock(&inode->i_lock);
180}
181
182struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
183{
184	struct nfs_server *server = NFS_SERVER(inode);
185	struct nfs_fattr fattr;
186	struct page *pages[NFSACL_MAXPAGES] = { };
187	struct nfs3_getaclargs args = {
188		.fh = NFS_FH(inode),
189		/* The xdr layer may allocate pages here. */
190		.pages = pages,
191	};
192	struct nfs3_getaclres res = {
193		.fattr =	&fattr,
194	};
195	struct rpc_message msg = {
196		.rpc_argp	= &args,
197		.rpc_resp	= &res,
198	};
199	struct posix_acl *acl;
200	int status, count;
201
202	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
203		return ERR_PTR(-EOPNOTSUPP);
204
205	status = nfs_revalidate_inode(server, inode);
206	if (status < 0)
207		return ERR_PTR(status);
208	acl = nfs3_get_cached_acl(inode, type);
209	if (acl != ERR_PTR(-EAGAIN))
210		return acl;
211	acl = NULL;
212
213	/*
214	 * Only get the access acl when explicitly requested: We don't
215	 * need it for access decisions, and only some applications use
216	 * it. Applications which request the access acl first are not
217	 * penalized from this optimization.
218	 */
219	if (type == ACL_TYPE_ACCESS)
220		args.mask |= NFS_ACLCNT|NFS_ACL;
221	if (S_ISDIR(inode->i_mode))
222		args.mask |= NFS_DFACLCNT|NFS_DFACL;
223	if (args.mask == 0)
224		return NULL;
225
226	dprintk("NFS call getacl\n");
227	msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL];
228	status = rpc_call_sync(server->client_acl, &msg, 0);
229	dprintk("NFS reply getacl: %d\n", status);
230
231	/* pages may have been allocated at the xdr layer. */
232	for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
233		__free_page(args.pages[count]);
234
235	switch (status) {
236		case 0:
237			status = nfs_refresh_inode(inode, &fattr);
238			break;
239		case -EPFNOSUPPORT:
240		case -EPROTONOSUPPORT:
241			dprintk("NFS_V3_ACL extension not supported; disabling\n");
242			server->caps &= ~NFS_CAP_ACLS;
243		case -ENOTSUPP:
244			status = -EOPNOTSUPP;
245		default:
246			goto getout;
247	}
248	if ((args.mask & res.mask) != args.mask) {
249		status = -EIO;
250		goto getout;
251	}
252
253	if (res.acl_access != NULL) {
254		if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) {
255			posix_acl_release(res.acl_access);
256			res.acl_access = NULL;
257		}
258	}
259	nfs3_cache_acls(inode,
260		(res.mask & NFS_ACL)   ? res.acl_access  : ERR_PTR(-EINVAL),
261		(res.mask & NFS_DFACL) ? res.acl_default : ERR_PTR(-EINVAL));
262
263	switch(type) {
264		case ACL_TYPE_ACCESS:
265			acl = res.acl_access;
266			res.acl_access = NULL;
267			break;
268
269		case ACL_TYPE_DEFAULT:
270			acl = res.acl_default;
271			res.acl_default = NULL;
272	}
273
274getout:
275	posix_acl_release(res.acl_access);
276	posix_acl_release(res.acl_default);
277
278	if (status != 0) {
279		posix_acl_release(acl);
280		acl = ERR_PTR(status);
281	}
282	return acl;
283}
284
285static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
286		  struct posix_acl *dfacl)
287{
288	struct nfs_server *server = NFS_SERVER(inode);
289	struct nfs_fattr fattr;
290	struct page *pages[NFSACL_MAXPAGES] = { };
291	struct nfs3_setaclargs args = {
292		.inode = inode,
293		.mask = NFS_ACL,
294		.acl_access = acl,
295		.pages = pages,
296	};
297	struct rpc_message msg = {
298		.rpc_argp	= &args,
299		.rpc_resp	= &fattr,
300	};
301	int status, count;
302
303	status = -EOPNOTSUPP;
304	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
305		goto out;
306
307	/* We are doing this here, because XDR marshalling can only
308	   return -ENOMEM. */
309	status = -ENOSPC;
310	if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES)
311		goto out;
312	if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES)
313		goto out;
314	if (S_ISDIR(inode->i_mode)) {
315		args.mask |= NFS_DFACL;
316		args.acl_default = dfacl;
317	}
318
319	dprintk("NFS call setacl\n");
320	nfs_begin_data_update(inode);
321	msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL];
322	status = rpc_call_sync(server->client_acl, &msg, 0);
323	spin_lock(&inode->i_lock);
324	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS;
325	spin_unlock(&inode->i_lock);
326	nfs_end_data_update(inode);
327	dprintk("NFS reply setacl: %d\n", status);
328
329	/* pages may have been allocated at the xdr layer. */
330	for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
331		__free_page(args.pages[count]);
332
333	switch (status) {
334		case 0:
335			status = nfs_refresh_inode(inode, &fattr);
336			nfs3_cache_acls(inode, acl, dfacl);
337			break;
338		case -EPFNOSUPPORT:
339		case -EPROTONOSUPPORT:
340			dprintk("NFS_V3_ACL SETACL RPC not supported"
341					"(will not retry)\n");
342			server->caps &= ~NFS_CAP_ACLS;
343		case -ENOTSUPP:
344			status = -EOPNOTSUPP;
345	}
346out:
347	return status;
348}
349
350int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
351{
352	struct posix_acl *alloc = NULL, *dfacl = NULL;
353	int status;
354
355	if (S_ISDIR(inode->i_mode)) {
356		switch(type) {
357			case ACL_TYPE_ACCESS:
358				alloc = dfacl = nfs3_proc_getacl(inode,
359						ACL_TYPE_DEFAULT);
360				if (IS_ERR(alloc))
361					goto fail;
362				break;
363
364			case ACL_TYPE_DEFAULT:
365				dfacl = acl;
366				alloc = acl = nfs3_proc_getacl(inode,
367						ACL_TYPE_ACCESS);
368				if (IS_ERR(alloc))
369					goto fail;
370				break;
371
372			default:
373				return -EINVAL;
374		}
375	} else if (type != ACL_TYPE_ACCESS)
376			return -EINVAL;
377
378	if (acl == NULL) {
379		alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
380		if (IS_ERR(alloc))
381			goto fail;
382	}
383	status = nfs3_proc_setacls(inode, acl, dfacl);
384	posix_acl_release(alloc);
385	return status;
386
387fail:
388	return PTR_ERR(alloc);
389}
390
391int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
392		mode_t mode)
393{
394	struct posix_acl *dfacl, *acl;
395	int error = 0;
396
397	dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT);
398	if (IS_ERR(dfacl)) {
399		error = PTR_ERR(dfacl);
400		return (error == -EOPNOTSUPP) ? 0 : error;
401	}
402	if (!dfacl)
403		return 0;
404	acl = posix_acl_clone(dfacl, GFP_KERNEL);
405	error = -ENOMEM;
406	if (!acl)
407		goto out_release_dfacl;
408	error = posix_acl_create_masq(acl, &mode);
409	if (error < 0)
410		goto out_release_acl;
411	error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
412						      dfacl : NULL);
413out_release_acl:
414	posix_acl_release(acl);
415out_release_dfacl:
416	posix_acl_release(dfacl);
417	return error;
418}
419