Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 May 2008 18:51:12 GMT
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 142223 for review
Message-ID:  <200805241851.m4OIpCnK076739@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=142223

Change 142223 by trasz@trasz_traszkan on 2008/05/24 18:50:18

	- Add SunOS-compatible API for ACL (ace_t) saving and loading.  It's
	  only temporary, as having two completely separate APIs for ACLs
	  is not a good idea.
	
	- Add saving and restoring of NFSv4 ACLs to UFS.  Not well tested
	  yet, and again only temporary, as it stores the number of entries
	  as a separate extattr.

Affected files ...

.. //depot/projects/soc2008/trasz_nfs4acl/lib/libc/include/namespace.h#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/lib/libc/sys/Symbol.map#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/lib/libc_r/uthread/Makefile.inc#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/lib/libc_r/uthread/uthread_facl.c#1 add
.. //depot/projects/soc2008/trasz_nfs4acl/sys/compat/freebsd32/syscalls.master#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/syscalls.master#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_acl.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vnode_if.src#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/acl.h#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/mount.h#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/unistd.h#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ffs/ffs_vfsops.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/acl.h#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_acl.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_vnops.c#2 edit

Differences ...

==== //depot/projects/soc2008/trasz_nfs4acl/lib/libc/include/namespace.h#2 (text+ko) ====

@@ -53,6 +53,8 @@
 #define		__acl_delete_fd			___acl_delete_fd
 #define		__acl_get_fd			___acl_get_fd
 #define		__acl_set_fd			___acl_set_fd
+#define		acl				_acl
+#define		facl				_facl
 #define		bind				_bind
 #define		__cap_get_fd			___cap_get_fd
 #define		__cap_set_fd			___cap_set_fd

==== //depot/projects/soc2008/trasz_nfs4acl/lib/libc/sys/Symbol.map#2 (text) ====

@@ -20,6 +20,8 @@
 	__acl_set_fd;
 	__acl_set_file;
 	__acl_set_link;
+	acl;
+	facl;
 	__getcwd;
 	__mac_execve;
 	__mac_get_fd;

==== //depot/projects/soc2008/trasz_nfs4acl/lib/libc_r/uthread/Makefile.inc#2 (text+ko) ====

@@ -9,6 +9,7 @@
 	uthread_acl_get_fd.c \
 	uthread_acl_set_fd.c \
 	uthread_acl_aclcheck_fd.c \
+	uthread_facl.c \
 	uthread_aio_suspend.c \
 	uthread_atfork.c \
 	uthread_attr_destroy.c \

==== //depot/projects/soc2008/trasz_nfs4acl/sys/compat/freebsd32/syscalls.master#2 (text+ko) ====

@@ -795,6 +795,8 @@
 480	AUE_FTRUNCATE	STD	{ int freebsd32_ftruncate(int fd, \
 				    u_int32_t lengthlo, u_int32_t lengthhi); }
 481	AUE_KILL	NOPROTO	{ int thr_kill2(pid_t pid, long id, int sig); }
+482	AUE_NULL	STD	{ int acl(char *path, int cmd, int nentries, void *aclp); }
+483	AUE_NULL	STD	{ int facl(int filedes, int cmd, int nentries, void *aclp); }
 482	AUE_SHMOPEN	NOPROTO	{ int shm_open(const char *path, int flags, \
 				    mode_t mode); }
 483	AUE_SHMUNLINK	NOPROTO	{ int shm_unlink(const char *path); }

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/syscalls.master#2 (text+ko) ====

@@ -843,6 +843,8 @@
 479	AUE_TRUNCATE	STD	{ int truncate(char *path, off_t length); }
 480	AUE_FTRUNCATE	STD	{ int ftruncate(int fd, off_t length); }
 481	AUE_KILL	STD	{ int thr_kill2(pid_t pid, long id, int sig); }
+482	AUE_NULL	STD	{ int acl(char *path, int cmd, int nentries, void *aclp); }
+483	AUE_NULL	STD	{ int facl(int filedes, int cmd, int nentries, void *aclp); }
 482	AUE_SHMOPEN	STD	{ int shm_open(const char *path, int flags, \
 				    mode_t mode); }
 483	AUE_SHMUNLINK	STD	{ int shm_unlink(const char *path); }

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_acl.c#2 (text+ko) ====

@@ -66,6 +66,8 @@
 static int	vacl_aclcheck(struct thread *td, struct vnode *vp,
 		    acl_type_t type, struct acl *aclp);
 
+MALLOC_DEFINE(M_ACE, "acebuffers", "NFSv4 ACL buffers");
+
 /*
  * These calls wrap the real vnode operations, and are called by the syscall
  * code once the syscall has converted the path or file descriptor to a vnode
@@ -420,6 +422,157 @@
 	return (error);
 }
 
+static int
+kacl_get(struct thread *td, struct vnode *vp, int nentries, void *aclp)
+{
+	void *inkernelacl;
+	int error, count;
+
+	if (nentries <= 0 || nentries > MAX_ACL_ENTRIES)
+		return (EINVAL);
+
+	inkernelacl = malloc(nentries * sizeof(ace_t), M_ACE, M_ZERO | M_WAITOK);
+	KASSERT(inkernelacl != NULL, "null inkernelacl");
+
+	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+#if 0
+	error = mac_check_vnode_getacl(td->td_ucred, vp, ACL_TYPE_NFS4);
+	if (error != 0)
+		goto out;
+#endif
+	error = VOP_GETACE(vp, nentries, &count, inkernelacl, td->td_ucred, td);
+#ifdef MAC
+out:
+#endif
+	VOP_UNLOCK(vp, 0, td);
+
+	if (error == 0) {
+		td->td_retval[0] = count;
+		error = copyout(inkernelacl, aclp, nentries * sizeof(ace_t));
+	}
+
+	free(inkernelacl, M_ACE);
+
+	return (error);
+}
+
+static int
+kacl_getaclcnt(struct thread *td, struct vnode *vp, int nentries, void *notused)
+{
+	int error, count;
+
+	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+#if 0
+	error = mac_check_vnode_getacl(td->td_ucred, vp, ACL_TYPE_NFS4);
+	if (error != 0)
+		goto out;
+#endif
+	error = VOP_GETACECNT(vp, &count, td->td_ucred, td);
+#ifdef MAC
+out:
+#endif
+	VOP_UNLOCK(vp, 0, td);
+
+	if (error == 0)
+		td->td_retval[0] = count;
+
+	return (error);
+}
+
+static int
+kacl_set(struct thread *td, struct vnode *vp, int nentries, void *aclp)
+{
+	struct mount *mp;
+	void *inkernelacl;
+	int error;
+
+	if (nentries <= 0 || nentries > MAX_ACL_ENTRIES)
+		return (EINVAL);
+
+	inkernelacl = malloc(nentries * sizeof(ace_t), M_ACE, M_ZERO | M_WAITOK);
+	KASSERT(inkernelacl != NULL, "null inkernelacl");
+
+	error = copyin(aclp, inkernelacl, nentries * sizeof(ace_t));
+	if (error)
+		goto out_free;
+
+	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
+	if (error != 0)
+		goto out_free;
+
+	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+#if 0
+	error = mac_check_vnode_setacl(td->td_ucred, vp, type, &inkernelacl);
+	if (error != 0)
+		goto out;
+#endif
+	error = VOP_SETACE(vp, nentries, inkernelacl, td->td_ucred, td);
+#ifdef MAC
+out:
+#endif
+	VOP_UNLOCK(vp, 0, td);
+	vn_finished_write(mp);
+
+out_free:
+	free(inkernelacl, M_ACE);
+
+	return (error);
+}
+
+static int
+kacl(struct thread *td, struct vnode *vp, int cmd, int nentries, void *aclp)
+{
+	switch (cmd) {
+		case ACE_GETACL:
+			return (kacl_get(td, vp, nentries, aclp));
+
+		case ACE_GETACLCNT:
+			return (kacl_getaclcnt(td, vp, nentries, aclp));
+
+		case ACE_SETACL:
+			return (kacl_set(td, vp, nentries, aclp));
+
+		default:
+			return (EINVAL);
+	}
+}
+
+int
+acl(struct thread *td, struct acl_args *uap)
+{
+	struct nameidata nd;
+	int vfslocked, error;
+
+	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
+	error = namei(&nd);
+	vfslocked = NDHASGIANT(&nd);
+	if (error == 0) {
+		error = kacl(td, nd.ni_vp, uap->cmd, uap->nentries, uap->aclp);
+		NDFREE(&nd, 0);
+	}
+	VFS_UNLOCK_GIANT(vfslocked);
+	return (error);
+}
+
+int
+facl(struct thread *td, struct facl_args *uap)
+{
+	struct file *fp;
+	int vfslocked, error;
+
+	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
+	if (error == 0) {
+		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
+		error = kacl(td, fp->f_vnode, uap->cmd, uap->nentries, uap->aclp);
+		fdrop(fp, td);
+		VFS_UNLOCK_GIANT(vfslocked);
+	}
+	return (error);
+}
+
 /* ARGUSED */
 
 static void

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vnode_if.src#2 (text+ko) ====

@@ -513,6 +513,35 @@
 	IN struct thread *td;
 };
 
+%% getace	vp	L L L
+
+vop_getace {
+	IN struct vnode *vp;
+	IN int nentries;
+	OUT int *count;
+	OUT void *aclp;
+	IN struct ucred *cred;
+	IN struct thread *td;
+};
+
+%% getacecnt	vp	L L L
+
+vop_getacecnt {
+	IN struct vnode *vp;
+	OUT int *count;
+	IN struct ucred *cred;
+	IN struct thread *td;
+};
+
+%% setace	vp	E E E
+
+vop_setace {
+	IN struct vnode *vp;
+	IN int nentries;
+	IN void *aclp;
+	IN struct ucred *cred;
+	IN struct thread *td;
+};
 
 %% closeextattr	vp	L L L
 

==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/acl.h#2 (text+ko) ====

@@ -113,9 +113,90 @@
  */
 #define	ACL_UNDEFINED_ID	((uid_t)-1)
 
+/*
+ * NFSv4 ACL types and related constants.
+ */
+#ifndef _SOLARIS_C_SOURCE /* XXX: Otherwise zfs won't compile. */
+
+#define	NFS4_ACL_EXTATTR_NAMESPACE		EXTATTR_NAMESPACE_SYSTEM
+#define	NFS4_ACL_EXTATTR_NAME			"nfs4.acl"
+#define	NFS4_ACLCNT_EXTATTR_NAME		"nfs4.aclcount"
+
+#define MAX_ACL_ENTRIES				1024
+
+typedef uint32_t	ace_type_t;
+typedef uint32_t	ace_flags_t;
+typedef uint32_t	ace_mask_t;
+
+struct ace_t_struct {
+	ace_type_t	a_type;
+	ace_flags_t	a_flags;
+	ace_mask_t	a_access_mask;
+	uid_t		a_who;
+};
+typedef struct ace_t_struct ace_t;
+
+/*
+ * Possible values for a_type field.
+ */
+#define ACE_ACCESS_ALLOWED_ACE_TYPE	0x00000000
+#define ACE_ACCESS_DENIED_ACE_TYPE	0x00000001
+#define ACE_SYSTEM_AUDIT_ACE_TYPE	0x00000002
+#define ACE_SYSTEM_ALARM_ACE_TYPE	0x00000003
 
+/*
+ * Possible values for a_flags field.
+ */
+#define ACE_FILE_INHERIT_ACE		0x00000001
+#define ACE_DIRECTORY_INHERIT_ACE	0x00000002
+#define ACE_NO_PROPAGATE_INHERIT_ACE	0x00000004
+#define ACE_INHERIT_ONLY_ACE		0x00000008
+#define ACE_SUCCESSFUL_ACCESS_ACE_FLAG	0x00000010
+#define ACE_FAILED_ACCESS_ACE_FLAG	0x00000020
+#define ACE_IDENTIFIER_GROUP		0x00000040
+
+/*
+ * The following three values go into a_flags field and mean,
+ * respectively, OWNER@, GROUP@ and EVERYONE@.
+ */
+#define ACE_OWNER			0x10000000
+#define ACE_GROUP			0x20000000
+#define ACE_EVERYONE			0x40000000
+
+/*
+ * Possible values for a_access_mask field.
+ */
+#define ACE_READ_DATA			0x00000001
+#define ACE_LIST_DIRECTORY		0x00000001
+#define ACE_WRITE_DATA			0x00000002
+#define ACE_ADD_FILE			0x00000002
+#define ACE_APPEND_DATA			0x00000004
+#define ACE_ACE_ADD_SUBDIRECTORY	0x00000004
+#define ACE_READ_NAMED_ATTRS		0x00000008
+#define ACE_WRITE_NAMED_ATTRS		0x00000010
+#define ACE_EXECUTE			0x00000020
+#define ACE_DELETE_CHILD		0x00000040
+#define ACE_READ_ATTRIBUTES		0x00000080
+#define ACE_WRITE_ATTRIBUTES		0x00000100
+#define ACE_DELETE			0x00010000
+#define ACE_READ_ACL			0x00020000
+#define ACE_WRITE_ACL			0x00040000
+#define ACE_WRITE_OWNER			0x00080000
+#define ACE_SYNCHRONIZE			0x00100000
+
+/*
+ * Possible values for _cmd parameter for acl(2)/facl(2).
+ */
+#define ACE_SETACL	1
+#define ACE_GETACL	2
+#define ACE_GETACLCNT	3
+
+#endif /* !_SOLARIS_C_SOURCE */
+
 #ifdef _KERNEL
 
+MALLOC_DECLARE(M_ACE);
+
 extern uma_zone_t	acl_zone;
 
 /*
@@ -151,7 +232,7 @@
 
 /*
  * Syscall interface -- use the library calls instead as the syscalls have
- * strict acl entry ordering requirements.
+ * strict acl entry ordering requirements.  This does not support NFSv4 ACLs.
  */
 __BEGIN_DECLS
 int	__acl_aclcheck_fd(int _filedes, acl_type_t _type, struct acl *_aclp);
@@ -171,6 +252,14 @@
 __END_DECLS
 
 /*
+ * SunOS-compatible syscall interface.  It supports only NFSv4 ACLs (ace_t).
+ */
+__BEGIN_DECLS
+int	acl(char *_path, int _cmd, int _nentries, void *_aclp);
+int	facl(int _filedes, int _cmd, int _nentries, void *_aclp);
+__END_DECLS
+
+/*
  * Supported POSIX.1e ACL manipulation and assignment/retrieval API _np calls
  * are local extensions that reflect an environment capable of opening file
  * descriptors of directories, and allowing additional ACL type for different

==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/mount.h#2 (text+ko) ====

@@ -233,6 +233,7 @@
 #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.
@@ -268,7 +269,7 @@
 			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	| \
@@ -276,7 +277,7 @@
 			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.
@@ -294,10 +295,6 @@
 #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

==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/unistd.h#2 (text+ko) ====

@@ -153,6 +153,7 @@
 #define	_PC_CAP_PRESENT		61
 #define	_PC_INF_PRESENT		62
 #define	_PC_MAC_PRESENT		63
+#define	_ACL_ACE_ENABLED	64
 #endif
 
 /* From OpenSolaris, used by SEEK_DATA/SEEK_HOLE. */

==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ffs/ffs_vfsops.c#2 (text+ko) ====

@@ -125,7 +125,7 @@
 static const char *ffs_opts[] = { "acls", "async", "noatime", "noclusterr",
     "noclusterw", "noexec", "export", "force", "from", "multilabel", 
     "snapshot", "nosuid", "suiddir", "nosymfollow", "sync",
-    "union", NULL };
+    "union", "nfs4acls", NULL };
 
 static int
 ffs_mount(struct mount *mp, struct thread *td)
@@ -186,6 +186,14 @@
 	if (vfs_getopt(mp->mnt_optnew, "snapshot", NULL, NULL) == 0)
 		mntorflags |= MNT_SNAPSHOT;
 
+	if (vfs_getopt(mp->mnt_optnew, "nfs4acls", NULL, NULL) == 0) {
+		printf("WARNING: both acls and nfs4acls specified\n");
+#if 0
+		return (EINVAL);
+#endif
+		mntorflags |= MNT_NFS4ACLS;
+	}
+
 	MNT_ILOCK(mp);
 	mp->mnt_flag = (mp->mnt_flag | mntorflags) & ~mntandnotflags;
 	MNT_IUNLOCK(mp);
@@ -816,7 +824,12 @@
 	if ((fs->fs_flags & FS_ACLS) != 0) {
 #ifdef UFS_ACL
 		MNT_ILOCK(mp);
-		mp->mnt_flag |= MNT_ACLS;
+
+		if (mp->mnt_flag | MNT_NFS4ACLS)
+			printf("WARNING: ACLs flag on fs conflicts with nfs4acls mount option; flag ignored\n");
+		else
+			mp->mnt_flag |= MNT_ACLS;
+
 		MNT_IUNLOCK(mp);
 #else
 		printf(

==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/acl.h#2 (text+ko) ====

@@ -44,6 +44,13 @@
 int	ufs_setacl(struct vop_setacl_args *);
 int	ufs_aclcheck(struct vop_aclcheck_args *);
 
+int ufs_load_acecnt(struct vnode *vp, int *nentries, struct thread *td);
+int ufs_nfs4acl_from_inode(struct vop_getace_args *ap);
+void ufs_sync_inode_from_nfs4acl(ace_t *aclp, int nentries, struct inode *ip);
+int ufs_getace(struct vop_getace_args *ap);
+int ufs_getacecnt(struct vop_getacecnt_args *ap);
+int ufs_setace(struct vop_setace_args *ap);
+
 #endif /* !_KERNEL */
 
 #endif /* !_UFS_UFS_ACL_H_ */

==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_acl.c#2 (text+ko) ====

@@ -438,4 +438,206 @@
 	return (acl_posix1e_check(ap->a_aclp));
 }
 
+int
+ufs_load_acecnt(struct vnode *vp, int *nentries, struct thread *td)
+{
+	int error, length;
+
+	length = sizeof (*nentries);
+
+	error = vn_extattr_get(vp, IO_NODELOCKED,
+	    NFS4_ACL_EXTATTR_NAMESPACE,
+	    NFS4_ACLCNT_EXTATTR_NAME, &length,
+	    (char *)nentries, td);
+
+	if (error == 0 && length != sizeof (*nentries)) {
+		printf("ufs_load_acecnt: short read (%d bytes)\n", length);
+		return (EIO);
+	}
+
+	if (error != 0 && error != ENOATTR)
+		printf("ufs_load_acecnt: error %d\n", error);
+
+	return error;
+}
+
+int
+ufs_nfs4acl_from_inode(struct vop_getace_args *ap)
+{
+	if (ap->a_nentries < 6)
+		return (ENOSPC);
+
+	*(ap->a_count) = 6;
+
+	return (0);
+}
+
+void
+ufs_sync_inode_from_nfs4acl(ace_t *aclp, int nentries, struct inode *ip)
+{
+}
+
+int
+ufs_getace(struct vop_getace_args *ap)
+{
+	int error, length, expected_length;
+
+	/*
+	 * XXX: If ufs_getace() should work on file systems not supporting
+	 * ACLs, remove this check.
+	 */
+	if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0)
+		return (EOPNOTSUPP);
+
+	error = ufs_load_acecnt(ap->a_vp, ap->a_count, ap->a_td);
+	switch (error) {
+	case ENOATTR:
+		return (ufs_nfs4acl_from_inode(ap));
+
+	case 0:
+		break;
+
+	default:
+		return (EPERM);
+	}
+
+	if (*(ap->a_count) > ap->a_nentries)
+		return (ENOSPC);
+
+	expected_length = *(ap->a_count) * sizeof(ace_t);
+	length = expected_length;
+
+	error = vn_extattr_get(ap->a_vp, IO_NODELOCKED,
+	    NFS4_ACL_EXTATTR_NAMESPACE,
+	    NFS4_ACL_EXTATTR_NAME, &length, (char *)ap->a_aclp,
+	    ap->a_td);
+
+	switch (error) {
+	/* XXX: If ufs_getace() should work on filesystems without
+	 * the EA configured, add case EOPNOTSUPP here. */
+	case ENOATTR:
+		/*
+		 * Legitimately no ACL set on object, purely
+		 * emulate it through the inode.  These fields will
+		 * be updated when the ACL is synchronized with
+		 * the inode later.
+		 */
+		return (ufs_nfs4acl_from_inode(ap));
+
+	case 0:
+		if (length != expected_length) {
+			/*
+			 * 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_getace(): short read, wanted %d bytes, "
+			    "got only %d.", expected_length, length);
+
+			return (EPERM);
+		}
+
+		break;
+
+	default:
+		error = EINVAL;
+	}
+
+	return (error);
+}
+
+int
+ufs_getacecnt(struct vop_getacecnt_args *ap)
+{
+	int error;
+
+	/*
+	 * XXX: If ufs_getacecnt() should work on file systems not supporting
+	 * ACLs, remove this check.
+	 */
+	if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0)
+		return (EOPNOTSUPP);
+
+	error = ufs_load_acecnt(ap->a_vp, ap->a_count, ap->a_td);
+
+	if (error == ENOATTR) {
+		*(ap->a_count) = 6;
+		error = 0;
+	}
+
+	return (error);
+}
+
+int
+ufs_setace(struct vop_setace_args *ap)
+{
+	struct inode *ip = VTOI(ap->a_vp);
+	int error, nentries;
+
+	if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0)
+		return (EOPNOTSUPP);
+
+	/*
+	 * XXX: Check if ACL is valid.
+	 */
+
+	/*
+	 * XXX: Remove ACL if it's trivial.
+	 */
+
+	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
+		return (EROFS);
+
+	/*
+	 * Authorize the ACL operation.
+	 */
+	if (ip->i_flags & (IMMUTABLE | APPEND))
+		return (EPERM);
+
+	/*
+	 * Must hold VADMIN (be file owner) or have appropriate privilege.
+	 */
+	if ((error = VOP_ACCESS(ap->a_vp, VADMIN, ap->a_cred, ap->a_td)))
+		return (error);
+
+	nentries = ap->a_nentries;
+
+	error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
+	    NFS4_ACL_EXTATTR_NAMESPACE,
+	    NFS4_ACLCNT_EXTATTR_NAME, sizeof(int),
+	    (char *)&nentries, ap->a_td);
+
+	if (error == ENOATTR)
+		return (EOPNOTSUPP);
+
+	if (error != 0)
+		return (error);
+
+	error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
+	    NFS4_ACL_EXTATTR_NAMESPACE,
+	    NFS4_ACL_EXTATTR_NAME, ap->a_nentries * sizeof(ace_t),
+	    (char *)ap->a_aclp, ap->a_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 != 0)
+		return (error);
+
+	/*
+	 * Now that the EA is successfully updated, update the
+	 * inode and mark it as changed.
+	 */
+	ufs_sync_inode_from_nfs4acl(ap->a_aclp, ap->a_nentries, ip);
+	ip->i_flag |= IN_CHANGE;
+
+	VN_KNOTE_UNLOCKED(ap->a_vp, NOTE_ATTRIB);
+	return (0);
+}
+
 #endif /* !UFS_ACL */

==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_vnops.c#2 (text+ko) ====

@@ -2102,6 +2102,14 @@
 		*ap->a_retval = 0;
 #endif
 		break;
+
+	case _ACL_ACE_ENABLED:
+		if (ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS)
+			*ap->a_retval = 1;
+		else
+			*ap->a_retval = 0;
+		break;
+
 	case _PC_ACL_PATH_MAX:
 #ifdef UFS_ACL
 		if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS)
@@ -2466,6 +2474,9 @@
 	.vop_setacl =		ufs_setacl,
 	.vop_aclcheck =		ufs_aclcheck,
 #endif
+	.vop_getace =		ufs_getace,
+	.vop_setace =		ufs_setace,
+	.vop_getacecnt =	ufs_getacecnt,
 };
 
 struct vop_vector ufs_fifoops = {
@@ -2494,4 +2505,7 @@
 	.vop_setacl =		ufs_setacl,
 	.vop_aclcheck =		ufs_aclcheck,
 #endif
+	.vop_getace =		ufs_getace,
+	.vop_setace =		ufs_setace,
+	.vop_getacecnt =	ufs_getacecnt,
 };



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200805241851.m4OIpCnK076739>