vfs: add support for incoming faccessat(2) syscall
authorNicolas Thery <nthery@gmail.com>
Sat, 22 Aug 2009 22:37:44 +0000 (00:37 +0200)
committerNicolas Thery <nthery@gmail.com>
Sun, 23 Aug 2009 06:59:57 +0000 (08:59 +0200)
Add flags argument to vop_access and change vop_helper_access()
to check access against real or effective uid/gid depending on
AT_EACCESS presence in flags.

NOTE: nfs_access() may need to be changed too but I haven't yet
managed to figure out whether if should use real or effective uid
depending on AT_EACCESS.

Approved-by: dillon@, corecode@
sys/kern/vfs_helper.c
sys/kern/vfs_vopops.c
sys/sys/fcntl.h
sys/sys/vfsops.h

index 97310a6..c8343ff 100644 (file)
@@ -73,6 +73,16 @@ vop_helper_access(struct vop_access_args *ap, uid_t ino_uid, gid_t ino_gid,
        mode_t mask, mode = ap->a_mode;
        gid_t *gp;
        int i;
+       uid_t proc_uid;
+       gid_t proc_gid;
+
+       if (ap->a_flags & AT_EACCESS) {
+               proc_uid = cred->cr_uid;
+               proc_gid = cred->cr_gid;
+       } else {
+               proc_uid = cred->cr_ruid;
+               proc_gid = cred->cr_rgid;
+       }
 
        /*
         * Disallow write attempts on read-only filesystems;
@@ -98,13 +108,13 @@ vop_helper_access(struct vop_access_args *ap, uid_t ino_uid, gid_t ino_gid,
                return (EPERM);
 
        /* Otherwise, user id 0 always gets access. */
-       if (cred->cr_ruid == 0)
+       if (proc_uid == 0)
                return (0);
 
        mask = 0;
 
        /* Otherwise, check the owner. */
-       if (cred->cr_ruid == ino_uid) {
+       if (proc_uid == ino_uid) {
                if (mode & VEXEC)
                        mask |= S_IXUSR;
                if (mode & VREAD)
@@ -116,10 +126,10 @@ vop_helper_access(struct vop_access_args *ap, uid_t ino_uid, gid_t ino_gid,
 
        /* 
         * Otherwise, check the groups. 
-        * We must special-case the primary group to check against the
-        * real gid and not the effective one.
+        * We must special-case the primary group to, if needed, check against
+        * the real gid and not the effective one.
         */
-       if (cred->cr_rgid == ino_gid) {
+       if (proc_gid == ino_gid) {
                if (mode & VEXEC)
                        mask |= S_IXGRP;
                if (mode & VREAD)
index ec92b3e..951f61e 100644 (file)
@@ -259,7 +259,8 @@ vop_close(struct vop_ops *ops, struct vnode *vp, int fflag)
 }
 
 int
-vop_access(struct vop_ops *ops, struct vnode *vp, int mode, struct ucred *cred)
+vop_access(struct vop_ops *ops, struct vnode *vp, int mode, int flags,
+    struct ucred *cred)
 {
        struct vop_access_args ap;
        int error;
@@ -268,6 +269,7 @@ vop_access(struct vop_ops *ops, struct vnode *vp, int mode, struct ucred *cred)
        ap.a_head.a_ops = ops;
        ap.a_vp = vp;
        ap.a_mode = mode;
+       ap.a_flags = flags;
        ap.a_cred = cred;
 
        DO_OPS(ops, error, &ap, vop_access);
index cf7c9f8..bd49cf4 100644 (file)
 #define AT_FDCWD               0xFFFAFDCD      /* invalid file descriptor */
 #define AT_SYMLINK_NOFOLLOW    1
 #define AT_REMOVEDIR           2
+#define AT_EACCESS             4
 
 /*
  * Constants used for fcntl(2)
index 6d80f34..3cf9132 100644 (file)
@@ -138,7 +138,8 @@ struct vop_close_args {
 struct vop_access_args {
        struct vop_generic_args a_head;
        struct vnode *a_vp;
-       int a_mode;
+       int a_mode;                             /* V* bitmask */
+       int a_flags;                            /* AT_* bitmask */
        struct ucred *a_cred;
 };
 
@@ -732,7 +733,7 @@ int vop_old_mknod(struct vop_ops *ops, struct vnode *dvp,
 int vop_open(struct vop_ops *ops, struct vnode *vp, int mode,
                struct ucred *cred, struct file *file);
 int vop_close(struct vop_ops *ops, struct vnode *vp, int fflag);
-int vop_access(struct vop_ops *ops, struct vnode *vp, int mode,
+int vop_access(struct vop_ops *ops, struct vnode *vp, int mode, int flags,
                struct ucred *cred);
 int vop_getattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap);
 int vop_setattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap,
@@ -971,7 +972,9 @@ extern struct syslink_desc vop_nrename_desc;
 #define VOP_CLOSE(vp, fflag)                           \
        vop_close(*(vp)->v_ops, vp, fflag)
 #define VOP_ACCESS(vp, mode, cred)                     \
-       vop_access(*(vp)->v_ops, vp, mode, cred)
+       vop_access(*(vp)->v_ops, vp, mode, 0, cred)
+#define VOP_ACCESS_FLAGS(vp, mode, flags, cred)                \
+       vop_access(*(vp)->v_ops, vp, mode, flags, cred)
 #define VOP_GETATTR(vp, vap)                           \
        vop_getattr(*(vp)->v_ops, vp, vap)
 #define VOP_SETATTR(vp, vap, cred)                     \