static int old_init_ucred(struct mdt_thread_info *info, struct mdt_body *body) { struct lu_ucred *uc = mdt_ucred(info); struct mdt_device *mdt = info->mti_mdt; struct md_identity *identity = NULL; ENTRY; LASSERT(uc != NULL); uc->uc_valid = UCRED_INVALID; uc->uc_o_uid = uc->uc_uid = body->uid; uc->uc_o_gid = uc->uc_gid = body->gid; uc->uc_o_fsuid = uc->uc_fsuid = body->fsuid; uc->uc_o_fsgid = uc->uc_fsgid = body->fsgid; uc->uc_suppgids[0] = body->suppgid; uc->uc_suppgids[1] = -1; uc->uc_ginfo = NULL; if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { identity = mdt_identity_get(mdt->mdt_identity_cache, uc->uc_fsuid); if (IS_ERR(identity)) { if (unlikely(PTR_ERR(identity) == -EREMCHG)) { identity = NULL; } else { CDEBUG(D_SEC, "Deny access without identity: " "uid %u\n", uc->uc_fsuid); RETURN(-EACCES); } } } uc->uc_identity = identity; /* process root_squash here. */ mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); /* remove fs privilege for non-root user. */ if (uc->uc_fsuid) uc->uc_cap = body->capability & ~CFS_CAP_FS_MASK; else uc->uc_cap = body->capability; uc->uc_valid = UCRED_OLD; RETURN(0); }
static int old_init_ucred_reint(struct mdt_thread_info *info) { struct md_ucred *uc = mdt_ucred(info); struct mdt_device *mdt = info->mti_mdt; struct md_identity *identity = NULL; ENTRY; uc->mu_valid = UCRED_INVALID; uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid; uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid; uc->mu_ginfo = NULL; if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { identity = mdt_identity_get(mdt->mdt_identity_cache, uc->mu_fsuid); if (IS_ERR(identity)) { if (unlikely(PTR_ERR(identity) == -EREMCHG)) { identity = NULL; } else { CDEBUG(D_SEC, "Deny access without identity: " "uid %u\n", uc->mu_fsuid); RETURN(-EACCES); } } } uc->mu_identity = identity; /* 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) uc->mu_cap &= ~CFS_CAP_FS_MASK; uc->mu_valid = UCRED_OLD; RETURN(0); }
int mdt_check_ucred(struct mdt_thread_info *info) { struct ptlrpc_request *req = mdt_info_req(info); struct mdt_device *mdt = info->mti_mdt; struct ptlrpc_user_desc *pud = req->rq_user_desc; struct md_ucred *ucred = mdt_ucred(info); struct md_identity *identity = NULL; lnet_nid_t peernid = req->rq_peer.nid; __u32 perm = 0; __u32 remote = exp_connect_rmtclient(info->mti_exp); int setuid; int setgid; int rc = 0; ENTRY; if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW)) RETURN(0); if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc) RETURN(0); /* sanity check: if we use strong authentication, we expect the * uid which client claimed is true */ if (remote) { if (req->rq_auth_mapped_uid == INVALID_UID) { CDEBUG(D_SEC, "remote user not mapped, deny access!\n"); RETURN(-EACCES); } if (ptlrpc_user_desc_do_idmap(req, pud)) RETURN(-EACCES); if (req->rq_auth_mapped_uid != pud->pud_uid) { CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u " "while client claims %u:%u/%u:%u\n", libcfs_nid2str(peernid), req->rq_auth_uid, req->rq_auth_mapped_uid, pud->pud_uid, pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid); RETURN(-EACCES); } } else { if (req->rq_auth_uid != pud->pud_uid) { CDEBUG(D_SEC, "local client %s: auth uid %u " "while client claims %u:%u/%u:%u\n", libcfs_nid2str(peernid), req->rq_auth_uid, pud->pud_uid, pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid); RETURN(-EACCES); } } if (is_identity_get_disabled(mdt->mdt_identity_cache)) { if (remote) { CDEBUG(D_SEC, "remote client must run with identity_get " "enabled!\n"); RETURN(-EACCES); } RETURN(0); } identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid); if (IS_ERR(identity)) { if (unlikely(PTR_ERR(identity) == -EREMCHG && !remote)) { RETURN(0); } else { CDEBUG(D_SEC, "Deny access without identity: uid %u\n", pud->pud_uid); RETURN(-EACCES); } } perm = mdt_identity_get_perm(identity, remote, peernid); /* find out the setuid/setgid attempt */ setuid = (pud->pud_uid != pud->pud_fsuid); setgid = (pud->pud_gid != pud->pud_fsgid || pud->pud_gid != identity->mi_gid); /* check permission of setuid */ if (setuid && !(perm & CFS_SETUID_PERM)) { CDEBUG(D_SEC, "mdt blocked setuid attempt (%u -> %u) from %s\n", pud->pud_uid, pud->pud_fsuid, libcfs_nid2str(peernid)); GOTO(out, rc = -EACCES); } /* check permission of setgid */ if (setgid && !(perm & CFS_SETGID_PERM)) { CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) " "from %s\n", pud->pud_uid, pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid, libcfs_nid2str(peernid)); GOTO(out, rc = -EACCES); } EXIT; out: mdt_identity_put(mdt->mdt_identity_cache, identity); return rc; }
static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, void *buf) { struct ptlrpc_request *req = mdt_info_req(info); struct mdt_device *mdt = info->mti_mdt; struct ptlrpc_user_desc *pud = req->rq_user_desc; struct md_ucred *ucred = mdt_ucred(info); lnet_nid_t peernid = req->rq_peer.nid; __u32 perm = 0; __u32 remote = exp_connect_rmtclient(info->mti_exp); int setuid; int setgid; int rc = 0; ENTRY; LASSERT(req->rq_auth_gss); LASSERT(!req->rq_auth_usr_mdt); LASSERT(req->rq_user_desc); ucred->mu_valid = UCRED_INVALID; ucred->mu_o_uid = pud->pud_uid; ucred->mu_o_gid = pud->pud_gid; ucred->mu_o_fsuid = pud->pud_fsuid; ucred->mu_o_fsgid = pud->pud_fsgid; if (type == BODY_INIT) { struct mdt_body *body = (struct mdt_body *)buf; ucred->mu_suppgids[0] = body->suppgid; ucred->mu_suppgids[1] = -1; } /* sanity check: we expect the uid which client claimed is true */ if (remote) { if (req->rq_auth_mapped_uid == INVALID_UID) { CDEBUG(D_SEC, "remote user not mapped, deny access!\n"); RETURN(-EACCES); } if (ptlrpc_user_desc_do_idmap(req, pud)) RETURN(-EACCES); if (req->rq_auth_mapped_uid != pud->pud_uid) { CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u " "while client claims %u:%u/%u:%u\n", libcfs_nid2str(peernid), req->rq_auth_uid, req->rq_auth_mapped_uid, pud->pud_uid, pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid); RETURN(-EACCES); } } else { if (req->rq_auth_uid != pud->pud_uid) { CDEBUG(D_SEC, "local client %s: auth uid %u " "while client claims %u:%u/%u:%u\n", libcfs_nid2str(peernid), req->rq_auth_uid, pud->pud_uid, pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid); RETURN(-EACCES); } } if (is_identity_get_disabled(mdt->mdt_identity_cache)) { if (remote) { CDEBUG(D_SEC, "remote client must run with identity_get " "enabled!\n"); RETURN(-EACCES); } else { ucred->mu_identity = NULL; perm = CFS_SETUID_PERM | CFS_SETGID_PERM | CFS_SETGRP_PERM; } } else { struct md_identity *identity; identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid); if (IS_ERR(identity)) { if (unlikely(PTR_ERR(identity) == -EREMCHG && !remote)) { ucred->mu_identity = NULL; perm = CFS_SETUID_PERM | CFS_SETGID_PERM | CFS_SETGRP_PERM; } else { CDEBUG(D_SEC, "Deny access without identity: uid %u\n", pud->pud_uid); RETURN(-EACCES); } } else { ucred->mu_identity = identity; perm = mdt_identity_get_perm(ucred->mu_identity, remote, peernid); } } /* find out the setuid/setgid attempt */ setuid = (pud->pud_uid != pud->pud_fsuid); setgid = ((pud->pud_gid != pud->pud_fsgid) || (ucred->mu_identity && (pud->pud_gid != ucred->mu_identity->mi_gid))); /* check permission of setuid */ if (setuid && !(perm & CFS_SETUID_PERM)) { CDEBUG(D_SEC, "mdt blocked setuid attempt (%u -> %u) from %s\n", pud->pud_uid, pud->pud_fsuid, libcfs_nid2str(peernid)); GOTO(out, rc = -EACCES); } /* check permission of setgid */ if (setgid && !(perm & CFS_SETGID_PERM)) { CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) " "from %s\n", pud->pud_uid, pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid, ucred->mu_identity->mi_gid, libcfs_nid2str(peernid)); GOTO(out, rc = -EACCES); } /* * NB: remote client not allowed to setgroups anyway. */ if (!remote && perm & CFS_SETGRP_PERM) { if (pud->pud_ngroups) { /* setgroups for local client */ ucred->mu_ginfo = cfs_groups_alloc(pud->pud_ngroups); if (!ucred->mu_ginfo) { CERROR("failed to alloc %d groups\n", pud->pud_ngroups); GOTO(out, rc = -ENOMEM); } lustre_groups_from_list(ucred->mu_ginfo, pud->pud_groups); lustre_groups_sort(ucred->mu_ginfo); } else { ucred->mu_ginfo = NULL; } } else { ucred->mu_suppgids[0] = -1; ucred->mu_suppgids[1] = -1; ucred->mu_ginfo = NULL; } ucred->mu_uid = pud->pud_uid; ucred->mu_gid = pud->pud_gid; ucred->mu_fsuid = pud->pud_fsuid; ucred->mu_fsgid = pud->pud_fsgid; /* process root_squash here. */ mdt_root_squash(info, peernid); /* remove fs privilege for non-root user. */ if (ucred->mu_fsuid) ucred->mu_cap = pud->pud_cap & ~CFS_CAP_FS_MASK; else ucred->mu_cap = pud->pud_cap; if (remote && !(perm & CFS_RMTOWN_PERM)) ucred->mu_cap &= ~(CFS_CAP_SYS_RESOURCE_MASK | CFS_CAP_CHOWN_MASK); ucred->mu_valid = UCRED_NEW; EXIT; out: if (rc) { if (ucred->mu_ginfo) { cfs_put_group_info(ucred->mu_ginfo); ucred->mu_ginfo = NULL; } if (ucred->mu_identity) { mdt_identity_put(mdt->mdt_identity_cache, ucred->mu_identity); ucred->mu_identity = NULL; } } return rc; }
int mdt_handle_idmap(struct mdt_thread_info *info) { struct ptlrpc_request *req = mdt_info_req(info); struct mdt_device *mdt = info->mti_mdt; struct mdt_export_data *med; struct ptlrpc_user_desc *pud = req->rq_user_desc; struct md_identity *identity; __u32 opc; int rc = 0; ENTRY; if (!req->rq_export) RETURN(0); med = mdt_req2med(req); if (!exp_connect_rmtclient(info->mti_exp)) RETURN(0); opc = lustre_msg_get_opc(req->rq_reqmsg); /* Bypass other opc */ if ((opc != SEC_CTX_INIT) && (opc != SEC_CTX_INIT_CONT) && (opc != SEC_CTX_FINI) && (opc != MDS_CONNECT)) RETURN(0); LASSERT(med->med_idmap); if (unlikely(!pud)) { CDEBUG(D_SEC, "remote client must run with rq_user_desc " "present\n"); RETURN(-EACCES); } if (req->rq_auth_mapped_uid == INVALID_UID) { CDEBUG(D_SEC, "invalid authorized mapped uid, please check " "/etc/lustre/idmap.conf!\n"); RETURN(-EACCES); } if (is_identity_get_disabled(mdt->mdt_identity_cache)) { CDEBUG(D_SEC, "remote client must run with identity_get " "enabled!\n"); RETURN(-EACCES); } identity = mdt_identity_get(mdt->mdt_identity_cache, req->rq_auth_mapped_uid); if (IS_ERR(identity)) { CDEBUG(D_SEC, "can't get mdt identity(%u), no mapping added\n", req->rq_auth_mapped_uid); RETURN(-EACCES); } switch (opc) { case SEC_CTX_INIT: case SEC_CTX_INIT_CONT: case MDS_CONNECT: rc = lustre_idmap_add(med->med_idmap, pud->pud_uid, identity->mi_uid, pud->pud_gid, identity->mi_gid); break; case SEC_CTX_FINI: rc = lustre_idmap_del(med->med_idmap, pud->pud_uid, identity->mi_uid, pud->pud_gid, identity->mi_gid); break; } mdt_identity_put(mdt->mdt_identity_cache, identity); if (rc) RETURN(rc); switch (opc) { case SEC_CTX_INIT: case SEC_CTX_INIT_CONT: case SEC_CTX_FINI: mdt_revoke_export_locks(req->rq_export); break; } RETURN(0); }