From 22bc0797bed34dfae932104ea65fb85ed249043d Mon Sep 17 00:00:00 2001 From: deen Date: Wed, 5 Dec 2007 20:37:01 +0000 Subject: [PATCH] Implementation of NFS-like root squash capability. b=12749 i=adilger i=johann --- lustre/ChangeLog | 7 ++++ lustre/include/obd.h | 4 +++ lustre/mds/handler.c | 5 +++ lustre/mds/lproc_mds.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++ lustre/mds/mds_internal.h | 3 ++ lustre/mds/mds_lib.c | 26 ++++++++++++++ 6 files changed, 136 insertions(+) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index f8a6f89..0b7e5a8 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -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. diff --git a/lustre/include/obd.h b/lustre/include/obd.h index b9cc606..9f2f444 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -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 { diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index e863c39..e00d413 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -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: diff --git a/lustre/mds/lproc_mds.c b/lustre/mds/lproc_mds.c index d932c97..768aa80 100644 --- a/lustre/mds/lproc_mds.c +++ b/lustre/mds/lproc_mds.c @@ -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 } }; diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index afc27ac..dc71c45 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -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, diff --git a/lustre/mds/mds_lib.c b/lustre/mds/mds_lib.c index 640d11e..f613465 100644 --- a/lustre/mds/mds_lib.c +++ b/lustre/mds/mds_lib.c @@ -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; -- 1.8.3.1