X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fptlrpc%2Fsec_config.c;h=630994afdb97579854c4a00f306fb45bb057fad7;hb=ea5df4799a3c6ca7f386303694d4440997d82d43;hp=e98c11da8a1aa054eadfc779959c3012321748e0;hpb=c27bfc3b78c13a164440f50c5de82aa4493235a9;p=fs%2Flustre-release.git diff --git a/lustre/ptlrpc/sec_config.c b/lustre/ptlrpc/sec_config.c index e98c11d..630994a 100644 --- a/lustre/ptlrpc/sec_config.c +++ b/lustre/ptlrpc/sec_config.c @@ -15,11 +15,7 @@ * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ @@ -27,7 +23,7 @@ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2014, Intel Corporation. + * Copyright (c) 2011, 2017, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -48,7 +44,7 @@ #include #include #include -#include +#include #include #include "ptlrpc_internal.h" @@ -241,14 +237,13 @@ EXPORT_SYMBOL(sptlrpc_parse_rule); void sptlrpc_rule_set_free(struct sptlrpc_rule_set *rset) { - LASSERT(rset->srs_nslot || - (rset->srs_nrule == 0 && rset->srs_rules == NULL)); + LASSERT(rset->srs_nslot || + (rset->srs_nrule == 0 && rset->srs_rules == NULL)); - if (rset->srs_nslot) { - OBD_FREE(rset->srs_rules, - rset->srs_nslot * sizeof(*rset->srs_rules)); - sptlrpc_rule_set_init(rset); - } + if (rset->srs_nslot) { + OBD_FREE_PTR_ARRAY(rset->srs_rules, rset->srs_nslot); + sptlrpc_rule_set_init(rset); + } } EXPORT_SYMBOL(sptlrpc_rule_set_free); @@ -267,19 +262,18 @@ int sptlrpc_rule_set_expand(struct sptlrpc_rule_set *rset) nslot = rset->srs_nslot + 8; - /* better use realloc() if available */ - OBD_ALLOC(rules, nslot * sizeof(*rset->srs_rules)); - if (rules == NULL) - return -ENOMEM; + /* better use realloc() if available */ + OBD_ALLOC_PTR_ARRAY(rules, nslot); + if (rules == NULL) + return -ENOMEM; - if (rset->srs_nrule) { - LASSERT(rset->srs_nslot && rset->srs_rules); - memcpy(rules, rset->srs_rules, - rset->srs_nrule * sizeof(*rset->srs_rules)); + if (rset->srs_nrule) { + LASSERT(rset->srs_nslot && rset->srs_rules); + memcpy(rules, rset->srs_rules, + rset->srs_nrule * sizeof(*rset->srs_rules)); - OBD_FREE(rset->srs_rules, - rset->srs_nslot * sizeof(*rset->srs_rules)); - } + OBD_FREE_PTR_ARRAY(rset->srs_rules, rset->srs_nslot); + } rset->srs_rules = rules; rset->srs_nslot = nslot; @@ -506,38 +500,7 @@ struct sptlrpc_conf { }; static struct mutex sptlrpc_conf_lock; -static struct list_head sptlrpc_confs; - -static inline int is_hex(char c) -{ - return ((c >= '0' && c <= '9') || - (c >= 'a' && c <= 'f')); -} - -static void target2fsname(const char *tgt, char *fsname, int buflen) -{ - const char *ptr; - int len; - - ptr = strrchr(tgt, '-'); - if (ptr) { - if ((strncmp(ptr, "-MDT", 4) != 0 && - strncmp(ptr, "-OST", 4) != 0) || - !is_hex(ptr[4]) || !is_hex(ptr[5]) || - !is_hex(ptr[6]) || !is_hex(ptr[7])) - ptr = NULL; - } - - /* if we didn't find the pattern, treat the whole string as fsname */ - if (ptr == NULL) - len = strlen(tgt); - else - len = ptr - tgt; - - len = min(len, buflen - 1); - memcpy(fsname, tgt, len); - fsname[len] = '\0'; -} +static LIST_HEAD(sptlrpc_confs); static void sptlrpc_conf_free_rsets(struct sptlrpc_conf *conf) { @@ -653,66 +616,86 @@ static int sptlrpc_conf_merge_rule(struct sptlrpc_conf *conf, * find one through the target name in the record inside conf_lock; * otherwise means caller already hold conf_lock. */ -static int __sptlrpc_process_config(struct lustre_cfg *lcfg, - struct sptlrpc_conf *conf) +static int __sptlrpc_process_config(char *target, const char *fsname, + struct sptlrpc_rule *rule, + struct sptlrpc_conf *conf) { - char *target, *param; - char fsname[MTI_NAME_MAXLEN]; - struct sptlrpc_rule rule; - int rc; - ENTRY; - - target = lustre_cfg_string(lcfg, 1); - if (target == NULL) { - CERROR("missing target name\n"); - RETURN(-EINVAL); - } - - param = lustre_cfg_string(lcfg, 2); - if (param == NULL) { - CERROR("missing parameter\n"); - RETURN(-EINVAL); - } - - CDEBUG(D_SEC, "processing rule: %s.%s\n", target, param); - - /* parse rule to make sure the format is correct */ - if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) { - CERROR("Invalid sptlrpc parameter: %s\n", param); - RETURN(-EINVAL); - } - param += sizeof(PARAM_SRPC_FLVR) - 1; + int rc; - rc = sptlrpc_parse_rule(param, &rule); - if (rc) - RETURN(-EINVAL); - - if (conf == NULL) { - target2fsname(target, fsname, sizeof(fsname)); + ENTRY; + if (!conf) { + if (!fsname) + return -ENODEV; mutex_lock(&sptlrpc_conf_lock); - conf = sptlrpc_conf_get(fsname, 0); - if (conf == NULL) { - CERROR("can't find conf\n"); - rc = -ENOMEM; - } else { - rc = sptlrpc_conf_merge_rule(conf, target, &rule); - } + conf = sptlrpc_conf_get(fsname, 0); + if (!conf) { + CERROR("can't find conf\n"); + rc = -ENOMEM; + } else { + rc = sptlrpc_conf_merge_rule(conf, target, rule); + } mutex_unlock(&sptlrpc_conf_lock); - } else { + } else { LASSERT(mutex_is_locked(&sptlrpc_conf_lock)); - rc = sptlrpc_conf_merge_rule(conf, target, &rule); - } + rc = sptlrpc_conf_merge_rule(conf, target, rule); + } - if (rc == 0) - conf->sc_modified++; + if (!rc) + conf->sc_modified++; - RETURN(rc); + RETURN(rc); } int sptlrpc_process_config(struct lustre_cfg *lcfg) { - return __sptlrpc_process_config(lcfg, NULL); + char fsname[MTI_NAME_MAXLEN]; + struct sptlrpc_rule rule; + char *target, *param; + int rc; + + print_lustre_cfg(lcfg); + + target = lustre_cfg_string(lcfg, 1); + if (!target) { + CERROR("missing target name\n"); + return -EINVAL; + } + + param = lustre_cfg_string(lcfg, 2); + if (!param) { + CERROR("missing parameter\n"); + return -EINVAL; + } + + /* parse rule to make sure the format is correct */ + if (strncmp(param, PARAM_SRPC_FLVR, + sizeof(PARAM_SRPC_FLVR) - 1) != 0) { + CERROR("Invalid sptlrpc parameter: %s\n", param); + return -EINVAL; + } + param += sizeof(PARAM_SRPC_FLVR) - 1; + + CDEBUG(D_SEC, "processing rule: %s.%s\n", target, param); + + /* + * Three types of targets exist for sptlrpc using conf_param + * 1. '_mgs' which targets mgc srpc settings. Treat it as + * as a special file system name. + * 2. target is a device which can be fsname-MDTXXXX or + * fsname-OSTXXXX. This can be verified by the function + * server_name2fsname. + * 3. If both above conditions are not meet then the target + * is a actual filesystem. + */ + if (server_name2fsname(target, fsname, NULL)) + strlcpy(fsname, target, sizeof(target)); + + rc = sptlrpc_parse_rule(param, &rule); + if (rc) + return rc; + + return __sptlrpc_process_config(target, fsname, &rule, NULL); } EXPORT_SYMBOL(sptlrpc_process_config); @@ -838,6 +821,14 @@ static void inline flavor_set_flags(struct sptlrpc_flavor *sf, if (fl_udesc && sf->sf_rpc != SPTLRPC_FLVR_NULL) sf->sf_flags |= PTLRPC_SEC_FL_UDESC; } + + /* Some flavors use a single uid (0) context */ + if (flvr_is_rootonly(sf->sf_rpc)) + sf->sf_flags |= PTLRPC_SEC_FL_ROOTONLY; + + /* User descriptor might need to be cleared */ + if (flvr_allows_user_desc(sf->sf_rpc) == 0) + sf->sf_flags &= ~PTLRPC_SEC_FL_UDESC; } void sptlrpc_conf_choose_flavor(enum lustre_sec_part from, @@ -851,7 +842,7 @@ void sptlrpc_conf_choose_flavor(enum lustre_sec_part from, char name[MTI_NAME_MAXLEN]; int len, rc = 0; - target2fsname(target->uuid, name, sizeof(name)); + obd_uuid2fsname(name, target->uuid, sizeof(name)); mutex_lock(&sptlrpc_conf_lock); @@ -913,16 +904,16 @@ void sptlrpc_conf_client_adapt(struct obd_device *obd) strcmp(obd->obd_type->typ_name, LUSTRE_LWP_NAME) == 0); CDEBUG(D_SEC, "obd %s\n", obd->u.cli.cl_target_uuid.uuid); - /* serialize with connect/disconnect import */ - down_read(&obd->u.cli.cl_sem); + /* serialize with connect/disconnect import */ + down_read_nested(&obd->u.cli.cl_sem, OBD_CLI_SEM_MDCOSC); imp = obd->u.cli.cl_import; if (imp) { - spin_lock(&imp->imp_lock); + write_lock(&imp->imp_sec_lock); if (imp->imp_sec) - imp->imp_sec_expire = cfs_time_current_sec() + + imp->imp_sec_expire = ktime_get_real_seconds() + SEC_ADAPT_DELAY; - spin_unlock(&imp->imp_lock); + write_unlock(&imp->imp_sec_lock); } up_read(&obd->u.cli.cl_sem); @@ -930,286 +921,51 @@ void sptlrpc_conf_client_adapt(struct obd_device *obd) } EXPORT_SYMBOL(sptlrpc_conf_client_adapt); - -static void rule2string(struct sptlrpc_rule *r, char *buf, int buflen) -{ - char dirbuf[8]; - char net[LNET_NIDSTR_SIZE] = "default"; - char *ptr = buf; - - if (r->sr_netid != LNET_NIDNET(LNET_NID_ANY)) - libcfs_net2str_r(r->sr_netid, net, sizeof(net)); - - if (r->sr_from == LUSTRE_SP_ANY && r->sr_to == LUSTRE_SP_ANY) - dirbuf[0] = '\0'; - else - snprintf(dirbuf, sizeof(dirbuf), ".%s2%s", - sptlrpc_part2name(r->sr_from), - sptlrpc_part2name(r->sr_to)); - - ptr += snprintf(buf, buflen, "srpc.flavor.%s%s=", net, dirbuf); - - sptlrpc_flavor2name(&r->sr_flvr, ptr, buflen - (ptr - buf)); - buf[buflen - 1] = '\0'; -} - -static int sptlrpc_record_rule_set(struct llog_handle *llh, - char *target, - struct sptlrpc_rule_set *rset) -{ - struct llog_cfg_rec *lcr; - struct lustre_cfg_bufs bufs; - char param[48]; - int i, rc; - - for (i = 0; i < rset->srs_nrule; i++) { - rule2string(&rset->srs_rules[i], param, sizeof(param)); - - lustre_cfg_bufs_reset(&bufs, NULL); - lustre_cfg_bufs_set_string(&bufs, 1, target); - lustre_cfg_bufs_set_string(&bufs, 2, param); - lcr = lustre_cfg_rec_new(LCFG_SPTLRPC_CONF, &bufs); - if (lcr == NULL) - return -ENOMEM; - rc = llog_write(NULL, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX); - lustre_cfg_rec_free(lcr); - if (rc) - return rc; - } - return 0; -} - -static int sptlrpc_record_rules(struct llog_handle *llh, - struct sptlrpc_conf *conf) -{ - struct sptlrpc_conf_tgt *conf_tgt; - - sptlrpc_record_rule_set(llh, conf->sc_fsname, &conf->sc_rset); - - list_for_each_entry(conf_tgt, &conf->sc_tgts, sct_list) { - sptlrpc_record_rule_set(llh, conf_tgt->sct_name, - &conf_tgt->sct_rset); - } - return 0; -} - -#define LOG_SPTLRPC_TMP "sptlrpc.tmp" -#define LOG_SPTLRPC "sptlrpc" - -static -int sptlrpc_target_local_copy_conf(struct obd_device *obd, - struct sptlrpc_conf *conf) -{ - struct llog_handle *llh = NULL; - struct llog_ctxt *ctxt; - struct lvfs_run_ctxt saved; - struct dentry *dentry; - int rc; - ENTRY; - - ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); - if (ctxt == NULL) - RETURN(-EINVAL); - - push_ctxt(&saved, &obd->obd_lvfs_ctxt); - - dentry = ll_lookup_one_len(MOUNT_CONFIGS_DIR, current->fs->pwd.dentry, - strlen(MOUNT_CONFIGS_DIR)); - if (IS_ERR(dentry)) { - rc = PTR_ERR(dentry); - CERROR("cannot lookup %s directory: rc = %d\n", - MOUNT_CONFIGS_DIR, rc); - GOTO(out_ctx, rc); - } - - /* erase the old tmp log */ - rc = llog_erase(NULL, ctxt, NULL, LOG_SPTLRPC_TMP); - if (rc < 0 && rc != -ENOENT) { - CERROR("%s: cannot erase temporary sptlrpc log: rc = %d\n", - obd->obd_name, rc); - GOTO(out_dput, rc); - } - - /* write temporary log */ - rc = llog_open_create(NULL, ctxt, &llh, NULL, LOG_SPTLRPC_TMP); - if (rc) - GOTO(out_dput, rc); - rc = llog_init_handle(NULL, llh, LLOG_F_IS_PLAIN, NULL); - if (rc) - GOTO(out_close, rc); - - rc = sptlrpc_record_rules(llh, conf); - -out_close: - llog_close(NULL, llh); - if (rc == 0) - rc = lustre_rename(dentry, obd->obd_lvfs_ctxt.pwdmnt, - LOG_SPTLRPC_TMP, LOG_SPTLRPC); -out_dput: - dput(dentry); -out_ctx: - pop_ctxt(&saved, &obd->obd_lvfs_ctxt); - llog_ctxt_put(ctxt); - CDEBUG(D_SEC, "target %s: write local sptlrpc conf: rc = %d\n", - obd->obd_name, rc); - RETURN(rc); -} - -static int local_read_handler(const struct lu_env *env, - struct llog_handle *llh, - struct llog_rec_hdr *rec, void *data) -{ - struct sptlrpc_conf *conf = (struct sptlrpc_conf *) data; - struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1); - int cfg_len, rc; - ENTRY; - - if (rec->lrh_type != OBD_CFG_REC) { - CERROR("unhandled lrh_type: %#x\n", rec->lrh_type); - RETURN(-EINVAL); - } - - cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) - - sizeof(struct llog_rec_tail); - - rc = lustre_cfg_sanity_check(lcfg, cfg_len); - if (rc) { - CERROR("Insane cfg\n"); - RETURN(rc); - } - - if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) { - CERROR("invalid command (%x)\n", lcfg->lcfg_command); - RETURN(-EINVAL); - } - - RETURN(__sptlrpc_process_config(lcfg, conf)); -} - -static -int sptlrpc_target_local_read_conf(struct obd_device *obd, - struct sptlrpc_conf *conf) -{ - struct llog_handle *llh = NULL; - struct llog_ctxt *ctxt; - struct lvfs_run_ctxt saved; - int rc; - ENTRY; - - LASSERT(conf->sc_updated == 0 && conf->sc_local == 0); - - ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); - if (ctxt == NULL) { - CERROR("missing llog context\n"); - RETURN(-EINVAL); - } - - push_ctxt(&saved, &obd->obd_lvfs_ctxt); - - rc = llog_open(NULL, ctxt, &llh, NULL, LOG_SPTLRPC, LLOG_OPEN_EXISTS); - if (rc < 0) { - if (rc == -ENOENT) - rc = 0; - GOTO(out_pop, rc); - } - - rc = llog_init_handle(NULL, llh, LLOG_F_IS_PLAIN, NULL); - if (rc) - GOTO(out_close, rc); - - if (llog_get_size(llh) <= 1) { - CDEBUG(D_SEC, "no local sptlrpc copy found\n"); - GOTO(out_close, rc = 0); - } - - rc = llog_process(NULL, llh, local_read_handler, (void *)conf, NULL); - - if (rc == 0) { - conf->sc_local = 1; - } else { - sptlrpc_conf_free_rsets(conf); - } - -out_close: - llog_close(NULL, llh); -out_pop: - pop_ctxt(&saved, &obd->obd_lvfs_ctxt); - llog_ctxt_put(ctxt); - CDEBUG(D_SEC, "target %s: read local sptlrpc conf: rc = %d\n", - obd->obd_name, rc); - RETURN(rc); -} - - /** * called by target devices, extract sptlrpc rules which applies to * this target, to be used for future rpc flavor checking. */ int sptlrpc_conf_target_get_rules(struct obd_device *obd, - struct sptlrpc_rule_set *rset, - int initial) -{ - struct sptlrpc_conf *conf; - struct sptlrpc_conf_tgt *conf_tgt; - enum lustre_sec_part sp_dst; - char fsname[MTI_NAME_MAXLEN]; - int rc = 0; - ENTRY; - - if (strcmp(obd->obd_type->typ_name, LUSTRE_MDT_NAME) == 0) { - sp_dst = LUSTRE_SP_MDT; - } else if (strcmp(obd->obd_type->typ_name, LUSTRE_OST_NAME) == 0) { - sp_dst = LUSTRE_SP_OST; - } else { - CERROR("unexpected obd type %s\n", obd->obd_type->typ_name); - RETURN(-EINVAL); - } - CDEBUG(D_SEC, "get rules for target %s\n", obd->obd_uuid.uuid); + struct sptlrpc_rule_set *rset) +{ + struct sptlrpc_conf *conf; + struct sptlrpc_conf_tgt *conf_tgt; + enum lustre_sec_part sp_dst; + char fsname[MTI_NAME_MAXLEN]; + int rc = 0; + ENTRY; + + if (strcmp(obd->obd_type->typ_name, LUSTRE_MDT_NAME) == 0) { + sp_dst = LUSTRE_SP_MDT; + } else if (strcmp(obd->obd_type->typ_name, LUSTRE_OST_NAME) == 0) { + sp_dst = LUSTRE_SP_OST; + } else { + CERROR("unexpected obd type %s\n", obd->obd_type->typ_name); + RETURN(-EINVAL); + } - target2fsname(obd->obd_uuid.uuid, fsname, sizeof(fsname)); + obd_uuid2fsname(fsname, obd->obd_uuid.uuid, sizeof(fsname)); mutex_lock(&sptlrpc_conf_lock); - - conf = sptlrpc_conf_get(fsname, 0); - if (conf == NULL) { - CERROR("missing sptlrpc config log\n"); - GOTO(out, rc); - } - - if (conf->sc_updated == 0) { - /* - * always read from local copy. here another option is - * if we already have a local copy (read from another - * target device hosted on the same node) we simply use that. - */ - if (conf->sc_local) - sptlrpc_conf_free_rsets(conf); - - sptlrpc_target_local_read_conf(obd, conf); - } else { - LASSERT(conf->sc_local == 0); - - /* write a local copy */ - if (initial || conf->sc_modified) - sptlrpc_target_local_copy_conf(obd, conf); - else - CDEBUG(D_SEC, "unchanged, skip updating local copy\n"); - } - - /* extract rule set for this target */ - conf_tgt = sptlrpc_conf_get_tgt(conf, obd->obd_name, 0); - - rc = sptlrpc_rule_set_extract(&conf->sc_rset, - conf_tgt ? &conf_tgt->sct_rset: NULL, - LUSTRE_SP_ANY, sp_dst, rset); -out: + conf = sptlrpc_conf_get(fsname, 0); + if (conf == NULL) { + CERROR("missing sptlrpc config log\n"); + rc = -EFAULT; + } else { + /* extract rule set for this target */ + conf_tgt = sptlrpc_conf_get_tgt(conf, obd->obd_name, 0); + + rc = sptlrpc_rule_set_extract(&conf->sc_rset, + conf_tgt ? &conf_tgt->sct_rset : NULL, + LUSTRE_SP_ANY, sp_dst, rset); + } mutex_unlock(&sptlrpc_conf_lock); - RETURN(rc); + + RETURN(rc); } int sptlrpc_conf_init(void) { - INIT_LIST_HEAD(&sptlrpc_confs); mutex_init(&sptlrpc_conf_lock); return 0; }