Whamcloud - gitweb
Implementation of NFS-like root squash capability.
authordeen <deen>
Wed, 5 Dec 2007 20:37:01 +0000 (20:37 +0000)
committerdeen <deen>
Wed, 5 Dec 2007 20:37:01 +0000 (20:37 +0000)
b=12749
i=adilger
i=johann

lustre/ChangeLog
lustre/include/obd.h
lustre/mds/handler.c
lustre/mds/lproc_mds.c
lustre/mds/mds_internal.h
lustre/mds/mds_lib.c

index f8a6f89..0b7e5a8 100644 (file)
@@ -126,6 +126,13 @@ Details    : When CRAY_XT3 is defined, the fsgid supplied by the client is
             whereas the supplied fsgid can be trusted if it is in the list of
             supplementary groups returned by the group upcall.
 
+Severity   : normal
+Bugzilla   : 12749
+Description: Root Squash Functionality
+Details    : Implementation of NFS-like root squash capability. Specifically,
+             don't allow someone with root access on a client node to be able
+             to manipulate files owned by root on a server node.
+
 --------------------------------------------------------------------------------
 
 2007-10-26         Cluster File Systems, Inc. <info@clusterfs.com>
index b9cc606..9f2f444 100644 (file)
@@ -467,6 +467,10 @@ struct mds_obd {
                                          mds_fl_cfglog:1,
                                          mds_fl_synced:1,
                                          mds_evict_ost_nids:1;
+
+        uid_t                            mds_squash_uid;
+        gid_t                            mds_squash_gid;
+        lnet_nid_t                       mds_nosquash_nid;
 };
 
 struct echo_obd {
index e863c39..e00d413 100644 (file)
@@ -1293,6 +1293,11 @@ int mds_reint(struct ptlrpc_request *req, int offset,
                 GOTO(out, req->rq_status = -EINVAL);
         }
 
+        mds_root_squash(&req->rq_export->exp_obd->u.mds, &req->rq_peer.nid,
+                        &rec->ur_uc.luc_fsuid, &rec->ur_uc.luc_fsgid,
+                        &rec->ur_uc.luc_cap, &rec->ur_uc.luc_suppgid1,
+                        &rec->ur_uc.luc_suppgid2);
+
         /* rc will be used to interrupt a for loop over multiple records */
         rc = mds_reint_rec(rec, offset, req, lockh);
  out:
index d932c97..768aa80 100644 (file)
@@ -305,6 +305,93 @@ static int lprocfs_rd_atime_diff(char *page, char **start, off_t off,
         return snprintf(page, count, "%lu\n", mds->mds_atime_diff);
 }
 
+static int lprocfs_wr_rootsquash(struct file *file, const char *buffer,
+                                 unsigned long count, void *data)
+{
+        struct obd_device *obd = data;
+        struct mds_obd *mds = &obd->u.mds;
+        char kernbuf[50], *tmp, *end;
+        unsigned long uid, gid;
+
+        if (count > (sizeof(kernbuf) - 1))
+                return -EINVAL;
+
+        if (copy_from_user(kernbuf, buffer, count))
+                return -EFAULT;
+
+        kernbuf[count] = '\0';
+
+        uid = simple_strtoul(kernbuf, &tmp, 0);
+        if (kernbuf == tmp) {
+                if (tmp[0] != ':')
+                        return -EINVAL;
+                uid = mds->mds_squash_uid;
+        }
+        /* skip ':' */
+        tmp++;
+        gid = simple_strtoul(tmp, &end, 0);
+        if (tmp == end)
+                gid = mds->mds_squash_gid;
+
+        mds->mds_squash_uid = uid;
+        mds->mds_squash_gid = gid;
+        return count;
+}
+
+static int lprocfs_rd_rootsquash(char *page, char **start, off_t off,
+                                 int count, int *eof, void *data)
+{
+        struct obd_device *obd = data;
+        struct mds_obd *mds = &obd->u.mds;
+
+        *eof = 1;
+        return snprintf(page, count, "%lu:%lu\n",
+                        (unsigned long)mds->mds_squash_uid,
+                        (unsigned long)mds->mds_squash_gid);
+}
+
+static int lprocfs_wr_nosquash_nid(struct file *file, const char *buffer,
+                                   unsigned long count, void *data)
+{
+        struct obd_device *obd = data;
+        struct mds_obd *mds = &obd->u.mds;
+        char kernbuf[30], *start, *end;
+
+        if (count > (sizeof(kernbuf) - 1))
+                return -EINVAL;
+
+        if (copy_from_user(kernbuf, buffer, count))
+                return -EFAULT;
+        kernbuf[count] = '\0';
+
+        /* strip frontal whitespaces */
+        start = kernbuf;
+        while (*start && isspace(*start))
+                start++;
+        /* EOL - string doesn't contain NID */
+        if (*start == '\0')
+                return -EINVAL;
+        /* strip backward whitespaces */
+        end = kernbuf + count - 1;
+        while (*end && isspace(*end))
+                end--;
+        *(end + 1) = '\0';
+
+        mds->mds_nosquash_nid = libcfs_str2nid(start);
+        return count;
+}
+
+static int lprocfs_rd_nosquash_nid(char *page, char **start, off_t off,
+                                   int count, int *eof, void *data)
+{
+        struct obd_device *obd = data;
+        struct mds_obd *mds = &obd->u.mds;
+
+        *eof = 1;
+        return snprintf(page, count, "%s\n",
+                        libcfs_nid2str(mds->mds_nosquash_nid));
+}
+
 struct lprocfs_vars lprocfs_mds_obd_vars[] = {
         { "uuid",            lprocfs_rd_uuid,        0, 0 },
         { "blocksize",       lprocfs_rd_blksize,     0, 0 },
@@ -336,6 +423,10 @@ struct lprocfs_vars lprocfs_mds_obd_vars[] = {
         { "group_flush",     0, lprocfs_wr_group_flush, 0},
         { "group_info",      0, lprocfs_wr_group_info, 0 },
         { "atime_diff",      lprocfs_rd_atime_diff, lprocfs_wr_atime_diff, 0 },
+        { "rootsquash",      lprocfs_rd_rootsquash,
+                             lprocfs_wr_rootsquash, 0 },
+        { "nosquash_nid",    lprocfs_rd_nosquash_nid,
+                             lprocfs_wr_nosquash_nid, 0 },
         { 0 }
 };
 
index afc27ac..dc71c45 100644 (file)
@@ -174,6 +174,9 @@ int mds_update_unpack(struct ptlrpc_request *, int offset,
 int mds_init_ucred(struct lvfs_ucred *ucred, struct ptlrpc_request *req,
                    int offset);
 void mds_exit_ucred(struct lvfs_ucred *ucred, struct mds_obd *obd);
+void mds_root_squash(struct mds_obd *mds, lnet_nid_t *peernid,
+                     __u32 *fsuid, __u32 *fsgid, __u32 *cap,
+                     __u32 *suppgid, __u32 *suppgid2);
 
 /* mds/mds_unlink_open.c */
 int mds_osc_destroy_orphan(struct obd_device *obd, umode_t mode,
index 640d11e..f613465 100644 (file)
@@ -428,6 +428,28 @@ int mds_update_unpack(struct ptlrpc_request *req, int offset,
         RETURN(rc);
 }
 
+void mds_root_squash(struct mds_obd *mds, lnet_nid_t *peernid,
+                     __u32 *fsuid, __u32 *fsgid, __u32 *cap,
+                     __u32 *suppgid, __u32 *suppgid2)
+{
+        if (!mds->mds_squash_uid || *fsuid)
+               return;
+
+        if (*peernid == mds->mds_nosquash_nid)
+                return;
+
+        CDEBUG(D_OTHER, "squash req from %s, (%d:%d/%x)=>(%d:%d/%x)\n",
+               libcfs_nid2str(*peernid), *fsuid, *fsgid, *cap,
+               mds->mds_squash_uid, mds->mds_squash_gid, 0);
+
+        *fsuid = mds->mds_squash_uid;
+        *fsgid = mds->mds_squash_gid;
+        *cap = 0;
+        *suppgid = -1;
+        if (suppgid2)
+                *suppgid2 = -1;
+}
+
 int mds_init_ucred(struct lvfs_ucred *ucred, struct ptlrpc_request *req,
                    int offset)
 {
@@ -446,6 +468,10 @@ int mds_init_ucred(struct lvfs_ucred *ucred, struct ptlrpc_request *req,
         } else
 #endif
         {
+                mds_root_squash(mds, &req->rq_peer.nid, &body->fsuid,
+                                &body->fsgid, &body->capability,
+                                &body->suppgid, NULL);
+
                 ucred->luc_fsuid = body->fsuid;
                 ucred->luc_fsgid = body->fsgid;
                 ucred->luc_cap = body->capability;