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_inode_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_inode_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(&nop_mnt_idmap
, fh
->fh_dentry
, ACL_TYPE_ACCESS
,
120 error
= set_posix_acl(&nop_mnt_idmap
, fh
->fh_dentry
, 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
192 nfsaclsvc_decode_getaclargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
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)
205 nfsaclsvc_decode_setaclargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
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
))
226 nfsaclsvc_decode_accessargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
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
244 nfsaclsvc_encode_getaclres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
246 struct nfsd3_getaclres
*resp
= rqstp
->rq_resp
;
247 struct dentry
*dentry
= resp
->fh
.fh_dentry
;
250 if (!svcxdr_encode_stat(xdr
, resp
->status
))
253 if (dentry
== NULL
|| d_really_is_negative(dentry
))
255 inode
= d_inode(dentry
);
257 if (!svcxdr_encode_fattr(rqstp
, xdr
, &resp
->fh
, &resp
->stat
))
259 if (xdr_stream_encode_u32(xdr
, resp
->mask
) < 0)
262 if (!nfs_stream_encode_acl(xdr
, inode
, resp
->acl_access
,
263 resp
->mask
& NFS_ACL
, 0))
265 if (!nfs_stream_encode_acl(xdr
, inode
, resp
->acl_default
,
266 resp
->mask
& NFS_DFACL
, NFS_ACL_DEFAULT
))
274 nfsaclsvc_encode_accessres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
276 struct nfsd3_accessres
*resp
= rqstp
->rq_resp
;
278 if (!svcxdr_encode_stat(xdr
, resp
->status
))
280 switch (resp
->status
) {
282 if (!svcxdr_encode_fattr(rqstp
, xdr
, &resp
->fh
, &resp
->stat
))
284 if (xdr_stream_encode_u32(xdr
, resp
->access
) < 0)
293 * XDR release functions
295 static void nfsaclsvc_release_getacl(struct svc_rqst
*rqstp
)
297 struct nfsd3_getaclres
*resp
= rqstp
->rq_resp
;
300 posix_acl_release(resp
->acl_access
);
301 posix_acl_release(resp
->acl_default
);
304 static void nfsaclsvc_release_access(struct svc_rqst
*rqstp
)
306 struct nfsd3_accessres
*resp
= rqstp
->rq_resp
;
311 #define ST 1 /* status*/
312 #define AT 21 /* attributes */
313 #define pAT (1+AT) /* post attributes - conditional */
314 #define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
316 static const struct svc_procedure nfsd_acl_procedures2
[5] = {
318 .pc_func
= nfsacld_proc_null
,
319 .pc_decode
= nfssvc_decode_voidarg
,
320 .pc_encode
= nfssvc_encode_voidres
,
321 .pc_argsize
= sizeof(struct nfsd_voidargs
),
322 .pc_argzero
= sizeof(struct nfsd_voidargs
),
323 .pc_ressize
= sizeof(struct nfsd_voidres
),
324 .pc_cachetype
= RC_NOCACHE
,
328 [ACLPROC2_GETACL
] = {
329 .pc_func
= nfsacld_proc_getacl
,
330 .pc_decode
= nfsaclsvc_decode_getaclargs
,
331 .pc_encode
= nfsaclsvc_encode_getaclres
,
332 .pc_release
= nfsaclsvc_release_getacl
,
333 .pc_argsize
= sizeof(struct nfsd3_getaclargs
),
334 .pc_argzero
= sizeof(struct nfsd3_getaclargs
),
335 .pc_ressize
= sizeof(struct nfsd3_getaclres
),
336 .pc_cachetype
= RC_NOCACHE
,
337 .pc_xdrressize
= ST
+1+2*(1+ACL
),
340 [ACLPROC2_SETACL
] = {
341 .pc_func
= nfsacld_proc_setacl
,
342 .pc_decode
= nfsaclsvc_decode_setaclargs
,
343 .pc_encode
= nfssvc_encode_attrstatres
,
344 .pc_release
= nfssvc_release_attrstat
,
345 .pc_argsize
= sizeof(struct nfsd3_setaclargs
),
346 .pc_argzero
= sizeof(struct nfsd3_setaclargs
),
347 .pc_ressize
= sizeof(struct nfsd_attrstat
),
348 .pc_cachetype
= RC_NOCACHE
,
349 .pc_xdrressize
= ST
+AT
,
352 [ACLPROC2_GETATTR
] = {
353 .pc_func
= nfsacld_proc_getattr
,
354 .pc_decode
= nfssvc_decode_fhandleargs
,
355 .pc_encode
= nfssvc_encode_attrstatres
,
356 .pc_release
= nfssvc_release_attrstat
,
357 .pc_argsize
= sizeof(struct nfsd_fhandle
),
358 .pc_argzero
= sizeof(struct nfsd_fhandle
),
359 .pc_ressize
= sizeof(struct nfsd_attrstat
),
360 .pc_cachetype
= RC_NOCACHE
,
361 .pc_xdrressize
= ST
+AT
,
362 .pc_name
= "GETATTR",
364 [ACLPROC2_ACCESS
] = {
365 .pc_func
= nfsacld_proc_access
,
366 .pc_decode
= nfsaclsvc_decode_accessargs
,
367 .pc_encode
= nfsaclsvc_encode_accessres
,
368 .pc_release
= nfsaclsvc_release_access
,
369 .pc_argsize
= sizeof(struct nfsd3_accessargs
),
370 .pc_argzero
= sizeof(struct nfsd3_accessargs
),
371 .pc_ressize
= sizeof(struct nfsd3_accessres
),
372 .pc_cachetype
= RC_NOCACHE
,
373 .pc_xdrressize
= ST
+AT
+1,
374 .pc_name
= "SETATTR",
378 static DEFINE_PER_CPU_ALIGNED(unsigned long,
379 nfsd_acl_count2
[ARRAY_SIZE(nfsd_acl_procedures2
)]);
380 const struct svc_version nfsd_acl_version2
= {
382 .vs_nproc
= ARRAY_SIZE(nfsd_acl_procedures2
),
383 .vs_proc
= nfsd_acl_procedures2
,
384 .vs_count
= nfsd_acl_count2
,
385 .vs_dispatch
= nfsd_dispatch
,
386 .vs_xdrsize
= NFS3_SVC_XDRSIZE
,