summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2009-12-21 19:39:10 +0000
committertrasz <trasz@FreeBSD.org>2009-12-21 19:39:10 +0000
commitf04a989f2dbe7ffdf8dc178715cc5fe4c658f813 (patch)
tree4b32c0e46acd0bb797fce83987089212198f0f51
parentfdf85ee3e500bc4c682b7a6c7fc0126cd005406e (diff)
downloadFreeBSD-src-f04a989f2dbe7ffdf8dc178715cc5fe4c658f813.zip
FreeBSD-src-f04a989f2dbe7ffdf8dc178715cc5fe4c658f813.tar.gz
Implement NFSv4 ACL support for UFS.
Reviewed by: rwatson
-rw-r--r--sbin/dumpfs/dumpfs.c5
-rw-r--r--sbin/mount/mntopts.h4
-rw-r--r--sbin/mount/mount.814
-rw-r--r--sbin/mount/mount.c2
-rw-r--r--sbin/tunefs/tunefs.85
-rw-r--r--sbin/tunefs/tunefs.c60
-rw-r--r--sys/sys/mount.h9
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c42
-rw-r--r--sys/ufs/ffs/fs.h32
-rw-r--r--sys/ufs/ufs/acl.h2
-rw-r--r--sys/ufs/ufs/ufs_acl.c222
-rw-r--r--sys/ufs/ufs/ufs_lookup.c127
-rw-r--r--sys/ufs/ufs/ufs_vnops.c188
13 files changed, 620 insertions, 92 deletions
diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c
index 4bcbe5f..b7f6d39 100644
--- a/sbin/dumpfs/dumpfs.c
+++ b/sbin/dumpfs/dumpfs.c
@@ -251,8 +251,11 @@ dumpfs(const char *name)
printf("gjournal ");
if (fsflags & FS_FLAGS_UPDATED)
printf("fs_flags expanded ");
+ if (fsflags & FS_NFS4ACLS)
+ printf("nfsv4acls ");
fsflags &= ~(FS_UNCLEAN | FS_DOSOFTDEP | FS_NEEDSFSCK | FS_INDEXDIRS |
- FS_ACLS | FS_MULTILABEL | FS_GJOURNAL | FS_FLAGS_UPDATED);
+ FS_ACLS | FS_MULTILABEL | FS_GJOURNAL | FS_FLAGS_UPDATED |
+ FS_NFS4ACLS);
if (fsflags != 0)
printf("unknown flags (%#x)", fsflags);
putchar('\n');
diff --git a/sbin/mount/mntopts.h b/sbin/mount/mntopts.h
index 2fcbbdd..2903d55 100644
--- a/sbin/mount/mntopts.h
+++ b/sbin/mount/mntopts.h
@@ -54,6 +54,7 @@ struct mntopt {
#define MOPT_SNAPSHOT { "snapshot", 0, MNT_SNAPSHOT, 0 }
#define MOPT_MULTILABEL { "multilabel", 0, MNT_MULTILABEL, 0 }
#define MOPT_ACLS { "acls", 0, MNT_ACLS, 0 }
+#define MOPT_NFS4ACLS { "nfsv4acls", 0, MNT_NFS4ACLS, 0 }
/* Control flags. */
#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 }
@@ -87,7 +88,8 @@ struct mntopt {
MOPT_NOCLUSTERR, \
MOPT_NOCLUSTERW, \
MOPT_MULTILABEL, \
- MOPT_ACLS
+ MOPT_ACLS, \
+ MOPT_NFS4ACLS
void getmntopts(const char *, const struct mntopt *, int *, int *);
void rmslashes(char *, char *);
diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8
index 3efc9f1..ea01455 100644
--- a/sbin/mount/mount.8
+++ b/sbin/mount/mount.8
@@ -120,11 +120,14 @@ takes effect.
The following options are available:
.Bl -tag -width indent
.It Cm acls
-Enable Access Control Lists, or ACLS, which can be customized via the
+Enable POSIX.1e Access Control Lists, or ACLs, which can be customized via the
.Xr setfacl 1
and
.Xr getfacl 1
commands.
+This flag is mutually exclusive with
+.Cm nfsv4acls
+flag.
.It Cm async
All
.Tn I/O
@@ -186,6 +189,15 @@ See
.Xr mac 4
for more information, which cause the multilabel mount flag to be set
automatically at mount-time.
+.It Cm nfsv4acls
+Enable NFSv4 ACLs, which can be customized via the
+.Xr setfacl 1
+and
+.Xr getfacl 1
+commands.
+This flag is mutually exclusive with
+.Cm acls
+flag.
.It Cm noasync
Metadata I/O should be done synchronously, while data I/O should be done
asynchronously.
diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c
index 0bd5533..907f754 100644
--- a/sbin/mount/mount.c
+++ b/sbin/mount/mount.c
@@ -111,6 +111,7 @@ static struct opt {
{ MNT_SOFTDEP, "soft-updates" },
{ MNT_MULTILABEL, "multilabel" },
{ MNT_ACLS, "acls" },
+ { MNT_NFS4ACLS, "nfsv4acls" },
{ MNT_GJOURNAL, "gjournal" },
{ 0, NULL }
};
@@ -918,6 +919,7 @@ flags2opts(int flags)
if (flags & MNT_SUIDDIR) res = catopt(res, "suiddir");
if (flags & MNT_MULTILABEL) res = catopt(res, "multilabel");
if (flags & MNT_ACLS) res = catopt(res, "acls");
+ if (flags & MNT_NFS4ACLS) res = catopt(res, "nfsv4acls");
return (res);
}
diff --git a/sbin/tunefs/tunefs.8 b/sbin/tunefs/tunefs.8
index e2664e3..53e463c 100644
--- a/sbin/tunefs/tunefs.8
+++ b/sbin/tunefs/tunefs.8
@@ -44,6 +44,7 @@
.Op Fl L Ar volname
.Op Fl l Cm enable | disable
.Op Fl m Ar minfree
+.Op Fl N Cm enable | disable
.Op Fl n Cm enable | disable
.Op Fl o Cm space | time
.Op Fl p
@@ -70,7 +71,7 @@ this option will cause all backups to be modified as well as the
primary super-block.
This is potentially dangerous - use with caution.
.It Fl a Cm enable | disable
-Turn on/off the administrative ACL enable flag.
+Turn on/off the administrative POSIX.1e ACL enable flag.
.It Fl e Ar maxbpg
Indicate the maximum number of blocks any single file can
allocate out of a cylinder group before it is forced to begin
@@ -114,6 +115,8 @@ factor of three over the performance obtained at a 10% threshold.
If the value is raised above the current usage level,
users will be unable to allocate files until enough files have
been deleted to get under the higher threshold.
+.It Fl N Cm enable | disable
+Turn on/off the administrative NFSv4 ACL enable flag.
.It Fl n Cm enable | disable
Turn on/off soft updates.
.It Fl o Cm space | time
diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
index 2b263bb..1b5f21a 100644
--- a/sbin/tunefs/tunefs.c
+++ b/sbin/tunefs/tunefs.c
@@ -76,12 +76,12 @@ void printfs(void);
int
main(int argc, char *argv[])
{
- char *avalue, *Jvalue, *Lvalue, *lvalue, *nvalue;
+ char *avalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue;
const char *special, *on;
const char *name;
int active;
int Aflag, aflag, eflag, evalue, fflag, fvalue, Jflag, Lflag, lflag;
- int mflag, mvalue, nflag, oflag, ovalue, pflag, sflag, svalue;
+ int mflag, mvalue, Nflag, nflag, oflag, ovalue, pflag, sflag, svalue;
int ch, found_arg, i;
const char *chg[2];
struct ufs_args args;
@@ -90,12 +90,12 @@ main(int argc, char *argv[])
if (argc < 3)
usage();
Aflag = aflag = eflag = fflag = Jflag = Lflag = lflag = mflag = 0;
- nflag = oflag = pflag = sflag = 0;
- avalue = Jvalue = Lvalue = lvalue = nvalue = NULL;
+ Nflag = nflag = oflag = pflag = sflag = 0;
+ avalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL;
evalue = fvalue = mvalue = ovalue = svalue = 0;
active = 0;
found_arg = 0; /* At least one arg is required. */
- while ((ch = getopt(argc, argv, "Aa:e:f:J:L:l:m:n:o:ps:")) != -1)
+ while ((ch = getopt(argc, argv, "Aa:e:f:J:L:l:m:N:n:o:ps:")) != -1)
switch (ch) {
case 'A':
@@ -105,7 +105,7 @@ main(int argc, char *argv[])
case 'a':
found_arg = 1;
- name = "ACLs";
+ name = "POSIX.1e ACLs";
avalue = optarg;
if (strcmp(avalue, "enable") &&
strcmp(avalue, "disable")) {
@@ -187,6 +187,18 @@ main(int argc, char *argv[])
mflag = 1;
break;
+ case 'N':
+ found_arg = 1;
+ name = "NFSv4 ACLs";
+ Nvalue = optarg;
+ if (strcmp(Nvalue, "enable") &&
+ strcmp(Nvalue, "disable")) {
+ errx(10, "bad %s (options are %s)",
+ name, "`enable' or `disable'");
+ }
+ Nflag = 1;
+ break;
+
case 'n':
found_arg = 1;
name = "soft updates";
@@ -255,10 +267,13 @@ main(int argc, char *argv[])
strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN);
}
if (aflag) {
- name = "ACLs";
+ name = "POSIX.1e ACLs";
if (strcmp(avalue, "enable") == 0) {
if (sblock.fs_flags & FS_ACLS) {
warnx("%s remains unchanged as enabled", name);
+ } else if (sblock.fs_flags & FS_NFS4ACLS) {
+ warnx("%s and NFSv4 ACLs are mutually "
+ "exclusive", name);
} else {
sblock.fs_flags |= FS_ACLS;
warnx("%s set", name);
@@ -349,6 +364,29 @@ main(int argc, char *argv[])
warnx(OPTWARN, "space", "<", MINFREE);
}
}
+ if (Nflag) {
+ name = "NFSv4 ACLs";
+ if (strcmp(Nvalue, "enable") == 0) {
+ if (sblock.fs_flags & FS_NFS4ACLS) {
+ warnx("%s remains unchanged as enabled", name);
+ } else if (sblock.fs_flags & FS_ACLS) {
+ warnx("%s and POSIX.1e ACLs are mutually "
+ "exclusive", name);
+ } else {
+ sblock.fs_flags |= FS_NFS4ACLS;
+ warnx("%s set", name);
+ }
+ } else if (strcmp(Nvalue, "disable") == 0) {
+ if ((~sblock.fs_flags & FS_NFS4ACLS) ==
+ FS_NFS4ACLS) {
+ warnx("%s remains unchanged as disabled",
+ name);
+ } else {
+ sblock.fs_flags &= ~FS_NFS4ACLS;
+ warnx("%s cleared", name);
+ }
+ }
+ }
if (nflag) {
name = "soft updates";
if (strcmp(nvalue, "enable") == 0) {
@@ -423,16 +461,18 @@ usage(void)
fprintf(stderr, "%s\n%s\n%s\n%s\n",
"usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
" [-J enable | disable ] [-L volname] [-l enable | disable]",
-" [-m minfree] [-n enable | disable] [-o space | time] [-p]",
-" [-s avgfpdir] special | filesystem");
+" [-m minfree] [-N enable | disable] [-n enable | disable]",
+" [-o space | time] [-p] [-s avgfpdir] special | filesystem");
exit(2);
}
void
printfs(void)
{
- warnx("ACLs: (-a) %s",
+ warnx("POSIX.1e ACLs: (-a) %s",
(sblock.fs_flags & FS_ACLS)? "enabled" : "disabled");
+ warnx("NFSv4 ACLs: (-N) %s",
+ (sblock.fs_flags & FS_NFS4ACLS)? "enabled" : "disabled");
warnx("MAC multilabel: (-l) %s",
(sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled");
warnx("soft updates: (-n) %s",
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index dbf8c20..b826413 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -239,6 +239,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
#define MNT_NOATIME 0x10000000 /* disable update of file access time */
#define MNT_NOCLUSTERR 0x40000000 /* disable cluster read */
#define MNT_NOCLUSTERW 0x80000000 /* disable cluster write */
+#define MNT_NFS4ACLS 0x00000010
/*
* NFS export related mount flags.
@@ -274,7 +275,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
MNT_ROOTFS | MNT_NOATIME | MNT_NOCLUSTERR| \
MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP | \
MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW | \
- MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS)
+ MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS | MNT_NFS4ACLS)
/* Mask of flags that can be updated. */
#define MNT_UPDATEMASK (MNT_NOSUID | MNT_NOEXEC | \
@@ -282,7 +283,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
MNT_NOATIME | \
MNT_NOSYMFOLLOW | MNT_IGNORE | \
MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR | \
- MNT_ACLS | MNT_USER)
+ MNT_ACLS | MNT_USER | MNT_NFS4ACLS)
/*
* External filesystem command modifier flags.
@@ -300,10 +301,6 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
#define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \
MNT_FORCE | MNT_SNAPSHOT | MNT_BYFSID)
/*
- * Still available.
- */
-#define MNT_SPARE_0x00000010 0x00000010
-/*
* Internal filesystem control flags stored in mnt_kern_flag.
*
* MNTK_UNMOUNT locks the mount entry so that name lookup cannot proceed
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index d3d7c2c..6eb8964 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -128,7 +128,7 @@ static struct buf_ops ffs_ops = {
static const char *ffs_opts[] = { "acls", "async", "noatime", "noclusterr",
"noclusterw", "noexec", "export", "force", "from", "multilabel",
"snapshot", "nosuid", "suiddir", "nosymfollow", "sync",
- "union", NULL };
+ "union", "nfsv4acls", NULL };
static int
ffs_mount(struct mount *mp)
@@ -177,6 +177,15 @@ ffs_mount(struct mount *mp)
vfs_deleteopt(mp->mnt_opt, "snapshot");
}
+ if (vfs_getopt(mp->mnt_optnew, "nfsv4acls", NULL, NULL) == 0) {
+ if (mntorflags & MNT_ACLS) {
+ printf("WARNING: \"acls\" and \"nfsv4acls\" "
+ "options are mutually exclusive\n");
+ return (EINVAL);
+ }
+ mntorflags |= MNT_NFS4ACLS;
+ }
+
MNT_ILOCK(mp);
mp->mnt_flag = (mp->mnt_flag | mntorflags) & ~mntandnotflags;
MNT_IUNLOCK(mp);
@@ -360,6 +369,13 @@ ffs_mount(struct mount *mp)
MNT_IUNLOCK(mp);
}
+ if ((fs->fs_flags & FS_NFS4ACLS) != 0) {
+ /* XXX: Set too late ? */
+ MNT_ILOCK(mp);
+ mp->mnt_flag |= MNT_NFS4ACLS;
+ MNT_IUNLOCK(mp);
+ }
+
/*
* If this is a snapshot request, take the snapshot.
*/
@@ -834,7 +850,13 @@ ffs_mountfs(devvp, mp, td)
if ((fs->fs_flags & FS_ACLS) != 0) {
#ifdef UFS_ACL
MNT_ILOCK(mp);
+
+ if (mp->mnt_flag & MNT_NFS4ACLS)
+ printf("WARNING: ACLs flag on fs conflicts with "
+ "\"nfsv4acls\" mount option; option ignored\n");
+ mp->mnt_flag &= ~MNT_NFS4ACLS;
mp->mnt_flag |= MNT_ACLS;
+
MNT_IUNLOCK(mp);
#else
printf(
@@ -842,6 +864,24 @@ ffs_mountfs(devvp, mp, td)
mp->mnt_stat.f_mntonname);
#endif
}
+ if ((fs->fs_flags & FS_NFS4ACLS) != 0) {
+#ifdef UFS_ACL
+ MNT_ILOCK(mp);
+
+ if (mp->mnt_flag & MNT_ACLS)
+ printf("WARNING: NFSv4 ACLs flag on fs conflicts with "
+ "\"acls\" mount option; option ignored\n");
+ mp->mnt_flag &= ~MNT_ACLS;
+ mp->mnt_flag |= MNT_NFS4ACLS;
+
+ MNT_IUNLOCK(mp);
+#else
+ printf(
+"WARNING: %s: NFSv4 ACLs flag on fs but no ACLs support\n",
+ mp->mnt_stat.f_mntonname);
+#endif
+ }
+
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index 7da18ea..93c12a4 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -393,22 +393,24 @@ CTASSERT(sizeof(struct fs) == 1376);
* flag to indicate that the indicies need to be rebuilt (by fsck) before
* they can be used.
*
- * FS_ACLS indicates that ACLs are administratively enabled for the
- * file system, so they should be loaded from extended attributes,
+ * FS_ACLS indicates that POSIX.1e ACLs are administratively enabled
+ * for the file system, so they should be loaded from extended attributes,
* observed for access control purposes, and be administered by object
- * owners. FS_MULTILABEL indicates that the TrustedBSD MAC Framework
- * should attempt to back MAC labels into extended attributes on the
- * file system rather than maintain a single mount label for all
- * objects.
- */
-#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */
-#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */
-#define FS_NEEDSFSCK 0x04 /* filesystem needs sync fsck before mount */
-#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */
-#define FS_ACLS 0x10 /* file system has ACLs enabled */
-#define FS_MULTILABEL 0x20 /* file system is MAC multi-label */
-#define FS_GJOURNAL 0x40 /* gjournaled file system */
-#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */
+ * owners. FS_NFS4ACLS indicates that NFSv4 ACLs are administratively
+ * enabled. This flag is mutually exclusive with FS_ACLS. FS_MULTILABEL
+ * indicates that the TrustedBSD MAC Framework should attempt to back MAC
+ * labels into extended attributes on the file system rather than maintain
+ * a single mount label for all objects.
+ */
+#define FS_UNCLEAN 0x0001 /* filesystem not clean at mount */
+#define FS_DOSOFTDEP 0x0002 /* filesystem using soft dependencies */
+#define FS_NEEDSFSCK 0x0004 /* filesystem needs sync fsck before mount */
+#define FS_INDEXDIRS 0x0008 /* kernel supports indexed directories */
+#define FS_ACLS 0x0010 /* file system has POSIX.1e ACLs enabled */
+#define FS_MULTILABEL 0x0020 /* file system is MAC multi-label */
+#define FS_GJOURNAL 0x0040 /* gjournaled file system */
+#define FS_FLAGS_UPDATED 0x0080 /* flags have been moved to new location */
+#define FS_NFS4ACLS 0x0100 /* file system has NFSv4 ACLs enabled */
/*
* Macros to access bits in the fs_active array.
diff --git a/sys/ufs/ufs/acl.h b/sys/ufs/ufs/acl.h
index b53e328..235261e 100644
--- a/sys/ufs/ufs/acl.h
+++ b/sys/ufs/ufs/acl.h
@@ -37,6 +37,8 @@
#ifdef _KERNEL
+int ufs_getacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct thread *td);
+int ufs_setacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct thread *td);
void ufs_sync_acl_from_inode(struct inode *ip, struct acl *acl);
void ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip);
diff --git a/sys/ufs/ufs/ufs_acl.c b/sys/ufs/ufs/ufs_acl.c
index 68e5015..c244e87 100644
--- a/sys/ufs/ufs/ufs_acl.c
+++ b/sys/ufs/ufs/ufs_acl.c
@@ -141,6 +141,81 @@ ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip)
}
/*
+ * Retrieve NFSv4 ACL, skipping access checks. Must be used in UFS code
+ * instead of VOP_GETACL() when we don't want to be restricted by the user
+ * not having ACL_READ_ACL permission, e.g. when calculating inherited ACL
+ * or in ufs_vnops.c:ufs_accessx().
+ */
+int
+ufs_getacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct thread *td)
+{
+ int error, len;
+ struct inode *ip = VTOI(vp);
+
+ len = sizeof(*aclp);
+ bzero(aclp, len);
+
+ error = vn_extattr_get(vp, IO_NODELOCKED,
+ NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME,
+ &len, (char *) aclp, td);
+ aclp->acl_maxcnt = ACL_MAX_ENTRIES;
+ if (error == ENOATTR) {
+ /*
+ * Legitimately no ACL set on object, purely
+ * emulate it through the inode.
+ */
+ acl_nfs4_sync_acl_from_mode(aclp, ip->i_mode, ip->i_uid);
+
+ return (0);
+ }
+
+ if (error)
+ return (error);
+
+ if (len != sizeof(*aclp)) {
+ /*
+ * A short (or long) read, meaning that for
+ * some reason the ACL is corrupted. Return
+ * EPERM since the object DAC protections
+ * are unsafe.
+ */
+ printf("ufs_getacl_nfs4(): Loaded invalid ACL ("
+ "%d bytes), inumber %d on %s\n", len,
+ ip->i_number, ip->i_fs->fs_fsmnt);
+
+ return (EPERM);
+ }
+
+ error = acl_nfs4_check(aclp, vp->v_type == VDIR);
+ if (error) {
+ printf("ufs_getacl_nfs4(): Loaded invalid ACL "
+ "(failed acl_nfs4_check), inumber %d on %s\n",
+ ip->i_number, ip->i_fs->fs_fsmnt);
+
+ return (EPERM);
+ }
+
+ return (0);
+}
+
+static int
+ufs_getacl_nfs4(struct vop_getacl_args *ap)
+{
+ int error;
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0)
+ return (EINVAL);
+
+ error = VOP_ACCESSX(ap->a_vp, VREAD_ACL, ap->a_td->td_ucred, ap->a_td);
+ if (error)
+ return (error);
+
+ error = ufs_getacl_nfs4_internal(ap->a_vp, ap->a_aclp, ap->a_td);
+
+ return (error);
+}
+
+/*
* Read POSIX.1e ACL from an EA. Return error if its not found
* or if any other error has occured.
*/
@@ -209,7 +284,7 @@ ufs_getacl_posix1e(struct vop_getacl_args *ap)
* ACLs, remove this check.
*/
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
- return (EOPNOTSUPP);
+ return (EINVAL);
old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO);
@@ -282,10 +357,118 @@ ufs_getacl(ap)
} */ *ap;
{
+ if ((ap->a_vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS)) == 0)
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return (ufs_getacl_nfs4(ap));
+
return (ufs_getacl_posix1e(ap));
}
/*
+ * Set NFSv4 ACL without doing any access checking. This is required
+ * e.g. by the UFS code that implements ACL inheritance, or from
+ * ufs_vnops.c:ufs_chmod(), as some of the checks have to be skipped
+ * in that case, and others are redundant.
+ */
+int
+ufs_setacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct thread *td)
+{
+ int error;
+ mode_t mode;
+ struct inode *ip = VTOI(vp);
+
+ KASSERT(acl_nfs4_check(aclp, vp->v_type == VDIR) == 0,
+ ("invalid ACL passed to ufs_setacl_nfs4_internal"));
+
+ if (acl_nfs4_is_trivial(aclp, ip->i_uid)) {
+ error = vn_extattr_rm(vp, IO_NODELOCKED,
+ NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME, td);
+
+ /*
+ * An attempt to remove ACL from a file that didn't have
+ * any extended entries is not an error.
+ */
+ if (error == ENOATTR)
+ error = 0;
+
+ } else {
+ error = vn_extattr_set(vp, IO_NODELOCKED,
+ NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME,
+ sizeof(*aclp), (char *) aclp, td);
+ }
+
+ /*
+ * Map lack of attribute definition in UFS_EXTATTR into lack of
+ * support for ACLs on the filesystem.
+ */
+ if (error == ENOATTR)
+ return (EOPNOTSUPP);
+
+ if (error)
+ return (error);
+
+ mode = ip->i_mode;
+
+ acl_nfs4_sync_mode_from_acl(&mode, aclp);
+
+ ip->i_mode &= ACL_PRESERVE_MASK;
+ ip->i_mode |= mode;
+ DIP_SET(ip, i_mode, ip->i_mode);
+ ip->i_flag |= IN_CHANGE;
+
+ VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB);
+
+ return (0);
+}
+
+static int
+ufs_setacl_nfs4(struct vop_setacl_args *ap)
+{
+ int error;
+ struct inode *ip = VTOI(ap->a_vp);
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0)
+ return (EINVAL);
+
+ if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+
+ if (ap->a_aclp == NULL)
+ return (EINVAL);
+
+ error = VOP_ACLCHECK(ap->a_vp, ap->a_type, ap->a_aclp, ap->a_cred,
+ ap->a_td);
+ if (error)
+ return (error);
+
+ /*
+ * Authorize the ACL operation.
+ */
+ if (ip->i_flags & (IMMUTABLE | APPEND))
+ return (EPERM);
+
+ /*
+ * Must hold VWRITE_ACL or have appropriate privilege.
+ */
+ if ((error = VOP_ACCESSX(ap->a_vp, VWRITE_ACL, ap->a_cred, ap->a_td)))
+ return (error);
+
+ /*
+ * With NFSv4 ACLs, chmod(2) may need to add additional entries.
+ * Make sure it has enough room for that - splitting every entry
+ * into two and appending "canonical six" entries at the end.
+ */
+ if (ap->a_aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2)
+ return (ENOSPC);
+
+ error = ufs_setacl_nfs4_internal(ap->a_vp, ap->a_aclp, ap->a_td);
+
+ return (0);
+}
+
+/*
* Set the ACL on a file.
*
* As part of the ACL is stored in the inode, and the rest in an EA,
@@ -302,7 +485,7 @@ ufs_setacl_posix1e(struct vop_setacl_args *ap)
struct oldacl *old;
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
- return (EOPNOTSUPP);
+ return (EINVAL);
/*
* If this is a set operation rather than a delete operation,
@@ -422,16 +605,43 @@ ufs_setacl(ap)
struct thread *td;
} */ *ap;
{
+ if ((ap->a_vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS)) == 0)
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return (ufs_setacl_nfs4(ap));
return (ufs_setacl_posix1e(ap));
}
static int
+ufs_aclcheck_nfs4(struct vop_aclcheck_args *ap)
+{
+ int is_directory = 0;
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0)
+ return (EINVAL);
+
+ /*
+ * With NFSv4 ACLs, chmod(2) may need to add additional entries.
+ * Make sure it has enough room for that - splitting every entry
+ * into two and appending "canonical six" entries at the end.
+ */
+ if (ap->a_aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2)
+ return (ENOSPC);
+
+ if (ap->a_vp->v_type == VDIR)
+ is_directory = 1;
+
+ return (acl_nfs4_check(ap->a_aclp, is_directory));
+}
+
+static int
ufs_aclcheck_posix1e(struct vop_aclcheck_args *ap)
{
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
- return (EOPNOTSUPP);
+ return (EINVAL);
/*
* Verify we understand this type of ACL, and that it applies
@@ -471,6 +681,12 @@ ufs_aclcheck(ap)
} */ *ap;
{
+ if ((ap->a_vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS)) == 0)
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return (ufs_aclcheck_nfs4(ap));
+
return (ufs_aclcheck_posix1e(ap));
}
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index ea73b1f..a19068e 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -80,6 +80,61 @@ SYSCTL_INT(_debug, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, "");
static int ufs_lookup_(struct vnode *, struct vnode **, struct componentname *,
ino_t *);
+static int
+ufs_delete_denied(struct vnode *vdp, struct vnode *tdp, struct ucred *cred,
+ struct thread *td)
+{
+ int error;
+
+#ifdef UFS_ACL
+ /*
+ * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt
+ *
+ * 3.16.2.1. ACE4_DELETE vs. ACE4_DELETE_CHILD
+ */
+
+ /*
+ * XXX: Is this check required?
+ */
+ error = VOP_ACCESS(vdp, VEXEC, cred, td);
+ if (error)
+ return (error);
+
+ error = VOP_ACCESSX(tdp, VDELETE, cred, td);
+ if (error == 0)
+ return (0);
+
+ error = VOP_ACCESSX(vdp, VDELETE_CHILD, cred, td);
+ if (error == 0)
+ return (0);
+
+ error = VOP_ACCESSX(vdp, VEXPLICIT_DENY | VDELETE_CHILD, cred, td);
+ if (error)
+ return (error);
+
+#endif /* !UFS_ACL */
+
+ /*
+ * Standard Unix access control - delete access requires VWRITE.
+ */
+ error = VOP_ACCESS(vdp, VWRITE, cred, td);
+ if (error)
+ return (error);
+
+ /*
+ * If directory is "sticky", then user must own
+ * the directory, or the file in it, else she
+ * may not delete it (unless she's root). This
+ * implements append-only directories.
+ */
+ if ((VTOI(vdp)->i_mode & ISVTX) &&
+ VOP_ACCESS(vdp, VADMIN, cred, td) &&
+ VOP_ACCESS(tdp, VADMIN, cred, td))
+ return (EPERM);
+
+ return (0);
+}
+
/*
* Convert a component of a pathname into a pointer to a locked inode.
* This is a very central and rather complicated routine.
@@ -410,8 +465,13 @@ notfound:
/*
* Access for write is interpreted as allowing
* creation of files in the directory.
+ *
+ * XXX: Fix the comment above.
*/
- error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread);
+ if (flags & WILLBEDIR)
+ error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread);
+ else
+ error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread);
if (error)
return (error);
/*
@@ -498,12 +558,17 @@ found:
if (nameiop == DELETE && (flags & ISLASTCN)) {
if (flags & LOCKPARENT)
ASSERT_VOP_ELOCKED(vdp, __FUNCTION__);
- /*
- * Write access to directory required to delete files.
- */
- error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread);
- if (error)
+ if ((error = VFS_VGET(vdp->v_mount, ino,
+ LK_EXCLUSIVE, &tdp)) != 0)
return (error);
+
+ error = ufs_delete_denied(vdp, tdp, cred, cnp->cn_thread);
+ if (error) {
+ vput(tdp);
+ return (error);
+ }
+
+
/*
* Return pointer to current entry in dp->i_offset,
* and distance past previous entry (if there
@@ -523,23 +588,10 @@ found:
if (dp->i_number == ino) {
VREF(vdp);
*vpp = vdp;
- return (0);
- }
- if ((error = VFS_VGET(vdp->v_mount, ino,
- LK_EXCLUSIVE, &tdp)) != 0)
- return (error);
- /*
- * If directory is "sticky", then user must own
- * the directory, or the file in it, else she
- * may not delete it (unless she's root). This
- * implements append-only directories.
- */
- if ((dp->i_mode & ISVTX) &&
- VOP_ACCESS(vdp, VADMIN, cred, cnp->cn_thread) &&
- VOP_ACCESS(tdp, VADMIN, cred, cnp->cn_thread)) {
vput(tdp);
- return (EPERM);
+ return (0);
}
+
*vpp = tdp;
return (0);
}
@@ -551,7 +603,11 @@ found:
* regular file, or empty directory.
*/
if (nameiop == RENAME && (flags & ISLASTCN)) {
- if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)))
+ if (flags & WILLBEDIR)
+ error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread);
+ else
+ error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread);
+ if (error)
return (error);
/*
* Careful about locking second inode.
@@ -563,6 +619,33 @@ found:
if ((error = VFS_VGET(vdp->v_mount, ino,
LK_EXCLUSIVE, &tdp)) != 0)
return (error);
+
+ error = ufs_delete_denied(vdp, tdp, cred, cnp->cn_thread);
+ if (error) {
+ vput(tdp);
+ return (error);
+ }
+
+#ifdef SunOS_doesnt_do_that
+ /*
+ * The only purpose of this check is to return the correct
+ * error. Assume that we want to rename directory "a"
+ * to a file "b", and that we have no ACL_WRITE_DATA on
+ * a containing directory, but we _do_ have ACL_APPEND_DATA.
+ * In that case, the VOP_ACCESS check above will return 0,
+ * and the operation will fail with ENOTDIR instead
+ * of EACCESS.
+ */
+ if (tdp->v_type == VDIR)
+ error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread);
+ else
+ error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread);
+ if (error) {
+ vput(tdp);
+ return (error);
+ }
+#endif
+
*vpp = tdp;
cnp->cn_flags |= SAVENAME;
return (0);
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 08b77ae..2d8f276 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -88,7 +88,7 @@ __FBSDID("$FreeBSD$");
#include <ufs/ffs/ffs_extern.h>
-static vop_access_t ufs_access;
+static vop_accessx_t ufs_accessx;
static int ufs_chmod(struct vnode *, int, struct ucred *, struct thread *);
static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *, struct thread *);
static vop_close_t ufs_close;
@@ -298,8 +298,8 @@ ufs_close(ap)
}
static int
-ufs_access(ap)
- struct vop_access_args /* {
+ufs_accessx(ap)
+ struct vop_accessx_args /* {
struct vnode *a_vp;
accmode_t a_accmode;
struct ucred *a_cred;
@@ -315,6 +315,7 @@ ufs_access(ap)
#endif
#ifdef UFS_ACL
struct acl *acl;
+ acl_type_t type;
#endif
/*
@@ -322,7 +323,7 @@ ufs_access(ap)
* unless the file is a socket, fifo, or a block or
* character device resident on the filesystem.
*/
- if (accmode & VWRITE) {
+ if (accmode & VMODIFY_PERMS) {
switch (vp->v_type) {
case VDIR:
case VLNK:
@@ -367,41 +368,63 @@ relock:
}
}
- /* If immutable bit set, nobody gets to write it. */
- if ((accmode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
+ /*
+ * If immutable bit set, nobody gets to write it. "& ~VADMIN_PERMS"
+ * is here, because without it, * it would be impossible for the owner
+ * to remove the IMMUTABLE flag.
+ */
+ if ((accmode & (VMODIFY_PERMS & ~VADMIN_PERMS)) &&
+ (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
return (EPERM);
#ifdef UFS_ACL
- if ((vp->v_mount->mnt_flag & MNT_ACLS) != 0) {
+ if ((vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS)) != 0) {
+ if (vp->v_mount->mnt_flag & MNT_NFS4ACLS)
+ type = ACL_TYPE_NFS4;
+ else
+ type = ACL_TYPE_ACCESS;
+
acl = acl_alloc(M_WAITOK);
- error = VOP_GETACL(vp, ACL_TYPE_ACCESS, acl, ap->a_cred,
- ap->a_td);
+ if (type == ACL_TYPE_NFS4)
+ error = ufs_getacl_nfs4_internal(vp, acl, ap->a_td);
+ else
+ error = VOP_GETACL(vp, type, acl, ap->a_cred, ap->a_td);
switch (error) {
- case EOPNOTSUPP:
- error = vaccess(vp->v_type, ip->i_mode, ip->i_uid,
- ip->i_gid, ap->a_accmode, ap->a_cred, NULL);
- break;
case 0:
- error = vaccess_acl_posix1e(vp->v_type, ip->i_uid,
- ip->i_gid, acl, ap->a_accmode, ap->a_cred, NULL);
+ if (type == ACL_TYPE_NFS4) {
+ error = vaccess_acl_nfs4(vp->v_type, ip->i_uid,
+ ip->i_gid, acl, accmode, ap->a_cred, NULL);
+ } else {
+ error = vfs_unixify_accmode(&accmode);
+ if (error == 0)
+ error = vaccess_acl_posix1e(vp->v_type, ip->i_uid,
+ ip->i_gid, acl, accmode, ap->a_cred, NULL);
+ }
break;
default:
- printf(
-"ufs_access(): Error retrieving ACL on object (%d).\n",
- error);
+ if (error != EOPNOTSUPP)
+ printf(
+"ufs_accessx(): Error retrieving ACL on object (%d).\n",
+ error);
/*
* XXX: Fall back until debugged. Should
* eventually possibly log an error, and return
* EPERM for safety.
*/
- error = vaccess(vp->v_type, ip->i_mode, ip->i_uid,
- ip->i_gid, ap->a_accmode, ap->a_cred, NULL);
+ error = vfs_unixify_accmode(&accmode);
+ if (error == 0)
+ error = vaccess(vp->v_type, ip->i_mode, ip->i_uid,
+ ip->i_gid, accmode, ap->a_cred, NULL);
}
acl_free(acl);
- } else
+
+ return (error);
+ }
#endif /* !UFS_ACL */
+ error = vfs_unixify_accmode(&accmode);
+ if (error == 0)
error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
- ap->a_accmode, ap->a_cred, NULL);
+ accmode, ap->a_cred, NULL);
return (error);
}
@@ -608,11 +631,20 @@ ufs_setattr(ap)
* check succeeds.
*/
if (vap->va_vaflags & VA_UTIMES_NULL) {
- error = VOP_ACCESS(vp, VADMIN, cred, td);
+ /*
+ * NFSv4.1, draft 21, 6.2.1.3.1, Discussion of Mask Attributes
+ *
+ * "A user having ACL_WRITE_DATA or ACL_WRITE_ATTRIBUTES
+ * will be allowed to set the times [..] to the current
+ * server time."
+ *
+ * XXX: Calling it four times seems a little excessive.
+ */
+ error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred, td);
if (error)
error = VOP_ACCESS(vp, VWRITE, cred, td);
} else
- error = VOP_ACCESS(vp, VADMIN, cred, td);
+ error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred, td);
if (error)
return (error);
if (vap->va_atime.tv_sec != VNOVAL)
@@ -652,6 +684,32 @@ ufs_setattr(ap)
return (error);
}
+#ifdef UFS_ACL
+static int
+ufs_update_nfs4_acl_after_mode_change(struct vnode *vp, int mode,
+ int file_owner_id, struct ucred *cred, struct thread *td)
+{
+ int error;
+ struct acl *aclp;
+
+ aclp = acl_alloc(M_WAITOK);
+ error = ufs_getacl_nfs4_internal(vp, aclp, td);
+ /*
+ * We don't have to handle EOPNOTSUPP here, as the filesystem claims
+ * it supports ACLs.
+ */
+ if (error)
+ goto out;
+
+ acl_nfs4_sync_acl_from_mode(aclp, mode, file_owner_id);
+ error = ufs_setacl_nfs4_internal(vp, aclp, td);
+
+out:
+ acl_free(aclp);
+ return (error);
+}
+#endif /* UFS_ACL */
+
/*
* Mark this file's access time for update for vfs_mark_atime(). This
* is called from execve() and mmap().
@@ -689,7 +747,7 @@ ufs_chmod(vp, mode, cred, td)
* To modify the permissions on a file, must possess VADMIN
* for that file.
*/
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
+ if ((error = VOP_ACCESSX(vp, VWRITE_ACL, cred, td)))
return (error);
/*
* Privileged processes may set the sticky bit on non-directories,
@@ -706,11 +764,25 @@ ufs_chmod(vp, mode, cred, td)
if (error)
return (error);
}
+
+ /*
+ * Deny setting setuid if we are not the file owner.
+ */
+ if ((mode & ISUID) && ip->i_uid != cred->cr_uid) {
+ error = priv_check_cred(cred, PRIV_VFS_ADMIN, 0);
+ if (error)
+ return (error);
+ }
+
ip->i_mode &= ~ALLPERMS;
ip->i_mode |= (mode & ALLPERMS);
DIP_SET(ip, i_mode, ip->i_mode);
ip->i_flag |= IN_CHANGE;
- return (0);
+#ifdef UFS_ACL
+ if ((vp->v_mount->mnt_flag & MNT_NFS4ACLS) != 0)
+ error = ufs_update_nfs4_acl_after_mode_change(vp, mode, ip->i_uid, cred, td);
+#endif
+ return (error);
}
/*
@@ -742,14 +814,14 @@ ufs_chown(vp, uid, gid, cred, td)
* To modify the ownership of a file, must possess VADMIN for that
* file.
*/
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
+ if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred, td)))
return (error);
/*
* To change the owner of a file, or change the group of a file to a
* group of which we are not a member, the caller must have
* privilege.
*/
- if ((uid != ip->i_uid ||
+ if (((uid != ip->i_uid && uid != cred->cr_uid) ||
(gid != ip->i_gid && !groupmember(gid, cred))) &&
(error = priv_check_cred(cred, PRIV_VFS_CHOWN, 0)))
return (error);
@@ -1397,6 +1469,33 @@ out:
return (error);
}
+#ifdef UFS_ACL
+static int
+ufs_do_nfs4_acl_inheritance(struct vnode *dvp, struct vnode *tvp,
+ mode_t child_mode, struct ucred *cred, struct thread *td)
+{
+ int error;
+ struct acl *parent_aclp, *child_aclp;
+
+ parent_aclp = acl_alloc(M_WAITOK);
+ child_aclp = acl_alloc(M_WAITOK | M_ZERO);
+
+ error = ufs_getacl_nfs4_internal(dvp, parent_aclp, td);
+ if (error)
+ goto out;
+ acl_nfs4_compute_inherited_acl(parent_aclp, child_aclp,
+ child_mode, VTOI(tvp)->i_uid, tvp->v_type == VDIR);
+ error = ufs_setacl_nfs4_internal(tvp, child_aclp, td);
+ if (error)
+ goto out;
+out:
+ acl_free(parent_aclp);
+ acl_free(child_aclp);
+
+ return (error);
+}
+#endif
+
/*
* Mkdir system call
*/
@@ -1630,6 +1729,13 @@ ufs_mkdir(ap)
acl_free(dacl);
dacl = acl = NULL;
}
+
+ if (dvp->v_mount->mnt_flag & MNT_NFS4ACLS) {
+ error = ufs_do_nfs4_acl_inheritance(dvp, tvp, dmode,
+ cnp->cn_cred, cnp->cn_thread);
+ if (error)
+ goto bad;
+ }
#endif /* !UFS_ACL */
/*
@@ -2117,6 +2223,7 @@ ufsfifo_pathconf(ap)
switch (ap->a_name) {
case _PC_ACL_EXTENDED:
+ case _PC_ACL_NFS4:
case _PC_ACL_PATH_MAX:
case _PC_MAC_PRESENT:
return (ufs_pathconf(ap));
@@ -2169,9 +2276,21 @@ ufs_pathconf(ap)
*ap->a_retval = 0;
#endif
break;
+
+ case _PC_ACL_NFS4:
+#ifdef UFS_ACL
+ if (ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS)
+ *ap->a_retval = 1;
+ else
+ *ap->a_retval = 0;
+#else
+ *ap->a_retval = 0;
+#endif
+ break;
+
case _PC_ACL_PATH_MAX:
#ifdef UFS_ACL
- if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS)
+ if (ap->a_vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS))
*ap->a_retval = ACL_MAX_ENTRIES;
else
*ap->a_retval = 3;
@@ -2466,6 +2585,13 @@ ufs_makeinode(mode, dvp, vpp, cnp)
}
acl_free(acl);
}
+
+ if (dvp->v_mount->mnt_flag & MNT_NFS4ACLS) {
+ error = ufs_do_nfs4_acl_inheritance(dvp, tvp, mode,
+ cnp->cn_cred, cnp->cn_thread);
+ if (error)
+ goto bad;
+ }
#endif /* !UFS_ACL */
ufs_makedirentry(ip, cnp, &newdir);
error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL);
@@ -2496,7 +2622,7 @@ struct vop_vector ufs_vnodeops = {
.vop_read = VOP_PANIC,
.vop_reallocblks = VOP_PANIC,
.vop_write = VOP_PANIC,
- .vop_access = ufs_access,
+ .vop_accessx = ufs_accessx,
.vop_bmap = ufs_bmap,
.vop_cachedlookup = ufs_lookup,
.vop_close = ufs_close,
@@ -2540,7 +2666,7 @@ struct vop_vector ufs_vnodeops = {
struct vop_vector ufs_fifoops = {
.vop_default = &fifo_specops,
.vop_fsync = VOP_PANIC,
- .vop_access = ufs_access,
+ .vop_accessx = ufs_accessx,
.vop_close = ufsfifo_close,
.vop_getattr = ufs_getattr,
.vop_inactive = ufs_inactive,
OpenPOWER on IntegriCloud