From: vs Date: Thu, 27 Nov 2008 02:12:20 +0000 (+0000) Subject: Branch HEAD X-Git-Tag: v1_9_120~58 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=e826cd5f673b4e4efd66e1a01f3327f5754f6307 Branch HEAD b=12749 i=nathan,deen Third of three patches for the root squash feature map root UID/GID to UID/GID set via configuration parameter root_squash with the exception for NID range set via configuration parameter nosquash_nids --- diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 9b1a226..a4dd44c 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -1831,6 +1831,17 @@ Details : Mounting a filesystem with extents feature will fail on big-endian systems since ext3-based ldiskfs is not supported on big-endian systems. This can be over-riden with "bigendian_extents" mount option. +Severity : enhancement +Bugzilla : 12749 +Description: The root squash functionality +Details : A security feature, which is to prevent users from being able + to mount lustre on their desktop, run as root, and delete + all of the files in the filesystem. The goal is accomplished by + remapping user id (UID) and group id (GID) of the root user to + a UID and GID specified by the system administartor via Lustre + configuration management server (MGS). The functionality also + allows to specify sets of clients for which the remapping does + not apply. -------------------------------------------------------------------------------- 2007-08-10 Cluster File Systems, Inc. diff --git a/lustre/include/lustre_disk.h b/lustre/include/lustre_disk.h index e9b15b8..5049532 100644 --- a/lustre/include/lustre_disk.h +++ b/lustre/include/lustre_disk.h @@ -63,6 +63,7 @@ #define LDD_F_SV_TYPE_MDT 0x0001 #define LDD_F_SV_TYPE_OST 0x0002 #define LDD_F_SV_TYPE_MGS 0x0004 +#define LDD_F_SV_ALL 0x0008 /** need an index assignment */ #define LDD_F_NEED_INDEX 0x0010 /** never registered */ @@ -138,9 +139,10 @@ static inline int server_make_name(__u32 flags, __u16 index, char *fs, char *name) { if (flags & (LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST)) { - sprintf(name, "%.8s-%s%04x", fs, - (flags & LDD_F_SV_TYPE_MDT) ? "MDT" : "OST", - index); + if (!(flags & LDD_F_SV_ALL)) + sprintf(name, "%.8s-%s%04x", fs, + (flags & LDD_F_SV_TYPE_MDT) ? "MDT" : "OST", + index); } else if (flags & LDD_F_SV_TYPE_MGS) { sprintf(name, "MGS"); } else { diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 4e8333b..1a5b7f7 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -4194,6 +4194,13 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m) d->ld_obd->obd_namespace = m->mdt_namespace = NULL; } + cfs_free_nidlist(&m->mdt_nosquash_nids); + if (m->mdt_nosquash_str) { + OBD_FREE(m->mdt_nosquash_str, m->mdt_nosquash_strlen); + m->mdt_nosquash_str = NULL; + m->mdt_nosquash_strlen = 0; + } + mdt_seq_fini(env, m); mdt_seq_fini_cli(m); mdt_fld_fini(env, m); @@ -4368,6 +4375,12 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m, m->mdt_capa_timeout = CAPA_TIMEOUT; m->mdt_capa_alg = CAPA_HMAC_ALG_SHA1; m->mdt_ck_timeout = CAPA_KEY_TIMEOUT; + m->mdt_squash_uid = 0; + m->mdt_squash_gid = 0; + CFS_INIT_LIST_HEAD(&m->mdt_nosquash_nids); + m->mdt_nosquash_str = NULL; + m->mdt_nosquash_strlen = 0; + init_rwsem(&m->mdt_squash_sem); spin_lock_init(&m->mdt_client_bitmap_lock); diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index ae204a9..c8f215c 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -175,6 +175,14 @@ struct mdt_device { struct lustre_capa_key mdt_capa_keys[2]; unsigned int mdt_capa_conf:1; + /* root squash */ + uid_t mdt_squash_uid; + gid_t mdt_squash_gid; + struct list_head mdt_nosquash_nids; + char *mdt_nosquash_str; + int mdt_nosquash_strlen; + struct rw_semaphore mdt_squash_sem; + cfs_proc_dir_entry_t *mdt_proc_entry; struct lprocfs_stats *mdt_stats; int mdt_sec_level; diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index fadd75d..973571e 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -53,6 +53,7 @@ #define DEBUG_SUBSYSTEM S_MDS #include "mdt_internal.h" +#include typedef enum ucred_init_type { @@ -81,11 +82,48 @@ void mdt_exit_ucred(struct mdt_thread_info *info) } } -/* XXX: root_squash will be redesigned in Lustre 1.7. - * Do not root_squash for inter-MDS operations */ -static int mdt_root_squash(struct mdt_thread_info *info) +static int match_nosquash_list(struct rw_semaphore *sem, + struct list_head *nidlist, + lnet_nid_t peernid) { - return 0; + int rc; + ENTRY; + down_read(sem); + rc = cfs_match_nid(peernid, nidlist); + up_read(sem); + RETURN(rc); +} + +/* root_squash for inter-MDS operations */ +static int mdt_root_squash(struct mdt_thread_info *info, lnet_nid_t peernid) +{ + struct md_ucred *ucred = mdt_ucred(info); + ENTRY; + + if (!info->mti_mdt->mdt_squash_uid || ucred->mu_fsuid) + RETURN(0); + + if (match_nosquash_list(&info->mti_mdt->mdt_squash_sem, + &info->mti_mdt->mdt_nosquash_nids, + peernid)) { + CDEBUG(D_OTHER, "%s is in nosquash_nids list\n", + libcfs_nid2str(peernid)); + RETURN(0); + } + + CDEBUG(D_OTHER, "squash req from %s, (%d:%d/%x)=>(%d:%d/%x)\n", + libcfs_nid2str(peernid), + ucred->mu_fsuid, ucred->mu_fsgid, ucred->mu_cap, + info->mti_mdt->mdt_squash_uid, info->mti_mdt->mdt_squash_gid, + 0); + + ucred->mu_fsuid = info->mti_mdt->mdt_squash_uid; + ucred->mu_fsgid = info->mti_mdt->mdt_squash_gid; + ucred->mu_cap = 0; + ucred->mu_suppgids[0] = -1; + ucred->mu_suppgids[1] = -1; + + RETURN(0); } static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, @@ -237,8 +275,8 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, ucred->mu_fsuid = pud->pud_fsuid; ucred->mu_fsgid = pud->pud_fsgid; - /* XXX: need to process root_squash here. */ - mdt_root_squash(info); + /* process root_squash here. */ + mdt_root_squash(info, peernid); /* remove fs privilege for non-root user. */ if (ucred->mu_fsuid) @@ -403,8 +441,8 @@ static int old_init_ucred(struct mdt_thread_info *info, } uc->mu_identity = identity; - /* XXX: need to process root_squash here. */ - mdt_root_squash(info); + /* process root_squash here. */ + mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); /* remove fs privilege for non-root user. */ if (uc->mu_fsuid) @@ -443,8 +481,8 @@ static int old_init_ucred_reint(struct mdt_thread_info *info) } uc->mu_identity = identity; - /* XXX: need to process root_squash here. */ - mdt_root_squash(info); + /* process root_squash here. */ + mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); /* remove fs privilege for non-root user. */ if (uc->mu_fsuid) diff --git a/lustre/mdt/mdt_lproc.c b/lustre/mdt/mdt_lproc.c index 37c1375..3ac423a 100644 --- a/lustre/mdt/mdt_lproc.c +++ b/lustre/mdt/mdt_lproc.c @@ -66,6 +66,7 @@ #include #include #include "mdt_internal.h" +#include static const char *mdt_proc_names[LPROC_MDT_NR] = { }; @@ -481,6 +482,171 @@ static int lprocfs_wr_cos(struct file *file, const char *buffer, return count; } +static int lprocfs_rd_root_squash(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct obd_device *obd = data; + struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); + ENTRY; + + return snprintf(page, count, "%u:%u\n", mdt->mdt_squash_uid, + mdt->mdt_squash_gid); +} + +static int safe_strtoul(const char *str, char **endp, unsigned long *res) +{ + char n[24]; + + *res = simple_strtoul(str, endp, 0); + if (str == *endp) + return 1; + + sprintf(n, "%lu", *res); + if (strncmp(n, str, *endp - str)) + /* overflow */ + return 1; + return 0; +} + +static int lprocfs_wr_root_squash(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct obd_device *obd = data; + struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); + char kernbuf[50], *tmp, *end; + unsigned long uid, gid; + int nouid, nogid; + ENTRY; + + if (count > (sizeof(kernbuf) - 1) || + copy_from_user(kernbuf, buffer, count)) { + CWARN("%s: can't copy string to kernel space, " + "uid:gid is expected, " + "continue with %u:%u, " + "there will be 0:0 on MDS restart\n", + obd->obd_name, mdt->mdt_squash_uid, + mdt->mdt_squash_gid); + RETURN(count); + } + + if (copy_from_user(kernbuf, buffer, count)) + RETURN(-EFAULT); + + kernbuf[count] = '\0'; + + nouid = nogid = 0; + if (safe_strtoul(buffer, &tmp, &uid)) { + uid = mdt->mdt_squash_uid; + nouid = 1; + } + + /* skip ':' */ + if (*tmp == ':') { + tmp++; + if (safe_strtoul(tmp, &end, &gid)) { + gid = mdt->mdt_squash_gid; + nogid = 1; + } + } else { + gid = mdt->mdt_squash_gid; + nogid = 1; + } + + mdt->mdt_squash_uid = uid; + mdt->mdt_squash_gid = gid; + + if (nouid || nogid) + CWARN("%s: can't parse \"\%s\", uid:gid is expected, " + "continue with %u:%u, " + "there will be %u:%u on MDS restart\n", + obd->obd_name, + buffer, mdt->mdt_squash_uid, mdt->mdt_squash_gid, + nouid ? 0 : mdt->mdt_squash_uid, + nogid ? 0 : mdt->mdt_squash_gid); + else + LCONSOLE_INFO("%s: root_squash is set to %u:%u\n", + obd->obd_name, + mdt->mdt_squash_uid, mdt->mdt_squash_gid); + RETURN(count); +} + +static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct obd_device *obd = data; + struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); + + if (mdt->mdt_nosquash_str) + return snprintf(page, count, "%s\n", mdt->mdt_nosquash_str); + return snprintf(page, count, "NONE\n"); +} + +static int lprocfs_wr_nosquash_nids(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct obd_device *obd = data; + struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); + int rc; + char *new; + struct list_head tmp; + ENTRY; + + /* copy to kernel space */ + OBD_ALLOC(new, count + 1); + if (new == 0) + GOTO(failed, rc = -ENOMEM); + + if (copy_from_user(new, buffer, count)) + GOTO(failed, rc = -EFAULT); + + new[count] = 0; + if (strlen(new) != count) + GOTO(failed, rc = -EINVAL); + + if (!strcmp(new, "NONE") || !strcmp(new, "clear")) { + /* empty string is special case */ + down_write(&mdt->mdt_squash_sem); + if (!list_empty(&mdt->mdt_nosquash_nids)) { + cfs_free_nidlist(&mdt->mdt_nosquash_nids); + OBD_FREE(mdt->mdt_nosquash_str, + mdt->mdt_nosquash_strlen); + mdt->mdt_nosquash_str = NULL; + mdt->mdt_nosquash_strlen = 0; + } + up_write(&mdt->mdt_squash_sem); + LCONSOLE_INFO("%s: nosquash_nids is cleared\n", + obd->obd_name); + OBD_FREE(new, count + 1); + RETURN(0); + } + + CFS_INIT_LIST_HEAD(&tmp); + if (cfs_parse_nidlist(new, count, &tmp) <= 0) + GOTO(failed, rc = -EINVAL); + + down_write(&mdt->mdt_squash_sem); + if (!list_empty(&mdt->mdt_nosquash_nids)) { + cfs_free_nidlist(&mdt->mdt_nosquash_nids); + OBD_FREE(mdt->mdt_nosquash_str, mdt->mdt_nosquash_strlen); + } + mdt->mdt_nosquash_str = new; + mdt->mdt_nosquash_strlen = count + 1; + list_splice(&tmp, &mdt->mdt_nosquash_nids); + + LCONSOLE_INFO("%s: nosquash_nids is set to %s\n", obd->obd_name, new); + up_write(&mdt->mdt_squash_sem); + RETURN(count); + + failed: + CWARN("%s: failed to set nosquash_nids (rc %d), " + "on MDS restart we will try to set it again, " + "continue with current nosquash_nids\n", + obd->obd_name, rc); + if (new) + OBD_FREE(new, count + 1); + RETURN(count); +} + static struct lprocfs_vars lprocfs_mdt_obd_vars[] = { { "uuid", lprocfs_rd_uuid, 0, 0 }, { "recovery_status", lprocfs_obd_rd_recovery_status, 0, 0 }, @@ -506,6 +672,10 @@ static struct lprocfs_vars lprocfs_mdt_obd_vars[] = { { "sec_level", lprocfs_rd_sec_level, lprocfs_wr_sec_level, 0 }, { "commit_on_sharing", lprocfs_rd_cos, lprocfs_wr_cos, 0 }, + { "root_squash", lprocfs_rd_root_squash, + lprocfs_wr_root_squash, 0 }, + { "nosquash_nids", lprocfs_rd_nosquash_nids, + lprocfs_wr_nosquash_nids, 0 }, { 0 } }; diff --git a/lustre/mgs/mgs_llog.c b/lustre/mgs/mgs_llog.c index 72ea751..89dcf26 100644 --- a/lustre/mgs/mgs_llog.c +++ b/lustre/mgs/mgs_llog.c @@ -2428,9 +2428,50 @@ static int mgs_write_log_param(struct obd_device *obd, struct fs_db *fsdb, GOTO(end, rc); } - /* All mdt., ost. params in proc */ - if ((class_match_param(ptr, PARAM_MDT, NULL) == 0) || - (class_match_param(ptr, PARAM_MDD, NULL) == 0) || + /* All mdt. params in proc */ + if (class_match_param(ptr, PARAM_MDT, NULL) == 0) { + char mdt_index[16]; + int i; + __u32 idx; + + CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4); + if (strncmp(mti->mti_svname, mti->mti_fsname, + MTI_NAME_MAXLEN) == 0) + /* device is unspecified completely? */ + rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL; + else + rc = server_name2index(mti->mti_svname, &idx, NULL); + if (rc < 0) + goto active_err; + if ((rc & LDD_F_SV_TYPE_MDT) == 0) + goto active_err; + if (rc & LDD_F_SV_ALL) { + for (i = 0; i < INDEX_MAP_SIZE * 8; i++) { + if (!test_bit(i, + fsdb->fsdb_mdt_index_map)) + continue; + sprintf(mdt_index,"-MDT%04x", i); + name_create(&logname, mti->mti_fsname, + mdt_index); + rc = mgs_wlp_lcfg(obd, fsdb, mti, + logname, &bufs, + logname, ptr); + name_destroy(&logname); + if (rc) + goto active_err; + } + } else { + rc = mgs_wlp_lcfg(obd, fsdb, mti, + mti->mti_svname, &bufs, + mti->mti_svname, ptr); + if (rc) + goto active_err; + } + GOTO(end, rc); + } + + /* All mdd., ost. params in proc */ + if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) || (class_match_param(ptr, PARAM_OST, NULL) == 0)) { CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4); if (mgs_log_is_empty(obd, mti->mti_svname)) diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index be853c9..d6e7222 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -1683,6 +1683,8 @@ int server_name2index(char *svname, __u32 *idx, char **endptr) rc = LDD_F_SV_TYPE_OST; else return(-EINVAL); + if (strcmp(dash + 4, "all") == 0) + return rc | LDD_F_SV_ALL; index = simple_strtoul(dash + 4, endptr, 16); *idx = index;