Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/cddl/osnet Take a first whack at making zfs permiss...



details:   https://anonhg.NetBSD.org/src/rev/52e9ba28ba97
branches:  trunk
changeset: 782149:52e9ba28ba97
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Thu Oct 18 14:22:57 2012 +0000

description:
Take a first whack at making zfs permissions work.

zfs_access uses secpolicy_vnode_access, so it makes no sense for the
latter to call VOP_ACCESS!

Everything seems to return EACCES instead of EPERM, probably because
that's what kauth returns.  This should be fixed, but that may
require some nontrivial surgery to zfs's calls to secpolicy_*, which
is where kauth gets involved.

This commit imports some code from illumos to implement the routine
secpolicy_vnode_setattr.  This shouldn't be outside dist/, but for
now it is expedient to do so.  We ought to fix that, along with all
the other CDDL code outside dist/, when we next import a newer
version of zfs.

diffstat:

 external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c |   49 ++-
 external/cddl/osnet/sys/kern/policy.c                  |  228 +++++++++++++---
 external/cddl/osnet/sys/sys/policy.h                   |   47 +-
 3 files changed, 236 insertions(+), 88 deletions(-)

diffs (truncated from 492 to 300 lines):

diff -r 48e890f38f40 -r 52e9ba28ba97 external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c
--- a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c    Thu Oct 18 10:41:44 2012 +0000
+++ b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c    Thu Oct 18 14:22:57 2012 +0000
@@ -1422,7 +1422,8 @@
                 * Create a new file object and update the directory
                 * to reference it.
                 */
-               if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) {
+               error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr);
+               if (error) {
                        goto out;
                }
 
@@ -4779,22 +4780,34 @@
 static int
 zfs_netbsd_access(void *v)
 {
-       struct vop_access_args *ap = v;
+       struct vop_access_args /* {
+               struct vnode *a_vp;
+               int a_mode;
+               kauth_cred_t a_cred;
+       } */ *ap = v;
+       struct vnode *vp = ap->a_vp;
+       int mode = ap->a_mode;
+       mode_t zfs_mode = 0;
+       kauth_cred_t cred = ap->a_cred;
+       int error;
 
        /*
-        * ZFS itself only knowns about VREAD, VWRITE and VEXEC, the rest
-        * we have to handle by calling vaccess().
+        * XXX This is really random, especially the left shift by six,
+        * and it exists only because of randomness in zfs_unix_to_v4
+        * and zfs_zaccess_rwx in zfs_acl.c.
         */
-       if ((ap->a_mode & ~(VREAD|VWRITE|VEXEC)) != 0) {
-               vnode_t *vp = ap->a_vp;
-               znode_t *zp = VTOZ(vp);
-               znode_phys_t *zphys = zp->z_phys;
-
-               return (vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid,
-                   zphys->zp_gid, ap->a_mode, ap->a_cred));
-       }
-
-       return (zfs_access(ap->a_vp, ap->a_mode, 0, ap->a_cred, NULL));
+       if (mode & VREAD)
+               zfs_mode |= S_IROTH;
+       if (mode & VWRITE)
+               zfs_mode |= S_IWOTH;
+       if (mode & VEXEC)
+               zfs_mode |= S_IXOTH;
+       zfs_mode <<= 6;
+
+       KASSERT(VOP_ISLOCKED(vp));
+       error = zfs_access(vp, zfs_mode, 0, cred, NULL);
+
+       return (error);
 }
 
 static int
@@ -4849,13 +4862,19 @@
            NULL, NULL);
 
        /*
-        * Translate errors to match our namei insanity.
+        * Translate errors to match our namei insanity.  Also, if the
+        * caller wants to create an entry here, it's apparently our
+        * responsibility as lookup to make sure that's permissible.
+        * Go figure.
         */
        if (cnp->cn_flags & ISLASTCN) {
                switch (cnp->cn_nameiop) {
                case CREATE:
                case RENAME:
                        if (error == ENOENT) {
+                               error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred);
+                               if (error)
+                                       break;
                                error = EJUSTRETURN;
                                break;
                        }
diff -r 48e890f38f40 -r 52e9ba28ba97 external/cddl/osnet/sys/kern/policy.c
--- a/external/cddl/osnet/sys/kern/policy.c     Thu Oct 18 10:41:44 2012 +0000
+++ b/external/cddl/osnet/sys/kern/policy.c     Thu Oct 18 14:22:57 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: policy.c,v 1.3 2012/10/15 22:50:25 riastradh Exp $     */
+/*     $NetBSD: policy.c,v 1.4 2012/10/18 14:22:58 riastradh Exp $     */
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -55,6 +55,31 @@
  * SUCH DAMAGE.
  */
 
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, Joyent, Inc. All rights reserved.
+ */
+
 #include <sys/param.h>
 #include <sys/priv.h>
 #include <sys/vnode.h>
@@ -84,7 +109,7 @@
 }
 
 int
-secpolicy_fs_mount(kauth_cred_t cred, vnode_t *mvp, struct mount *vfsp)
+secpolicy_fs_mount(kauth_cred_t cred, struct vnode *mvp, struct mount *vfsp)
 {
 
        return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
@@ -113,7 +138,7 @@
 secpolicy_vnode_stky_modify(kauth_cred_t cred)
 {
 
-       return (EPERM);
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
 }
 
 int
@@ -125,80 +150,69 @@
 
 
 int
-secpolicy_vnode_owner(cred_t *cred, uid_t owner)
+secpolicy_vnode_owner(kauth_cred_t cred, uid_t owner)
 {
-       uid_t uid;
 
-       uid = crgetuid(cred);
-       
-       if (owner == uid)
-                return (0);
+       if (owner == kauth_cred_getuid(cred))
+               return (0);
 
-       return 0;
-//     return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
-//         KAUTH_REQ_SYSTEM_MOUNT_NEW, vfsp, NULL, NULL);
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
 }
 
 int
-secpolicy_vnode_access(kauth_cred_t cred, struct vnode *vp, uint64_t owner,
+secpolicy_vnode_access(kauth_cred_t cred, struct vnode *vp, uid_t owner,
     int mode)
 {
 
-       (void)owner;            /* XXX ignore? */
-       KASSERT(VOP_ISLOCKED(vp));
-       return VOP_ACCESS(vp, mode, cred);
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
 }
 
-/*
- * Check privileges for setting xvattr attributes
- */
 int
-secpolicy_xvattr(xvattr_t *xvap, uid_t owner, cred_t *cr, vtype_t vtype)
+secpolicy_xvattr(xvattr_t *xvap, uid_t owner, kauth_cred_t cred, vtype_t vtype)
 {
-/*     return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
-       KAUTH_REQ_SYSTEM_MOUNT_UPDATE, vfsp, NULL, NULL);*/
-       return 0;
+
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
 }
 
 int
 secpolicy_vnode_setid_retain(kauth_cred_t cred, boolean_t issuidroot __unused)
 {
 
-       return  (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL));
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
 }
 
 int
 secpolicy_vnode_setids_setgids(kauth_cred_t cred, gid_t gid)
 {
 
-       if (!groupmember(gid, cred))
-               return  (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
-                       NULL));
-       return (0);
+       if (groupmember(gid, cred))
+               return (0);
+
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
+}
+
+int
+secpolicy_vnode_chown(kauth_cred_t cred, boolean_t check_self)
+{
+
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
 }
 
 int
-secpolicy_vnode_chown(struct kauth_cred *cred, boolean_t check_self)
+secpolicy_vnode_create_gid(kauth_cred_t cred)
 {
 
-       return  (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
-               NULL));
-       /* return (priv_check_cred(cred, PRIV_VFS_CHOWN, 0)); */
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
 }
 
 int
-secpolicy_vnode_create_gid(struct kauth_cred *cred)
+secpolicy_vnode_setdac(kauth_cred_t cred, uid_t owner)
 {
 
-       return (EPERM);
-}
+       if (owner == kauth_cred_getuid(cred))
+               return (0);
 
-int
-secpolicy_vnode_setdac(struct kauth_cred *cred, uid_t owner)
-{
-
-       return 0;
-       /*return (priv_check_cred(cred, PRIV_VFS_ADMIN, 0));*/
+       return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
 }
 
 int
@@ -211,7 +225,7 @@
         * is not a member of. Both of these are allowed in jail(8).
         */
        if (vp->v_type != VDIR && (vap->va_mode & S_ISTXT)) {
-               if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0)
+               if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL))
                        return (EFTYPE);
        }
        /*
@@ -220,17 +234,131 @@
         */
        if ((vap->va_mode & S_ISGID) != 0)
                return (secpolicy_vnode_setids_setgids(cred, ovap->va_gid));
-       
+
        return (0);
 }
 
+/*
+ * XXX Copied from illumos.  Should not be here; should be under
+ * external/cddl/osnet/dist.  Not sure why it is even in illumos's
+ * policy.c rather than somewhere in vnode.c or something.
+ */
 int
 secpolicy_vnode_setattr(kauth_cred_t cred, struct vnode *vp, struct vattr *vap,
     const struct vattr *ovap, int flags,
-    int unlocked_access(void *, int, kauth_cred_t ), void *node)
+    int unlocked_access(void *, int, kauth_cred_t), void *node)
 {
+       int mask = vap->va_mask;
+       int error = 0;
+       boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
 
-       return 0;
+       if (mask & AT_SIZE) {
+               if (vp->v_type == VDIR) {
+                       error = EISDIR;
+                       goto out;
+               }
+
+               /*
+                * If ATTR_NOACLCHECK is set in the flags, then we don't
+                * perform the secondary unlocked_access() call since the
+                * ACL (if any) is being checked there.
+                */
+               if (skipaclchk == B_FALSE) {
+                       error = unlocked_access(node, VWRITE, cred);
+                       if (error)
+                               goto out;
+               }
+       }



Home | Main Index | Thread Index | Old Index