1 // SPDX-License-Identifier: GPL-2.0
3 * Process version 2 NFSACL requests.
5 * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
9 /* FIXME: nfsacl.h is a broken header */
10 #include <linux/nfsacl.h>
11 #include <linux/gfp.h>
16 #define NFSDDBG_FACILITY NFSDDBG_PROC
22 nfsacld_proc_null(struct svc_rqst
*rqstp
)
28 * Get the Access and/or Default ACL of a file.
30 static __be32
nfsacld_proc_getacl(struct svc_rqst
*rqstp
)
32 struct nfsd3_getaclargs
*argp
= rqstp
->rq_argp
;
33 struct nfsd3_getaclres
*resp
= rqstp
->rq_resp
;
34 struct posix_acl
*acl
;
38 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp
->fh
));
40 fh
= fh_copy(&resp
->fh
, &argp
->fh
);
41 resp
->status
= fh_verify(rqstp
, &resp
->fh
, 0, NFSD_MAY_NOP
);
42 if (resp
->status
!= nfs_ok
)
45 inode
= d_inode(fh
->fh_dentry
);
47 if (argp
->mask
& ~NFS_ACL_MASK
) {
48 resp
->status
= nfserr_inval
;
51 resp
->mask
= argp
->mask
;
53 resp
->status
= fh_getattr(fh
, &resp
->stat
);
54 if (resp
->status
!= nfs_ok
)
57 if (resp
->mask
& (NFS_ACL
|NFS_ACLCNT
)) {
58 acl
= get_acl(inode
, ACL_TYPE_ACCESS
);
60 /* Solaris returns the inode's minimum ACL. */
61 acl
= posix_acl_from_mode(inode
->i_mode
, GFP_KERNEL
);
64 resp
->status
= nfserrno(PTR_ERR(acl
));
67 resp
->acl_access
= acl
;
69 if (resp
->mask
& (NFS_DFACL
|NFS_DFACLCNT
)) {
70 /* Check how Solaris handles requests for the Default ACL
71 of a non-directory! */
72 acl
= get_acl(inode
, ACL_TYPE_DEFAULT
);
74 resp
->status
= nfserrno(PTR_ERR(acl
));
77 resp
->acl_default
= acl
;
80 /* resp->acl_{access,default} are released in nfssvc_release_getacl. */
85 posix_acl_release(resp
->acl_access
);
86 posix_acl_release(resp
->acl_default
);
91 * Set the Access and/or Default ACL of a file.
93 static __be32
nfsacld_proc_setacl(struct svc_rqst
*rqstp
)
95 struct nfsd3_setaclargs
*argp
= rqstp
->rq_argp
;
96 struct nfsd_attrstat
*resp
= rqstp
->rq_resp
;
101 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp
->fh
));
103 fh
= fh_copy(&resp
->fh
, &argp
->fh
);
104 resp
->status
= fh_verify(rqstp
, &resp
->fh
, 0, NFSD_MAY_SATTR
);
105 if (resp
->status
!= nfs_ok
)
108 inode
= d_inode(fh
->fh_dentry
);
110 error
= fh_want_write(fh
);
116 error
= set_posix_acl(&init_user_ns
, inode
, ACL_TYPE_ACCESS
,
120 error
= set_posix_acl(&init_user_ns
, inode
, ACL_TYPE_DEFAULT
,
129 resp
->status
= fh_getattr(fh
, &resp
->stat
);
132 /* argp->acl_{access,default} may have been allocated in
133 nfssvc_decode_setaclargs. */
134 posix_acl_release(argp
->acl_access
);
135 posix_acl_release(argp
->acl_default
);
142 resp
->status
= nfserrno(error
);
147 * Check file attributes
149 static __be32
nfsacld_proc_getattr(struct svc_rqst
*rqstp
)
151 struct nfsd_fhandle
*argp
= rqstp
->rq_argp
;
152 struct nfsd_attrstat
*resp
= rqstp
->rq_resp
;
154 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp
->fh
));
156 fh_copy(&resp
->fh
, &argp
->fh
);
157 resp
->status
= fh_verify(rqstp
, &resp
->fh
, 0, NFSD_MAY_NOP
);
158 if (resp
->status
!= nfs_ok
)
160 resp
->status
= fh_getattr(&resp
->fh
, &resp
->stat
);
168 static __be32
nfsacld_proc_access(struct svc_rqst
*rqstp
)
170 struct nfsd3_accessargs
*argp
= rqstp
->rq_argp
;
171 struct nfsd3_accessres
*resp
= rqstp
->rq_resp
;
173 dprintk("nfsd: ACCESS(2acl) %s 0x%x\n",
174 SVCFH_fmt(&argp
->fh
),
177 fh_copy(&resp
->fh
, &argp
->fh
);
178 resp
->access
= argp
->access
;
179 resp
->status
= nfsd_access(rqstp
, &resp
->fh
, &resp
->access
, NULL
);
180 if (resp
->status
!= nfs_ok
)
182 resp
->status
= fh_getattr(&resp
->fh
, &resp
->stat
);
188 * XDR decode functions
191 static int nfsaclsvc_decode_getaclargs(struct svc_rqst
*rqstp
, __be32
*p
)
193 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
194 struct nfsd3_getaclargs
*argp
= rqstp
->rq_argp
;
196 if (!svcxdr_decode_fhandle(xdr
, &argp
->fh
))
198 if (xdr_stream_decode_u32(xdr
, &argp
->mask
) < 0)
204 static int nfsaclsvc_decode_setaclargs(struct svc_rqst
*rqstp
, __be32
*p
)
206 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
207 struct nfsd3_setaclargs
*argp
= rqstp
->rq_argp
;
209 if (!svcxdr_decode_fhandle(xdr
, &argp
->fh
))
211 if (xdr_stream_decode_u32(xdr
, &argp
->mask
) < 0)
213 if (argp
->mask
& ~NFS_ACL_MASK
)
215 if (!nfs_stream_decode_acl(xdr
, NULL
, (argp
->mask
& NFS_ACL
) ?
216 &argp
->acl_access
: NULL
))
218 if (!nfs_stream_decode_acl(xdr
, NULL
, (argp
->mask
& NFS_DFACL
) ?
219 &argp
->acl_default
: NULL
))
225 static int nfsaclsvc_decode_accessargs(struct svc_rqst
*rqstp
, __be32
*p
)
227 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
228 struct nfsd3_accessargs
*args
= rqstp
->rq_argp
;
230 if (!svcxdr_decode_fhandle(xdr
, &args
->fh
))
232 if (xdr_stream_decode_u32(xdr
, &args
->access
) < 0)
239 * XDR encode functions
243 static int nfsaclsvc_encode_getaclres(struct svc_rqst
*rqstp
, __be32
*p
)
245 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
246 struct nfsd3_getaclres
*resp
= rqstp
->rq_resp
;
247 struct dentry
*dentry
= resp
->fh
.fh_dentry
;
251 if (!svcxdr_encode_stat(xdr
, resp
->status
))
254 if (dentry
== NULL
|| d_really_is_negative(dentry
))
256 inode
= d_inode(dentry
);
258 if (!svcxdr_encode_fattr(rqstp
, xdr
, &resp
->fh
, &resp
->stat
))
260 if (xdr_stream_encode_u32(xdr
, resp
->mask
) < 0)
263 rqstp
->rq_res
.page_len
= w
= nfsacl_size(
264 (resp
->mask
& NFS_ACL
) ? resp
->acl_access
: NULL
,
265 (resp
->mask
& NFS_DFACL
) ? resp
->acl_default
: NULL
);
267 if (!*(rqstp
->rq_next_page
++))
272 if (!nfs_stream_encode_acl(xdr
, inode
, resp
->acl_access
,
273 resp
->mask
& NFS_ACL
, 0))
275 if (!nfs_stream_encode_acl(xdr
, inode
, resp
->acl_default
,
276 resp
->mask
& NFS_DFACL
, NFS_ACL_DEFAULT
))
283 static int nfsaclsvc_encode_accessres(struct svc_rqst
*rqstp
, __be32
*p
)
285 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
286 struct nfsd3_accessres
*resp
= rqstp
->rq_resp
;
288 if (!svcxdr_encode_stat(xdr
, resp
->status
))
290 switch (resp
->status
) {
292 if (!svcxdr_encode_fattr(rqstp
, xdr
, &resp
->fh
, &resp
->stat
))
294 if (xdr_stream_encode_u32(xdr
, resp
->access
) < 0)
303 * XDR release functions
305 static void nfsaclsvc_release_getacl(struct svc_rqst
*rqstp
)
307 struct nfsd3_getaclres
*resp
= rqstp
->rq_resp
;
310 posix_acl_release(resp
->acl_access
);
311 posix_acl_release(resp
->acl_default
);
314 static void nfsaclsvc_release_access(struct svc_rqst
*rqstp
)
316 struct nfsd3_accessres
*resp
= rqstp
->rq_resp
;
321 struct nfsd3_voidargs
{ int dummy
; };
323 #define ST 1 /* status*/
324 #define AT 21 /* attributes */
325 #define pAT (1+AT) /* post attributes - conditional */
326 #define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
328 static const struct svc_procedure nfsd_acl_procedures2
[5] = {
330 .pc_func
= nfsacld_proc_null
,
331 .pc_decode
= nfssvc_decode_voidarg
,
332 .pc_encode
= nfssvc_encode_voidres
,
333 .pc_argsize
= sizeof(struct nfsd_voidargs
),
334 .pc_ressize
= sizeof(struct nfsd_voidres
),
335 .pc_cachetype
= RC_NOCACHE
,
339 [ACLPROC2_GETACL
] = {
340 .pc_func
= nfsacld_proc_getacl
,
341 .pc_decode
= nfsaclsvc_decode_getaclargs
,
342 .pc_encode
= nfsaclsvc_encode_getaclres
,
343 .pc_release
= nfsaclsvc_release_getacl
,
344 .pc_argsize
= sizeof(struct nfsd3_getaclargs
),
345 .pc_ressize
= sizeof(struct nfsd3_getaclres
),
346 .pc_cachetype
= RC_NOCACHE
,
347 .pc_xdrressize
= ST
+1+2*(1+ACL
),
350 [ACLPROC2_SETACL
] = {
351 .pc_func
= nfsacld_proc_setacl
,
352 .pc_decode
= nfsaclsvc_decode_setaclargs
,
353 .pc_encode
= nfssvc_encode_attrstatres
,
354 .pc_release
= nfssvc_release_attrstat
,
355 .pc_argsize
= sizeof(struct nfsd3_setaclargs
),
356 .pc_ressize
= sizeof(struct nfsd_attrstat
),
357 .pc_cachetype
= RC_NOCACHE
,
358 .pc_xdrressize
= ST
+AT
,
361 [ACLPROC2_GETATTR
] = {
362 .pc_func
= nfsacld_proc_getattr
,
363 .pc_decode
= nfssvc_decode_fhandleargs
,
364 .pc_encode
= nfssvc_encode_attrstatres
,
365 .pc_release
= nfssvc_release_attrstat
,
366 .pc_argsize
= sizeof(struct nfsd_fhandle
),
367 .pc_ressize
= sizeof(struct nfsd_attrstat
),
368 .pc_cachetype
= RC_NOCACHE
,
369 .pc_xdrressize
= ST
+AT
,
370 .pc_name
= "GETATTR",
372 [ACLPROC2_ACCESS
] = {
373 .pc_func
= nfsacld_proc_access
,
374 .pc_decode
= nfsaclsvc_decode_accessargs
,
375 .pc_encode
= nfsaclsvc_encode_accessres
,
376 .pc_release
= nfsaclsvc_release_access
,
377 .pc_argsize
= sizeof(struct nfsd3_accessargs
),
378 .pc_ressize
= sizeof(struct nfsd3_accessres
),
379 .pc_cachetype
= RC_NOCACHE
,
380 .pc_xdrressize
= ST
+AT
+1,
381 .pc_name
= "SETATTR",
385 static unsigned int nfsd_acl_count2
[ARRAY_SIZE(nfsd_acl_procedures2
)];
386 const struct svc_version nfsd_acl_version2
= {
389 .vs_proc
= nfsd_acl_procedures2
,
390 .vs_count
= nfsd_acl_count2
,
391 .vs_dispatch
= nfsd_dispatch
,
392 .vs_xdrsize
= NFS3_SVC_XDRSIZE
,