1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1999-2003 Robert N. M. Watson 5 * All rights reserved. 6 * 7 * This software was developed by Robert Watson for the TrustedBSD Project. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * Support for POSIX.1e access control lists: UFS-specific support functions. 33 */ 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #include "opt_ufs.h" 39 #include "opt_quota.h" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/stat.h> 44 #include <sys/mount.h> 45 #include <sys/vnode.h> 46 #include <sys/types.h> 47 #include <sys/acl.h> 48 #include <sys/event.h> 49 #include <sys/extattr.h> 50 #include <sys/proc.h> 51 52 #include <ufs/ufs/quota.h> 53 #include <ufs/ufs/inode.h> 54 #include <ufs/ufs/acl.h> 55 #include <ufs/ufs/extattr.h> 56 #include <ufs/ufs/dir.h> 57 #include <ufs/ufs/ufsmount.h> 58 #include <ufs/ufs/ufs_extern.h> 59 #include <ufs/ffs/fs.h> 60 61 #ifdef UFS_ACL 62 63 FEATURE(ufs_acl, "ACL support for UFS"); 64 65 /* 66 * Synchronize an ACL and an inode by copying over appropriate inode fields 67 * to the passed ACL. Assumes an ACL that would satisfy acl_posix1e_check(), 68 * and may panic if not. 69 */ 70 void 71 ufs_sync_acl_from_inode(struct inode *ip, struct acl *acl) 72 { 73 struct acl_entry *acl_mask, *acl_group_obj; 74 int i; 75 76 /* 77 * Update ACL_USER_OBJ, ACL_OTHER, but simply identify ACL_MASK 78 * and ACL_GROUP_OBJ for use after we know whether ACL_MASK is 79 * present. 80 */ 81 acl_mask = NULL; 82 acl_group_obj = NULL; 83 for (i = 0; i < acl->acl_cnt; i++) { 84 switch (acl->acl_entry[i].ae_tag) { 85 case ACL_USER_OBJ: 86 acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm( 87 ACL_USER_OBJ, ip->i_mode); 88 acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; 89 break; 90 91 case ACL_GROUP_OBJ: 92 acl_group_obj = &acl->acl_entry[i]; 93 acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; 94 break; 95 96 case ACL_OTHER: 97 acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm( 98 ACL_OTHER, ip->i_mode); 99 acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; 100 break; 101 102 case ACL_MASK: 103 acl_mask = &acl->acl_entry[i]; 104 acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; 105 break; 106 107 case ACL_USER: 108 case ACL_GROUP: 109 break; 110 111 default: 112 panic("ufs_sync_acl_from_inode(): bad ae_tag"); 113 } 114 } 115 116 if (acl_group_obj == NULL) 117 panic("ufs_sync_acl_from_inode(): no ACL_GROUP_OBJ"); 118 119 if (acl_mask == NULL) { 120 /* 121 * There is no ACL_MASK, so update ACL_GROUP_OBJ. 122 */ 123 acl_group_obj->ae_perm = acl_posix1e_mode_to_perm( 124 ACL_GROUP_OBJ, ip->i_mode); 125 } else { 126 /* 127 * Update the ACL_MASK entry instead of ACL_GROUP_OBJ. 128 */ 129 acl_mask->ae_perm = acl_posix1e_mode_to_perm(ACL_GROUP_OBJ, 130 ip->i_mode); 131 } 132 } 133 134 /* 135 * Calculate what the inode mode should look like based on an authoritative 136 * ACL for the inode. Replace only the fields in the inode that the ACL 137 * can represent. 138 */ 139 void 140 ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip) 141 { 142 int newmode; 143 144 newmode = ip->i_mode & ACL_PRESERVE_MASK; 145 newmode |= acl_posix1e_acl_to_mode(acl); 146 UFS_INODE_SET_MODE(ip, newmode); 147 DIP_SET(ip, i_mode, ip->i_mode); 148 } 149 150 /* 151 * Retrieve NFSv4 ACL, skipping access checks. Must be used in UFS code 152 * instead of VOP_GETACL() when we don't want to be restricted by the user 153 * not having ACL_READ_ACL permission, e.g. when calculating inherited ACL 154 * or in ufs_vnops.c:ufs_accessx(). 155 */ 156 int 157 ufs_getacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct thread *td) 158 { 159 int error, len; 160 struct inode *ip = VTOI(vp); 161 162 len = sizeof(*aclp); 163 bzero(aclp, len); 164 165 error = vn_extattr_get(vp, IO_NODELOCKED, 166 NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME, 167 &len, (char *) aclp, td); 168 aclp->acl_maxcnt = ACL_MAX_ENTRIES; 169 if (error == ENOATTR) { 170 /* 171 * Legitimately no ACL set on object, purely 172 * emulate it through the inode. 173 */ 174 acl_nfs4_sync_acl_from_mode(aclp, ip->i_mode, ip->i_uid); 175 176 return (0); 177 } 178 179 if (error) 180 return (error); 181 182 if (len != sizeof(*aclp)) { 183 /* 184 * A short (or long) read, meaning that for 185 * some reason the ACL is corrupted. Return 186 * EPERM since the object DAC protections 187 * are unsafe. 188 */ 189 printf("ufs_getacl_nfs4(): Loaded invalid ACL (" 190 "%d bytes), inumber %ju on %s\n", len, 191 (uintmax_t)ip->i_number, ITOFS(ip)->fs_fsmnt); 192 193 return (EPERM); 194 } 195 196 error = acl_nfs4_check(aclp, vp->v_type == VDIR); 197 if (error) { 198 printf("ufs_getacl_nfs4(): Loaded invalid ACL " 199 "(failed acl_nfs4_check), inumber %ju on %s\n", 200 (uintmax_t)ip->i_number, ITOFS(ip)->fs_fsmnt); 201 202 return (EPERM); 203 } 204 205 return (0); 206 } 207 208 static int 209 ufs_getacl_nfs4(struct vop_getacl_args *ap) 210 { 211 int error; 212 213 if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0) 214 return (EINVAL); 215 216 error = VOP_ACCESSX(ap->a_vp, VREAD_ACL, ap->a_td->td_ucred, ap->a_td); 217 if (error) 218 return (error); 219 220 error = ufs_getacl_nfs4_internal(ap->a_vp, ap->a_aclp, ap->a_td); 221 222 return (error); 223 } 224 225 /* 226 * Read POSIX.1e ACL from an EA. Return error if its not found 227 * or if any other error has occurred. 228 */ 229 static int 230 ufs_get_oldacl(acl_type_t type, struct oldacl *old, struct vnode *vp, 231 struct thread *td) 232 { 233 int error, len; 234 struct inode *ip = VTOI(vp); 235 236 len = sizeof(*old); 237 238 switch (type) { 239 case ACL_TYPE_ACCESS: 240 error = vn_extattr_get(vp, IO_NODELOCKED, 241 POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE, 242 POSIX1E_ACL_ACCESS_EXTATTR_NAME, &len, (char *) old, 243 td); 244 break; 245 case ACL_TYPE_DEFAULT: 246 if (vp->v_type != VDIR) 247 return (EINVAL); 248 error = vn_extattr_get(vp, IO_NODELOCKED, 249 POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE, 250 POSIX1E_ACL_DEFAULT_EXTATTR_NAME, &len, (char *) old, 251 td); 252 break; 253 default: 254 return (EINVAL); 255 } 256 257 if (error != 0) 258 return (error); 259 260 if (len != sizeof(*old)) { 261 /* 262 * A short (or long) read, meaning that for some reason 263 * the ACL is corrupted. Return EPERM since the object 264 * DAC protections are unsafe. 265 */ 266 printf("ufs_get_oldacl(): Loaded invalid ACL " 267 "(len = %d), inumber %ju on %s\n", len, 268 (uintmax_t)ip->i_number, ITOFS(ip)->fs_fsmnt); 269 return (EPERM); 270 } 271 272 return (0); 273 } 274 275 /* 276 * Retrieve the ACL on a file. 277 * 278 * As part of the ACL is stored in the inode, and the rest in an EA, 279 * assemble both into a final ACL product. Right now this is not done 280 * very efficiently. 281 */ 282 static int 283 ufs_getacl_posix1e(struct vop_getacl_args *ap) 284 { 285 struct inode *ip = VTOI(ap->a_vp); 286 int error; 287 struct oldacl *old; 288 289 /* 290 * XXX: If ufs_getacl() should work on file systems not supporting 291 * ACLs, remove this check. 292 */ 293 if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) 294 return (EINVAL); 295 296 old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO); 297 298 /* 299 * Attempt to retrieve the ACL from the extended attributes. 300 */ 301 error = ufs_get_oldacl(ap->a_type, old, ap->a_vp, ap->a_td); 302 switch (error) { 303 /* 304 * XXX: If ufs_getacl() should work on filesystems 305 * without the EA configured, add case EOPNOTSUPP here. 306 */ 307 case ENOATTR: 308 switch (ap->a_type) { 309 case ACL_TYPE_ACCESS: 310 /* 311 * Legitimately no ACL set on object, purely 312 * emulate it through the inode. These fields will 313 * be updated when the ACL is synchronized with 314 * the inode later. 315 */ 316 old->acl_cnt = 3; 317 old->acl_entry[0].ae_tag = ACL_USER_OBJ; 318 old->acl_entry[0].ae_id = ACL_UNDEFINED_ID; 319 old->acl_entry[0].ae_perm = ACL_PERM_NONE; 320 old->acl_entry[1].ae_tag = ACL_GROUP_OBJ; 321 old->acl_entry[1].ae_id = ACL_UNDEFINED_ID; 322 old->acl_entry[1].ae_perm = ACL_PERM_NONE; 323 old->acl_entry[2].ae_tag = ACL_OTHER; 324 old->acl_entry[2].ae_id = ACL_UNDEFINED_ID; 325 old->acl_entry[2].ae_perm = ACL_PERM_NONE; 326 break; 327 328 case ACL_TYPE_DEFAULT: 329 /* 330 * Unlike ACL_TYPE_ACCESS, there is no relationship 331 * between the inode contents and the ACL, and it is 332 * therefore possible for the request for the ACL 333 * to fail since the ACL is undefined. In this 334 * situation, return success and an empty ACL, 335 * as required by POSIX.1e. 336 */ 337 old->acl_cnt = 0; 338 break; 339 } 340 /* FALLTHROUGH */ 341 case 0: 342 error = acl_copy_oldacl_into_acl(old, ap->a_aclp); 343 if (error != 0) 344 break; 345 346 if (ap->a_type == ACL_TYPE_ACCESS) 347 ufs_sync_acl_from_inode(ip, ap->a_aclp); 348 default: 349 break; 350 } 351 352 free(old, M_ACL); 353 return (error); 354 } 355 356 int 357 ufs_getacl(ap) 358 struct vop_getacl_args /* { 359 struct vnode *vp; 360 acl_type_t type; 361 struct acl *aclp; 362 struct ucred *cred; 363 struct thread *td; 364 } */ *ap; 365 { 366 367 if ((ap->a_vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS)) == 0) 368 return (EOPNOTSUPP); 369 370 if (ap->a_type == ACL_TYPE_NFS4) 371 return (ufs_getacl_nfs4(ap)); 372 373 return (ufs_getacl_posix1e(ap)); 374 } 375 376 /* 377 * Set NFSv4 ACL without doing any access checking. This is required 378 * e.g. by the UFS code that implements ACL inheritance, or from 379 * ufs_vnops.c:ufs_chmod(), as some of the checks have to be skipped 380 * in that case, and others are redundant. 381 */ 382 int 383 ufs_setacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct thread *td) 384 { 385 int error; 386 mode_t mode, newmode; 387 struct inode *ip = VTOI(vp); 388 389 KASSERT(acl_nfs4_check(aclp, vp->v_type == VDIR) == 0, 390 ("invalid ACL passed to ufs_setacl_nfs4_internal")); 391 392 if (acl_nfs4_is_trivial(aclp, ip->i_uid)) { 393 error = vn_extattr_rm(vp, IO_NODELOCKED, 394 NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME, td); 395 396 /* 397 * An attempt to remove ACL from a file that didn't have 398 * any extended entries is not an error. 399 */ 400 if (error == ENOATTR) 401 error = 0; 402 403 } else { 404 error = vn_extattr_set(vp, IO_NODELOCKED, 405 NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME, 406 sizeof(*aclp), (char *) aclp, td); 407 } 408 409 /* 410 * Map lack of attribute definition in UFS_EXTATTR into lack of 411 * support for ACLs on the filesystem. 412 */ 413 if (error == ENOATTR) 414 return (EOPNOTSUPP); 415 416 if (error) 417 return (error); 418 419 mode = ip->i_mode; 420 421 acl_nfs4_sync_mode_from_acl(&mode, aclp); 422 423 newmode = ip->i_mode & ACL_PRESERVE_MASK; 424 newmode |= mode; 425 UFS_INODE_SET_MODE(ip, newmode); 426 DIP_SET(ip, i_mode, ip->i_mode); 427 UFS_INODE_SET_FLAG(ip, IN_CHANGE); 428 429 VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); 430 431 error = UFS_UPDATE(vp, 0); 432 return (error); 433 } 434 435 static int 436 ufs_setacl_nfs4(struct vop_setacl_args *ap) 437 { 438 int error; 439 struct inode *ip = VTOI(ap->a_vp); 440 441 if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0) 442 return (EINVAL); 443 444 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 445 return (EROFS); 446 447 if (ap->a_aclp == NULL) 448 return (EINVAL); 449 450 error = VOP_ACLCHECK(ap->a_vp, ap->a_type, ap->a_aclp, ap->a_cred, 451 ap->a_td); 452 if (error) 453 return (error); 454 455 /* 456 * Authorize the ACL operation. 457 */ 458 if (ip->i_flags & (IMMUTABLE | APPEND)) 459 return (EPERM); 460 461 /* 462 * Must hold VWRITE_ACL or have appropriate privilege. 463 */ 464 if ((error = VOP_ACCESSX(ap->a_vp, VWRITE_ACL, ap->a_cred, ap->a_td))) 465 return (error); 466 467 /* 468 * With NFSv4 ACLs, chmod(2) may need to add additional entries. 469 * Make sure it has enough room for that - splitting every entry 470 * into two and appending "canonical six" entries at the end. 471 */ 472 if (ap->a_aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2) 473 return (ENOSPC); 474 475 error = ufs_setacl_nfs4_internal(ap->a_vp, ap->a_aclp, ap->a_td); 476 477 return (error); 478 } 479 480 /* 481 * Set the ACL on a file. 482 * 483 * As part of the ACL is stored in the inode, and the rest in an EA, 484 * this is necessarily non-atomic, and has complex authorization. 485 * As ufs_setacl() includes elements of ufs_chown() and ufs_chmod(), 486 * a fair number of different access checks may be required to go ahead 487 * with the operation at all. 488 */ 489 static int 490 ufs_setacl_posix1e(struct vop_setacl_args *ap) 491 { 492 struct inode *ip = VTOI(ap->a_vp); 493 int error; 494 struct oldacl *old; 495 496 if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) 497 return (EINVAL); 498 499 /* 500 * If this is a set operation rather than a delete operation, 501 * invoke VOP_ACLCHECK() on the passed ACL to determine if it is 502 * valid for the target. This will include a check on ap->a_type. 503 */ 504 if (ap->a_aclp != NULL) { 505 /* 506 * Set operation. 507 */ 508 error = VOP_ACLCHECK(ap->a_vp, ap->a_type, ap->a_aclp, 509 ap->a_cred, ap->a_td); 510 if (error != 0) 511 return (error); 512 } else { 513 /* 514 * Delete operation. 515 * POSIX.1e allows only deletion of the default ACL on a 516 * directory (ACL_TYPE_DEFAULT). 517 */ 518 if (ap->a_type != ACL_TYPE_DEFAULT) 519 return (EINVAL); 520 if (ap->a_vp->v_type != VDIR) 521 return (ENOTDIR); 522 } 523 524 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 525 return (EROFS); 526 527 /* 528 * Authorize the ACL operation. 529 */ 530 if (ip->i_flags & (IMMUTABLE | APPEND)) 531 return (EPERM); 532 533 /* 534 * Must hold VADMIN (be file owner) or have appropriate privilege. 535 */ 536 if ((error = VOP_ACCESS(ap->a_vp, VADMIN, ap->a_cred, ap->a_td))) 537 return (error); 538 539 switch(ap->a_type) { 540 case ACL_TYPE_ACCESS: 541 old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO); 542 error = acl_copy_acl_into_oldacl(ap->a_aclp, old); 543 if (error == 0) { 544 error = vn_extattr_set(ap->a_vp, IO_NODELOCKED, 545 POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE, 546 POSIX1E_ACL_ACCESS_EXTATTR_NAME, sizeof(*old), 547 (char *) old, ap->a_td); 548 } 549 free(old, M_ACL); 550 break; 551 552 case ACL_TYPE_DEFAULT: 553 if (ap->a_aclp == NULL) { 554 error = vn_extattr_rm(ap->a_vp, IO_NODELOCKED, 555 POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE, 556 POSIX1E_ACL_DEFAULT_EXTATTR_NAME, ap->a_td); 557 /* 558 * Attempting to delete a non-present default ACL 559 * will return success for portability purposes. 560 * (TRIX) 561 * 562 * XXX: Note that since we can't distinguish 563 * "that EA is not supported" from "that EA is not 564 * defined", the success case here overlaps the 565 * the ENOATTR->EOPNOTSUPP case below. 566 */ 567 if (error == ENOATTR) 568 error = 0; 569 } else { 570 old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO); 571 error = acl_copy_acl_into_oldacl(ap->a_aclp, old); 572 if (error == 0) { 573 error = vn_extattr_set(ap->a_vp, IO_NODELOCKED, 574 POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE, 575 POSIX1E_ACL_DEFAULT_EXTATTR_NAME, 576 sizeof(*old), (char *) old, ap->a_td); 577 } 578 free(old, M_ACL); 579 } 580 break; 581 582 default: 583 error = EINVAL; 584 } 585 /* 586 * Map lack of attribute definition in UFS_EXTATTR into lack of 587 * support for ACLs on the filesystem. 588 */ 589 if (error == ENOATTR) 590 return (EOPNOTSUPP); 591 if (error != 0) 592 return (error); 593 594 if (ap->a_type == ACL_TYPE_ACCESS) { 595 /* 596 * Now that the EA is successfully updated, update the 597 * inode and mark it as changed. 598 */ 599 ufs_sync_inode_from_acl(ap->a_aclp, ip); 600 UFS_INODE_SET_FLAG(ip, IN_CHANGE); 601 error = UFS_UPDATE(ap->a_vp, 0); 602 } 603 604 VN_KNOTE_UNLOCKED(ap->a_vp, NOTE_ATTRIB); 605 return (error); 606 } 607 608 int 609 ufs_setacl(ap) 610 struct vop_setacl_args /* { 611 struct vnode *vp; 612 acl_type_t type; 613 struct acl *aclp; 614 struct ucred *cred; 615 struct thread *td; 616 } */ *ap; 617 { 618 if ((ap->a_vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS)) == 0) 619 return (EOPNOTSUPP); 620 621 if (ap->a_type == ACL_TYPE_NFS4) 622 return (ufs_setacl_nfs4(ap)); 623 624 return (ufs_setacl_posix1e(ap)); 625 } 626 627 static int 628 ufs_aclcheck_nfs4(struct vop_aclcheck_args *ap) 629 { 630 int is_directory = 0; 631 632 if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0) 633 return (EINVAL); 634 635 /* 636 * With NFSv4 ACLs, chmod(2) may need to add additional entries. 637 * Make sure it has enough room for that - splitting every entry 638 * into two and appending "canonical six" entries at the end. 639 */ 640 if (ap->a_aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2) 641 return (ENOSPC); 642 643 if (ap->a_vp->v_type == VDIR) 644 is_directory = 1; 645 646 return (acl_nfs4_check(ap->a_aclp, is_directory)); 647 } 648 649 static int 650 ufs_aclcheck_posix1e(struct vop_aclcheck_args *ap) 651 { 652 653 if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) 654 return (EINVAL); 655 656 /* 657 * Verify we understand this type of ACL, and that it applies 658 * to this kind of object. 659 * Rely on the acl_posix1e_check() routine to verify the contents. 660 */ 661 switch(ap->a_type) { 662 case ACL_TYPE_ACCESS: 663 break; 664 665 case ACL_TYPE_DEFAULT: 666 if (ap->a_vp->v_type != VDIR) 667 return (EINVAL); 668 break; 669 670 default: 671 return (EINVAL); 672 } 673 674 if (ap->a_aclp->acl_cnt > OLDACL_MAX_ENTRIES) 675 return (EINVAL); 676 677 return (acl_posix1e_check(ap->a_aclp)); 678 } 679 680 /* 681 * Check the validity of an ACL for a file. 682 */ 683 int 684 ufs_aclcheck(ap) 685 struct vop_aclcheck_args /* { 686 struct vnode *vp; 687 acl_type_t type; 688 struct acl *aclp; 689 struct ucred *cred; 690 struct thread *td; 691 } */ *ap; 692 { 693 694 if ((ap->a_vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS)) == 0) 695 return (EOPNOTSUPP); 696 697 if (ap->a_type == ACL_TYPE_NFS4) 698 return (ufs_aclcheck_nfs4(ap)); 699 700 return (ufs_aclcheck_posix1e(ap)); 701 } 702 703 #endif /* !UFS_ACL */ 704