Source-Changes-HG archive

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

[src/trunk]: src/lib/libperfuse - set user/group ownership after object creat...



details:   https://anonhg.NetBSD.org/src/rev/b02559becfee
branches:  trunk
changeset: 757397:b02559becfee
user:      manu <manu%NetBSD.org@localhost>
date:      Sat Aug 28 03:46:21 2010 +0000

description:
- set user/group ownership after object creation.

- enforce permissios checks. This needs to be  reviewed.

diffstat:

 lib/libperfuse/ops.c     |  208 ++++++++++++++++++++++++++++++++++++++++++++--
 lib/libperfuse/perfuse.c |    3 +-
 2 files changed, 200 insertions(+), 11 deletions(-)

diffs (truncated from 404 to 300 lines):

diff -r 831b1edce803 -r b02559becfee lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c      Fri Aug 27 18:31:18 2010 +0000
+++ b/lib/libperfuse/ops.c      Sat Aug 28 03:46:21 2010 +0000
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.3 2010/08/27 09:58:17 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.4 2010/08/28 03:46:21 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -41,6 +41,7 @@
 #include "perfuse_priv.h"
 #include "fuse.h"
 
+static int no_access(puffs_cookie_t, const struct puffs_cred *, mode_t);
 static void fuse_attr_to_vap(struct perfuse_state *,
     struct vattr *, struct fuse_attr *);
 static int node_lookup_dir_nodot(struct puffs_usermount *,
@@ -48,7 +49,8 @@
 static int node_lookup_common(struct puffs_usermount *, puffs_cookie_t, 
     const char*, struct puffs_node **);
 static int node_mk_common(struct puffs_usermount *, puffs_cookie_t,
-    struct puffs_newinfo *, perfuse_msg_t *);
+    struct puffs_newinfo *, const struct puffs_cn *pcn,
+    const struct vattr *, perfuse_msg_t *);
 static const char *basename_r(const char *);
 static ssize_t fuse_to_dirent(struct puffs_usermount *, puffs_cookie_t,
     struct fuse_dirent *, size_t);
@@ -90,6 +92,23 @@
 #define VTTOIF(indx) (vttoif_tab[(int)(indx)])
 
 
+static int
+no_access(opc, pcr, mode)
+       puffs_cookie_t opc;
+       const struct puffs_cred *pcr;
+       mode_t mode;
+{
+       struct puffs_node *pn;
+       struct vattr *va;
+
+       pn = (struct puffs_node *)opc;
+       va = puffs_pn_getvap(pn);
+
+       return puffs_access(va->va_type, va->va_mode, 
+                           va->va_uid, va->va_gid,
+                           mode, pcr);
+}
+
 static void
 fuse_attr_to_vap(ps, vap, fa)
        struct perfuse_state *ps;
@@ -222,15 +241,18 @@
  * perfuse_node_symlink
  */
 static int
-node_mk_common(pu, opc, pni, pm)
+node_mk_common(pu, opc, pni, pcn, vap, pm)
        struct puffs_usermount *pu;
        puffs_cookie_t opc;
        struct puffs_newinfo *pni;
+       const struct puffs_cn *pcn;
+       const struct vattr *vap;
        perfuse_msg_t *pm;
 {
        struct perfuse_state *ps;
        struct puffs_node *pn;
        struct fuse_entry_out *feo;
+       struct fuse_setattr_in *fsi;
        int error;
 
        ps =  puffs_getspecific(pu);
@@ -247,6 +269,25 @@
 
        fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
        puffs_newinfo_setcookie(pni, pn);
+       ps->ps_destroy_msg(pm);
+ 
+       /* 
+        * Set owner and group
+        */
+       (void)puffs_cred_getuid(pcn->pcn_cred, &pn->pn_va.va_uid);
+       (void)puffs_cred_getgid(pcn->pcn_cred, &pn->pn_va.va_gid);
+
+       pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, 
+                           FUSE_SETATTR, sizeof(*fsi), NULL);
+       fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in);
+       fsi->uid = pn->pn_va.va_uid;
+       fsi->gid = pn->pn_va.va_gid;
+       fsi->valid = FUSE_FATTR_UID|FUSE_FATTR_GID;
+
+       /*
+        * A fuse_attr_out is returned, but we ignore it.
+        */
+       error = XCHG_MSG(ps, pu, pm, sizeof(struct fuse_attr_out));
 
 out:
        ps->ps_destroy_msg(pm);
@@ -807,6 +848,12 @@
        int error;
        
        /*
+        * Create an object require -WX permission in the parent directory
+        */
+       if (no_access(opc, pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC))
+               return EACCES;
+
+       /*
         * If create is unimplemented: Check that it does not
         * already exists, and if not, do mknod and open
         */
@@ -888,6 +935,28 @@
        const char* path;
        size_t len;
        
+       /*
+        * Only superuser can mknod objects other than 
+        * directories, files, socks, fifo and links.
+        *
+        * Create an object require -WX permission in the parent directory
+        */
+       switch (vap->va_type) {
+       case VDIR:      /* FALLTHROUGH */
+       case VREG:      /* FALLTHROUGH */
+       case VFIFO:     /* FALLTHROUGH */
+       case VSOCK:     /* FALLTHROUGH */
+       case VLNK:
+               if (no_access(opc, pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC))
+                       return EACCES;
+               break;
+       default:        /* VNON, VBLK, VCHR, VBAD */
+               if (!puffs_cred_isjuggernaut(pcn->pcn_cred))
+                       return EACCES;
+               break;
+       }
+
+
        ps = puffs_getspecific(pu);
        path = basename_r((char *)PCNPATH(pcn));
        len = sizeof(*fmi) + strlen(path) + 1; 
@@ -899,7 +968,7 @@
        fmi->umask = 0;         /* Seems unused bu libfuse */
        (void)strlcpy((char *)(void *)(fmi + 1), path, len - sizeof(*fmi));
 
-       return node_mk_common(pu, opc, pni, pm);
+       return node_mk_common(pu, opc, pni, pcn, vap, pm);
 }
 
 
@@ -912,6 +981,7 @@
 {
        struct perfuse_state *ps;
        perfuse_msg_t *pm;
+       mode_t pmode;
        int op;
        struct fuse_open_in *foi;
        struct fuse_open_out *foo;
@@ -921,10 +991,28 @@
        ps = puffs_getspecific(pu);
 
        pn = (struct puffs_node *)opc;
-       if (puffs_pn_getvap(pn)->va_type == VDIR)
+       if (puffs_pn_getvap(pn)->va_type == VDIR) {
                op = FUSE_OPENDIR;
-       else
+               pmode = PUFFS_VREAD|PUFFS_VEXEC;
+       } else {
                op = FUSE_OPEN;
+               if (mode & (O_RDWR|O_WRONLY))
+                       pmode = PUFFS_VWRITE;
+               else
+                       pmode = PUFFS_VREAD;
+       }
+
+       /*
+        * Opening a directory require R-X on the directory
+        * Opening a file requires R-- for reading, -W- for writing
+        * In both cases, --X is required on the parent.
+        */
+       if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent,
+           pcr, PUFFS_VEXEC))
+               return EACCES;
+
+       if (no_access(opc, pcr, pmode))
+               return EACCES;
 
        /*
         * libfuse docs say O_CREAT should not be set.
@@ -1007,7 +1095,6 @@
 
        /*
         * Sync before close for files
-        * XXX no pcr argument to pass
         */
        if ((op == FUSE_RELEASE) && (pnd->pnd_flags & PND_DIRTY)) {
 #ifdef PERFUSE_DEBUG
@@ -1015,7 +1102,7 @@
                        DPRINTF("%s: SYNC opc = %p, file = \"%s\"\n", 
                                __func__, (void*)opc, (char *)PNPATH(pn));
 #endif
-               if ((error = perfuse_node_fsync(pu, opc, NULL, 0, 0, 0)) != 0)
+               if ((error = perfuse_node_fsync(pu, opc, pcr, 0, 0, 0)) != 0)
                        return error;
 
                pnd->pnd_flags &= ~PND_DIRTY;
@@ -1151,6 +1238,13 @@
        struct fuse_attr_out *fao;
        int error;
        
+       /*
+        * getattr requires --X on the parent directory
+        */
+       if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent,
+           pcr, PUFFS_VEXEC))
+               return EACCES;
+
        ps = puffs_getspecific(pu);
 
        /*
@@ -1196,7 +1290,51 @@
        struct perfuse_state *ps;
        struct fuse_setattr_in *fsi;
        int error;
+       struct vattr *old_va;
+
+       /*
+        * setattr requires --X on the parent directory
+        */
+       if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent,
+           pcr, PUFFS_VEXEC))
+               return EACCES;
+
+       old_va = puffs_pn_getvap((struct puffs_node *)opc);
+
+       /*
+        * Check for permission to change size
+        */
+       if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) &&
+           no_access(opc, pcr, PUFFS_VWRITE))
+               return EACCES;
+
+       /*
+        * Check for permission to change dates
+        */
+       if (((vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) ||
+            (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)) &&
+           (puffs_access_times(old_va->va_uid, old_va->va_gid,
+                               old_va->va_mode, 0, pcr) != 0))
+               return EACCES;
+
+       /*
+        * Check for permission to change owner and group
+        */
+       if (((vap->va_uid != (uid_t)PUFFS_VNOVAL) ||
+            (vap->va_gid != (gid_t)PUFFS_VNOVAL)) &&
+           (puffs_access_chown(old_va->va_uid, old_va->va_gid,
+                               vap->va_uid, vap->va_gid, pcr)) != 0)
+               return EACCES;
+
+       /*
+        * Check for permission to change permissions
+        */
+       if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
+           (puffs_access_chmod(old_va->va_uid, old_va->va_gid,
+                                old_va->va_type, vap->va_mode, pcr)) != 0)
+               return EACCES;
        
+
        ps = puffs_getspecific(pu);
 
        pm = ps->ps_new_msg(pu, opc, FUSE_SETATTR, sizeof(*fsi), pcr);
@@ -1445,6 +1583,14 @@
        size_t len;
        int error;
        
+       /*
+        * remove requires -WX on the parent directory 
+        * no right required on the object.
+        */
+       if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent,
+           pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC))
+               return EACCES;
+
        ps = puffs_getspecific(pu);
 
        if (targ == NULL)
@@ -1493,6 +1639,13 @@
        struct fuse_link_in *fli;
        int error;
        
+       /*
+        * Create an object require -WX permission in the parent directory
+        */
+       if (no_access(opc, pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC))
+               return EACCES;
+
+
        ps = puffs_getspecific(pu);
        pn = (struct puffs_node *)targ;
        name = basename_r((char *)PCNPATH(pcn));
@@ -1533,6 +1686,13 @@



Home | Main Index | Thread Index | Old Index