4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/systm.h>
36 #include <sys/vnode.h>
37 #include <sys/pathname.h>
41 #include <sys/errno.h>
42 #include <sys/socket.h>
43 #include <sys/sysmacros.h>
44 #include <sys/siginfo.h>
45 #include <sys/tiuser.h>
46 #include <sys/statvfs.h>
47 #include <sys/t_kuser.h>
49 #include <sys/kstat.h>
51 #include <sys/dirent.h>
52 #include <sys/cmn_err.h>
53 #include <sys/debug.h>
54 #include <sys/unistd.h>
55 #include <sys/vtrace.h>
58 #include <rpc/types.h>
64 #include <nfs/export.h>
65 #include <nfs/nfssys.h>
66 #include <nfs/nfs_clnt.h>
67 #include <nfs/nfs_acl.h>
69 #include <sys/fs_subr.h>
72 * These are the interface routines for the server side of the
73 * NFS ACL server. See the NFS ACL protocol specification
74 * for a description of this interface.
79 acl2_getacl(GETACL2args
*args
, GETACL2res
*resp
, struct exportinfo
*exi
,
80 struct svc_req
*req
, cred_t
*cr
, bool_t ro
)
86 vp
= nfs_fhtovp(&args
->fh
, exi
);
88 resp
->status
= NFSERR_STALE
;
92 bzero((caddr_t
)&resp
->resok
.acl
, sizeof (resp
->resok
.acl
));
94 resp
->resok
.acl
.vsa_mask
= args
->mask
;
96 error
= fop_getsecattr(vp
, &resp
->resok
.acl
, 0, cr
, NULL
);
98 if ((error
== ENOSYS
) && !(exi
->exi_export
.ex_flags
& EX_NOACLFAB
)) {
100 * If the underlying file system doesn't support
101 * aclent_t type acls, fabricate an acl. This is
102 * required in order to to support existing clients
103 * that require the call to fop_getsecattr to
104 * succeed while making the assumption that all
105 * file systems support aclent_t type acls. This
106 * causes problems for servers exporting ZFS file
107 * systems because ZFS supports ace_t type acls,
108 * and fails (with ENOSYS) when asked for aclent_t
111 * Note: if the fs_fab_acl() fails, we have other problems.
112 * This error should be returned to the caller.
114 error
= fs_fab_acl(vp
, &resp
->resok
.acl
, 0, cr
, NULL
);
119 resp
->status
= puterrno(error
);
123 va
.va_mask
= VATTR_ALL
;
124 error
= rfs4_delegated_getattr(vp
, &va
, 0, cr
);
128 /* check for overflowed values */
130 error
= vattr_to_nattr(&va
, &resp
->resok
.attr
);
133 resp
->status
= puterrno(error
);
134 if (resp
->resok
.acl
.vsa_aclcnt
> 0 &&
135 resp
->resok
.acl
.vsa_aclentp
!= NULL
) {
136 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_aclentp
,
137 resp
->resok
.acl
.vsa_aclcnt
* sizeof (aclent_t
));
139 if (resp
->resok
.acl
.vsa_dfaclcnt
> 0 &&
140 resp
->resok
.acl
.vsa_dfaclentp
!= NULL
) {
141 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_dfaclentp
,
142 resp
->resok
.acl
.vsa_dfaclcnt
* sizeof (aclent_t
));
147 resp
->status
= NFS_OK
;
148 if (!(args
->mask
& NA_ACL
)) {
149 if (resp
->resok
.acl
.vsa_aclcnt
> 0 &&
150 resp
->resok
.acl
.vsa_aclentp
!= NULL
) {
151 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_aclentp
,
152 resp
->resok
.acl
.vsa_aclcnt
* sizeof (aclent_t
));
154 resp
->resok
.acl
.vsa_aclentp
= NULL
;
156 if (!(args
->mask
& NA_DFACL
)) {
157 if (resp
->resok
.acl
.vsa_dfaclcnt
> 0 &&
158 resp
->resok
.acl
.vsa_dfaclentp
!= NULL
) {
159 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_dfaclentp
,
160 resp
->resok
.acl
.vsa_dfaclcnt
* sizeof (aclent_t
));
162 resp
->resok
.acl
.vsa_dfaclentp
= NULL
;
167 acl2_getacl_getfh(GETACL2args
*args
)
174 acl2_getacl_free(GETACL2res
*resp
)
177 if (resp
->status
== NFS_OK
) {
178 if (resp
->resok
.acl
.vsa_aclcnt
> 0 &&
179 resp
->resok
.acl
.vsa_aclentp
!= NULL
) {
180 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_aclentp
,
181 resp
->resok
.acl
.vsa_aclcnt
* sizeof (aclent_t
));
183 if (resp
->resok
.acl
.vsa_dfaclcnt
> 0 &&
184 resp
->resok
.acl
.vsa_dfaclentp
!= NULL
) {
185 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_dfaclentp
,
186 resp
->resok
.acl
.vsa_dfaclcnt
* sizeof (aclent_t
));
193 acl2_setacl(SETACL2args
*args
, SETACL2res
*resp
, struct exportinfo
*exi
,
194 struct svc_req
*req
, cred_t
*cr
, bool_t ro
)
200 vp
= nfs_fhtovp(&args
->fh
, exi
);
202 resp
->status
= NFSERR_STALE
;
206 if (rdonly(ro
, vp
)) {
208 resp
->status
= NFSERR_ROFS
;
212 (void) fop_rwlock(vp
, V_WRITELOCK_TRUE
, NULL
);
213 error
= fop_setsecattr(vp
, &args
->acl
, 0, cr
, NULL
);
215 fop_rwunlock(vp
, V_WRITELOCK_TRUE
, NULL
);
217 resp
->status
= puterrno(error
);
221 va
.va_mask
= VATTR_ALL
;
222 error
= rfs4_delegated_getattr(vp
, &va
, 0, cr
);
224 fop_rwunlock(vp
, V_WRITELOCK_TRUE
, NULL
);
227 /* check for overflowed values */
229 error
= vattr_to_nattr(&va
, &resp
->resok
.attr
);
232 resp
->status
= puterrno(error
);
236 resp
->status
= NFS_OK
;
240 acl2_setacl_getfh(SETACL2args
*args
)
248 acl2_getattr(GETATTR2args
*args
, GETATTR2res
*resp
, struct exportinfo
*exi
,
249 struct svc_req
*req
, cred_t
*cr
, bool_t ro
)
255 vp
= nfs_fhtovp(&args
->fh
, exi
);
257 resp
->status
= NFSERR_STALE
;
261 va
.va_mask
= VATTR_ALL
;
262 error
= rfs4_delegated_getattr(vp
, &va
, 0, cr
);
266 /* check for overflowed values */
268 error
= vattr_to_nattr(&va
, &resp
->resok
.attr
);
271 resp
->status
= puterrno(error
);
275 resp
->status
= NFS_OK
;
279 acl2_getattr_getfh(GETATTR2args
*args
)
287 acl2_access(ACCESS2args
*args
, ACCESS2res
*resp
, struct exportinfo
*exi
,
288 struct svc_req
*req
, cred_t
*cr
, bool_t ro
)
295 vp
= nfs_fhtovp(&args
->fh
, exi
);
297 resp
->status
= NFSERR_STALE
;
302 * If the file system is exported read only, it is not appropriate
303 * to check write permissions for regular files and directories.
304 * Special files are interpreted by the client, so the underlying
305 * permissions are sent back to the client for interpretation.
307 if (rdonly(ro
, vp
) && (vp
->v_type
== VREG
|| vp
->v_type
== VDIR
))
313 * We need the mode so that we can correctly determine access
314 * permissions relative to a mandatory lock file. Access to
315 * mandatory lock files is denied on the server, so it might
316 * as well be reflected to the server during the open.
318 va
.va_mask
= VATTR_MODE
;
319 error
= fop_getattr(vp
, &va
, 0, cr
, NULL
);
322 resp
->status
= puterrno(error
);
326 resp
->resok
.access
= 0;
328 if (args
->access
& ACCESS2_READ
) {
329 error
= fop_access(vp
, VREAD
, 0, cr
, NULL
);
330 if (!error
&& !MANDLOCK(vp
, va
.va_mode
))
331 resp
->resok
.access
|= ACCESS2_READ
;
333 if ((args
->access
& ACCESS2_LOOKUP
) && vp
->v_type
== VDIR
) {
334 error
= fop_access(vp
, VEXEC
, 0, cr
, NULL
);
336 resp
->resok
.access
|= ACCESS2_LOOKUP
;
338 if (checkwriteperm
&&
339 (args
->access
& (ACCESS2_MODIFY
|ACCESS2_EXTEND
))) {
340 error
= fop_access(vp
, VWRITE
, 0, cr
, NULL
);
341 if (!error
&& !MANDLOCK(vp
, va
.va_mode
))
342 resp
->resok
.access
|=
343 (args
->access
& (ACCESS2_MODIFY
|ACCESS2_EXTEND
));
345 if (checkwriteperm
&&
346 (args
->access
& ACCESS2_DELETE
) && (vp
->v_type
== VDIR
)) {
347 error
= fop_access(vp
, VWRITE
, 0, cr
, NULL
);
349 resp
->resok
.access
|= ACCESS2_DELETE
;
351 if (args
->access
& ACCESS2_EXECUTE
) {
352 error
= fop_access(vp
, VEXEC
, 0, cr
, NULL
);
353 if (!error
&& !MANDLOCK(vp
, va
.va_mode
))
354 resp
->resok
.access
|= ACCESS2_EXECUTE
;
357 va
.va_mask
= VATTR_ALL
;
358 error
= rfs4_delegated_getattr(vp
, &va
, 0, cr
);
362 /* check for overflowed values */
364 error
= vattr_to_nattr(&va
, &resp
->resok
.attr
);
367 resp
->status
= puterrno(error
);
371 resp
->status
= NFS_OK
;
375 acl2_access_getfh(ACCESS2args
*args
)
383 acl2_getxattrdir(GETXATTRDIR2args
*args
, GETXATTRDIR2res
*resp
,
384 struct exportinfo
*exi
, struct svc_req
*req
, cred_t
*cr
, bool_t ro
)
390 vp
= nfs_fhtovp(&args
->fh
, exi
);
392 resp
->status
= NFSERR_STALE
;
396 flags
= LOOKUP_XATTR
;
398 flags
|= CREATE_XATTR_DIR
;
401 error
= fop_pathconf(vp
, _PC_SATTR_EXISTS
, &val
, cr
, NULL
);
402 if (!error
&& val
== 0) {
403 error
= fop_pathconf(vp
, _PC_XATTR_EXISTS
,
405 if (!error
&& val
== 0) {
407 resp
->status
= NFSERR_NOENT
;
413 error
= fop_lookup(vp
, "", &avp
, NULL
, flags
, NULL
, cr
,
415 if (!error
&& avp
== vp
) { /* lookup of "" on old FS? */
421 va
.va_mask
= VATTR_ALL
;
422 error
= rfs4_delegated_getattr(avp
, &va
, 0, cr
);
424 error
= vattr_to_nattr(&va
, &resp
->resok
.attr
);
426 error
= makefh(&resp
->resok
.fh
, avp
, exi
);
434 resp
->status
= puterrno(error
);
437 resp
->status
= NFS_OK
;
441 acl2_getxattrdir_getfh(GETXATTRDIR2args
*args
)
448 acl3_getacl(GETACL3args
*args
, GETACL3res
*resp
, struct exportinfo
*exi
,
449 struct svc_req
*req
, cred_t
*cr
, bool_t ro
)
458 vp
= nfs3_fhtovp(&args
->fh
, exi
);
464 va
.va_mask
= VATTR_ALL
;
465 vap
= rfs4_delegated_getattr(vp
, &va
, 0, cr
) ? NULL
: &va
;
467 bzero((caddr_t
)&resp
->resok
.acl
, sizeof (resp
->resok
.acl
));
469 resp
->resok
.acl
.vsa_mask
= args
->mask
;
471 error
= fop_getsecattr(vp
, &resp
->resok
.acl
, 0, cr
, NULL
);
473 if ((error
== ENOSYS
) && !(exi
->exi_export
.ex_flags
& EX_NOACLFAB
)) {
475 * If the underlying file system doesn't support
476 * aclent_t type acls, fabricate an acl. This is
477 * required in order to to support existing clients
478 * that require the call to fop_getsecattr to
479 * succeed while making the assumption that all
480 * file systems support aclent_t type acls. This
481 * causes problems for servers exporting ZFS file
482 * systems because ZFS supports ace_t type acls,
483 * and fails (with ENOSYS) when asked for aclent_t
486 * Note: if the fs_fab_acl() fails, we have other problems.
487 * This error should be returned to the caller.
489 error
= fs_fab_acl(vp
, &resp
->resok
.acl
, 0, cr
, NULL
);
495 va
.va_mask
= VATTR_ALL
;
496 vap
= rfs4_delegated_getattr(vp
, &va
, 0, cr
) ? NULL
: &va
;
500 resp
->status
= NFS3_OK
;
501 vattr_to_post_op_attr(vap
, &resp
->resok
.attr
);
502 if (!(args
->mask
& NA_ACL
)) {
503 if (resp
->resok
.acl
.vsa_aclcnt
> 0 &&
504 resp
->resok
.acl
.vsa_aclentp
!= NULL
) {
505 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_aclentp
,
506 resp
->resok
.acl
.vsa_aclcnt
* sizeof (aclent_t
));
508 resp
->resok
.acl
.vsa_aclentp
= NULL
;
510 if (!(args
->mask
& NA_DFACL
)) {
511 if (resp
->resok
.acl
.vsa_dfaclcnt
> 0 &&
512 resp
->resok
.acl
.vsa_dfaclentp
!= NULL
) {
513 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_dfaclentp
,
514 resp
->resok
.acl
.vsa_dfaclcnt
* sizeof (aclent_t
));
516 resp
->resok
.acl
.vsa_dfaclentp
= NULL
;
521 if (curthread
->t_flag
& T_WOULDBLOCK
) {
522 curthread
->t_flag
&= ~T_WOULDBLOCK
;
523 resp
->status
= NFS3ERR_JUKEBOX
;
525 resp
->status
= puterrno3(error
);
529 vattr_to_post_op_attr(vap
, &resp
->resfail
.attr
);
533 acl3_getacl_getfh(GETACL3args
*args
)
540 acl3_getacl_free(GETACL3res
*resp
)
543 if (resp
->status
== NFS3_OK
) {
544 if (resp
->resok
.acl
.vsa_aclcnt
> 0 &&
545 resp
->resok
.acl
.vsa_aclentp
!= NULL
) {
546 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_aclentp
,
547 resp
->resok
.acl
.vsa_aclcnt
* sizeof (aclent_t
));
549 if (resp
->resok
.acl
.vsa_dfaclcnt
> 0 &&
550 resp
->resok
.acl
.vsa_dfaclentp
!= NULL
) {
551 kmem_free((caddr_t
)resp
->resok
.acl
.vsa_dfaclentp
,
552 resp
->resok
.acl
.vsa_dfaclcnt
* sizeof (aclent_t
));
559 acl3_setacl(SETACL3args
*args
, SETACL3res
*resp
, struct exportinfo
*exi
,
560 struct svc_req
*req
, cred_t
*cr
, bool_t ro
)
569 vp
= nfs3_fhtovp(&args
->fh
, exi
);
575 (void) fop_rwlock(vp
, V_WRITELOCK_TRUE
, NULL
);
577 va
.va_mask
= VATTR_ALL
;
578 vap
= rfs4_delegated_getattr(vp
, &va
, 0, cr
) ? NULL
: &va
;
580 if (rdonly(ro
, vp
)) {
581 resp
->status
= NFS3ERR_ROFS
;
585 error
= fop_setsecattr(vp
, &args
->acl
, 0, cr
, NULL
);
587 va
.va_mask
= VATTR_ALL
;
588 vap
= rfs4_delegated_getattr(vp
, &va
, 0, cr
) ? NULL
: &va
;
593 fop_rwunlock(vp
, V_WRITELOCK_TRUE
, NULL
);
596 resp
->status
= NFS3_OK
;
597 vattr_to_post_op_attr(vap
, &resp
->resok
.attr
);
601 if (curthread
->t_flag
& T_WOULDBLOCK
) {
602 curthread
->t_flag
&= ~T_WOULDBLOCK
;
603 resp
->status
= NFS3ERR_JUKEBOX
;
605 resp
->status
= puterrno3(error
);
608 fop_rwunlock(vp
, V_WRITELOCK_TRUE
, NULL
);
611 vattr_to_post_op_attr(vap
, &resp
->resfail
.attr
);
615 acl3_setacl_getfh(SETACL3args
*args
)
623 acl3_getxattrdir(GETXATTRDIR3args
*args
, GETXATTRDIR3res
*resp
,
624 struct exportinfo
*exi
, struct svc_req
*req
, cred_t
*cr
, bool_t ro
)
630 vp
= nfs3_fhtovp(&args
->fh
, exi
);
632 resp
->status
= NFS3ERR_STALE
;
636 flags
= LOOKUP_XATTR
;
638 flags
|= CREATE_XATTR_DIR
;
642 error
= fop_pathconf(vp
, _PC_SATTR_EXISTS
, &val
, cr
, NULL
);
643 if (!error
&& val
== 0) {
644 error
= fop_pathconf(vp
, _PC_XATTR_EXISTS
,
646 if (!error
&& val
== 0) {
648 resp
->status
= NFS3ERR_NOENT
;
654 error
= fop_lookup(vp
, "", &avp
, NULL
, flags
, NULL
, cr
,
656 if (!error
&& avp
== vp
) { /* lookup of "" on old FS? */
662 va
.va_mask
= VATTR_ALL
;
663 error
= rfs4_delegated_getattr(avp
, &va
, 0, cr
);
665 vattr_to_post_op_attr(&va
, &resp
->resok
.attr
);
666 error
= makefh3(&resp
->resok
.fh
, avp
, exi
);
674 resp
->status
= puterrno3(error
);
677 resp
->status
= NFS3_OK
;
681 acl3_getxattrdir_getfh(GETXATTRDIR3args
*args
)