Blame view

fs/nfsd/nfs3acl.c 6.29 KB
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
1
  /*
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
2
3
4
5
   * Process version 3 NFSACL requests.
   *
   * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
   */
9a74af213   Boaz Harrosh   nfsd: Move privat...
6
7
  #include "nfsd.h"
  /* FIXME: nfsacl.h is a broken header */
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
8
  #include <linux/nfsacl.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
9
  #include <linux/gfp.h>
9a74af213   Boaz Harrosh   nfsd: Move privat...
10
11
  #include "cache.h"
  #include "xdr3.h"
0a3adadee   J. Bruce Fields   nfsd: make fs/nfs...
12
  #include "vfs.h"
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
13
14
15
16
17
18
  
  #define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
  
  /*
   * NULL call.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
19
  static __be32
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
20
21
22
23
24
25
26
27
  nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
  {
  	return nfs_ok;
  }
  
  /*
   * Get the Access and/or Default ACL of a file.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
28
  static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
29
30
  		struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
  {
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
31
  	struct posix_acl *acl;
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
32
33
  	struct inode *inode;
  	svc_fh *fh;
c4d987ba8   Al Viro   [PATCH] nfsd: NFS...
34
  	__be32 nfserr = 0;
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
35
36
  
  	fh = fh_copy(&resp->fh, &argp->fh);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
37
38
  	nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
  	if (nfserr)
ac8587dcb   J. Bruce Fields   knfsd: fix spurio...
39
  		RETURN_STATUS(nfserr);
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
40

2b0143b5c   David Howells   VFS: normal files...
41
  	inode = d_inode(fh->fh_dentry);
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
42

7b8f45865   Kinglong Mee   nfsd: Add macro N...
43
  	if (argp->mask & ~NFS_ACL_MASK)
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
44
45
46
47
  		RETURN_STATUS(nfserr_inval);
  	resp->mask = argp->mask;
  
  	if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
48
  		acl = get_acl(inode, ACL_TYPE_ACCESS);
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
49
50
  		if (acl == NULL) {
  			/* Solaris returns the inode's minimum ACL. */
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
51
52
  			acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
  		}
35e634b83   Kinglong Mee   NFSD: Check acl r...
53
54
55
56
  		if (IS_ERR(acl)) {
  			nfserr = nfserrno(PTR_ERR(acl));
  			goto fail;
  		}
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
57
58
59
60
61
  		resp->acl_access = acl;
  	}
  	if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
  		/* Check how Solaris handles requests for the Default ACL
  		   of a non-directory! */
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
62
  		acl = get_acl(inode, ACL_TYPE_DEFAULT);
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
63
  		if (IS_ERR(acl)) {
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
64
65
  			nfserr = nfserrno(PTR_ERR(acl));
  			goto fail;
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  		}
  		resp->acl_default = acl;
  	}
  
  	/* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
  	RETURN_STATUS(0);
  
  fail:
  	posix_acl_release(resp->acl_access);
  	posix_acl_release(resp->acl_default);
  	RETURN_STATUS(nfserr);
  }
  
  /*
   * Set the Access and/or Default ACL of a file.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
82
  static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp,
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
83
84
85
  		struct nfsd3_setaclargs *argp,
  		struct nfsd3_attrstat *resp)
  {
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
86
  	struct inode *inode;
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
87
  	svc_fh *fh;
c4d987ba8   Al Viro   [PATCH] nfsd: NFS...
88
  	__be32 nfserr = 0;
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
89
  	int error;
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
90
91
  
  	fh = fh_copy(&resp->fh, &argp->fh);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
92
  	nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
93
94
  	if (nfserr)
  		goto out;
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
95

2b0143b5c   David Howells   VFS: normal files...
96
  	inode = d_inode(fh->fh_dentry);
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
97

4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
98
99
100
  	error = fh_want_write(fh);
  	if (error)
  		goto out_errno;
999653786   Ben Hutchings   nfsd: check permi...
101
102
103
  	fh_lock(fh);
  
  	error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
104
  	if (error)
999653786   Ben Hutchings   nfsd: check permi...
105
106
  		goto out_drop_lock;
  	error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
107

999653786   Ben Hutchings   nfsd: check permi...
108
109
  out_drop_lock:
  	fh_unlock(fh);
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
110
111
112
113
  	fh_drop_write(fh);
  out_errno:
  	nfserr = nfserrno(error);
  out:
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
114
115
116
117
118
119
120
121
122
123
  	/* argp->acl_{access,default} may have been allocated in
  	   nfs3svc_decode_setaclargs. */
  	posix_acl_release(argp->acl_access);
  	posix_acl_release(argp->acl_default);
  	RETURN_STATUS(nfserr);
  }
  
  /*
   * XDR decode functions
   */
91f07168c   Al Viro   [PATCH] xdr annot...
124
  static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p,
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
125
126
  		struct nfsd3_getaclargs *args)
  {
d40aa3372   Benoit Taine   nfsd: Remove assi...
127
128
  	p = nfs3svc_decode_fh(p, &args->fh);
  	if (!p)
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
129
130
131
132
133
  		return 0;
  	args->mask = ntohl(*p); p++;
  
  	return xdr_argsize_check(rqstp, p);
  }
91f07168c   Al Viro   [PATCH] xdr annot...
134
  static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p,
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
135
136
137
138
139
  		struct nfsd3_setaclargs *args)
  {
  	struct kvec *head = rqstp->rq_arg.head;
  	unsigned int base;
  	int n;
d40aa3372   Benoit Taine   nfsd: Remove assi...
140
141
  	p = nfs3svc_decode_fh(p, &args->fh);
  	if (!p)
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
142
143
  		return 0;
  	args->mask = ntohl(*p++);
7b8f45865   Kinglong Mee   nfsd: Add macro N...
144
  	if (args->mask & ~NFS_ACL_MASK ||
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  	    !xdr_argsize_check(rqstp, p))
  		return 0;
  
  	base = (char *)p - (char *)head->iov_base;
  	n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
  			  (args->mask & NFS_ACL) ?
  			  &args->acl_access : NULL);
  	if (n > 0)
  		n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
  				  (args->mask & NFS_DFACL) ?
  				  &args->acl_default : NULL);
  	return (n > 0);
  }
  
  /*
   * XDR encode functions
   */
  
  /* GETACL */
91f07168c   Al Viro   [PATCH] xdr annot...
164
  static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
165
166
167
168
169
  		struct nfsd3_getaclres *resp)
  {
  	struct dentry *dentry = resp->fh.fh_dentry;
  
  	p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
2b0143b5c   David Howells   VFS: normal files...
170
171
  	if (resp->status == 0 && dentry && d_really_is_positive(dentry)) {
  		struct inode *inode = d_inode(dentry);
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
172
173
174
  		struct kvec *head = rqstp->rq_res.head;
  		unsigned int base;
  		int n;
14d2b59e8   Jesper Juhl   [PATCH] NFS3: Cal...
175
  		int w;
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
176
177
178
179
180
  
  		*p++ = htonl(resp->mask);
  		if (!xdr_ressize_check(rqstp, p))
  			return 0;
  		base = (char *)p - (char *)head->iov_base;
14d2b59e8   Jesper Juhl   [PATCH] NFS3: Cal...
181
182
183
  		rqstp->rq_res.page_len = w = nfsacl_size(
  			(resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
  			(resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
184
  		while (w > 0) {
afc59400d   J. Bruce Fields   nfsd4: cleanup: r...
185
  			if (!*(rqstp->rq_next_page++))
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  				return 0;
  			w -= PAGE_SIZE;
  		}
  
  		n = nfsacl_encode(&rqstp->rq_res, base, inode,
  				  resp->acl_access,
  				  resp->mask & NFS_ACL, 0);
  		if (n > 0)
  			n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
  					  resp->acl_default,
  					  resp->mask & NFS_DFACL,
  					  NFS_ACL_DEFAULT);
  		if (n <= 0)
  			return 0;
  	} else
  		if (!xdr_ressize_check(rqstp, p))
  			return 0;
  
  	return 1;
  }
  
  /* SETACL */
91f07168c   Al Viro   [PATCH] xdr annot...
208
  static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p,
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
209
210
211
212
213
214
215
216
217
218
  		struct nfsd3_attrstat *resp)
  {
  	p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
  
  	return xdr_ressize_check(rqstp, p);
  }
  
  /*
   * XDR release functions
   */
91f07168c   Al Viro   [PATCH] xdr annot...
219
  static int nfs3svc_release_getacl(struct svc_rqst *rqstp, __be32 *p,
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  		struct nfsd3_getaclres *resp)
  {
  	fh_put(&resp->fh);
  	posix_acl_release(resp->acl_access);
  	posix_acl_release(resp->acl_default);
  	return 1;
  }
  
  #define nfs3svc_decode_voidargs		NULL
  #define nfs3svc_release_void		NULL
  #define nfsd3_setaclres			nfsd3_attrstat
  #define nfsd3_voidres			nfsd3_voidargs
  struct nfsd3_voidargs { int dummy; };
  
  #define PROC(name, argt, rest, relt, cache, respsize)	\
   { (svc_procfunc) nfsd3_proc_##name,		\
     (kxdrproc_t) nfs3svc_decode_##argt##args,	\
     (kxdrproc_t) nfs3svc_encode_##rest##res,	\
     (kxdrproc_t) nfs3svc_release_##relt,		\
     sizeof(struct nfsd3_##argt##args),		\
     sizeof(struct nfsd3_##rest##res),		\
     0,						\
     cache,					\
     respsize,					\
   }
  
  #define ST 1		/* status*/
  #define AT 21		/* attributes */
  #define pAT (1+AT)	/* post attributes - conditional */
  #define ACL (1+NFS_ACL_MAX_ENTRIES*3)  /* Access Control List */
  
  static struct svc_procedure		nfsd_acl_procedures3[] = {
    PROC(null,	void,		void,		void,	  RC_NOCACHE, ST),
    PROC(getacl,	getacl,		getacl,		getacl,	  RC_NOCACHE, ST+1+2*(1+ACL)),
    PROC(setacl,	setacl,		setacl,		fhandle,  RC_NOCACHE, ST+pAT),
  };
  
  struct svc_version	nfsd_acl_version3 = {
  		.vs_vers	= 3,
  		.vs_nproc	= 3,
  		.vs_proc	= nfsd_acl_procedures3,
  		.vs_dispatch	= nfsd_dispatch,
  		.vs_xdrsize	= NFS3_SVC_XDRSIZE,
1b7e0403c   Peter Staubach   nfsd: register NF...
263
  		.vs_hidden	= 0,
a257cdd0e   Andreas Gruenbacher   [PATCH] NFSD: Add...
264
  };