X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fmdt%2Fmdt_lib.c;h=b3dc46284daa2b3c8ca671188818456eddff1456;hb=feb80fe0c440f7790cc3afa53d048370374a81b1;hp=28500c9c0ffae6644eb4f8cc4c7d954781d6e261;hpb=b63da8a5e33b4b0f88e2548a8f7aca7efef6b3e8;p=fs%2Flustre-release.git diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index 28500c9..b3dc462 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -1,35 +1,49 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * lustre/mdt/mdt_lib.c - * Lustre Metadata Target (mdt) request unpacking helper. + * GPL HEADER START * - * Copyright (c) 2006 Cluster File Systems, Inc. - * Author: Peter Braam - * Author: Andreas Dilger - * Author: Phil Schwan - * Author: Mike Shaver - * Author: Nikita Danilov - * Author: Huang Hua + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. * - * This file is part of the Lustre file system, http://www.lustre.org - * Lustre is a trademark of Cluster File Systems, Inc. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * You may have signed or agreed to another license before downloading - * this software. If so, you are bound by the terms and conditions - * of that agreement, and the following does not apply to you. See the - * LICENSE file included with this distribution for more information. + * 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 * - * If you did not agree to a different license, then this copy of Lustre - * is open source software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. + * 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. * - * In either case, Lustre is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * license text for more details. + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * lustre/mdt/mdt_lib.c + * + * Lustre Metadata Target (mdt) request unpacking helper. + * + * Author: Peter Braam + * Author: Andreas Dilger + * Author: Phil Schwan + * Author: Mike Shaver + * Author: Nikita Danilov + * Author: Huang Hua + * Author: Fan Yong */ @@ -47,55 +61,6 @@ typedef enum ucred_init_type { REC_INIT = 2 } ucred_init_type_t; -int groups_from_list(struct group_info *ginfo, gid_t *glist) -{ - int i; - int count = ginfo->ngroups; - - /* fill group_info from gid array */ - for (i = 0; i < ginfo->nblocks; i++) { - int cp_count = min(NGROUPS_PER_BLOCK, count); - int off = i * NGROUPS_PER_BLOCK; - int len = cp_count * sizeof(*glist); - - if (memcpy(ginfo->blocks[i], glist + off, len)) - return -EFAULT; - - count -= cp_count; - } - return 0; -} - -/* groups_sort() is copied from linux kernel! */ -/* a simple shell-metzner sort */ -void groups_sort(struct group_info *group_info) -{ - int base, max, stride; - int gidsetsize = group_info->ngroups; - - for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1) - ; /* nothing */ - stride /= 3; - - while (stride) { - max = gidsetsize - stride; - for (base = 0; base < max; base++) { - int left = base; - int right = left + stride; - gid_t tmp = GROUP_AT(group_info, right); - - while (left >= 0 && GROUP_AT(group_info, left) > tmp) { - GROUP_AT(group_info, right) = - GROUP_AT(group_info, left); - right = left; - left -= stride; - } - GROUP_AT(group_info, right) = tmp; - } - stride /= 3; - } -} - void mdt_exit_ucred(struct mdt_thread_info *info) { struct md_ucred *uc = mdt_ucred(info); @@ -116,168 +81,13 @@ void mdt_exit_ucred(struct mdt_thread_info *info) } } -static int old_init_ucred(struct mdt_thread_info *info, - struct mdt_body *body) +/* 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) { - struct md_ucred *uc = mdt_ucred(info); - struct mdt_device *mdt = info->mti_mdt; - struct mdt_identity *identity = NULL; - - ENTRY; - - uc->mu_valid = UCRED_INVALID; - - if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { - /* get identity info of this user */ - identity = mdt_identity_get(mdt->mdt_identity_cache, - body->fsuid); - if (!identity) { - CERROR("Deny access without identity: uid %d\n", - body->fsuid); - RETURN(-EACCES); - } - } - - uc->mu_valid = UCRED_OLD; - uc->mu_squash = SQUASH_NONE; - uc->mu_o_uid = uc->mu_uid = body->uid; - uc->mu_o_gid = uc->mu_gid = body->gid; - uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid; - uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid; - uc->mu_suppgids[0] = body->suppgid; - uc->mu_suppgids[1] = -1; - if (uc->mu_fsuid) - uc->mu_cap = body->capability & ~CAP_FS_MASK; - else - uc->mu_cap = body->capability; - uc->mu_ginfo = NULL; - uc->mu_identity = identity; - - 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 mdt_identity *identity = NULL; - - ENTRY; - - uc->mu_valid = UCRED_INVALID; - - if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { - /* get identity info of this user */ - identity = mdt_identity_get(mdt->mdt_identity_cache, - uc->mu_fsuid); - if (!identity) { - CERROR("Deny access without identity: uid %d\n", - uc->mu_fsuid); - RETURN(-EACCES); - } - } - - uc->mu_valid = UCRED_OLD; - uc->mu_squash = SQUASH_NONE; - 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; - if (uc->mu_fsuid) - uc->mu_cap &= ~CAP_FS_MASK; - uc->mu_ginfo = NULL; - uc->mu_identity = identity; - - RETURN(0); -} - -static int nid_nosquash(struct mdt_device *mdt, lnet_nid_t nid) -{ - struct rootsquash_info *rsi = mdt->mdt_rootsquash_info; - int i; - - for (i = 0; i < rsi->rsi_n_nosquash_nids; i++) - if ((rsi->rsi_nosquash_nids[i] == nid) || - (rsi->rsi_nosquash_nids[i] == LNET_NID_ANY)) - return 1; - return 0; } -static int mdt_squash_root(struct mdt_device *mdt, struct md_ucred *ucred, - struct ptlrpc_user_desc *pud, lnet_nid_t peernid) -{ - struct rootsquash_info *rsi = mdt->mdt_rootsquash_info; - - if (!rsi || (!rsi->rsi_uid && !rsi->rsi_gid) || - nid_nosquash(mdt, peernid)) - return 0; - - CDEBUG(D_SEC, "squash req from "LPX64":" - "(%u:%u-%u:%u/%x)=>(%u:%u-%u:%u/%x)\n", peernid, - pud->pud_uid, pud->pud_gid, - pud->pud_fsuid, pud->pud_fsgid, pud->pud_cap, - pud->pud_uid ? pud->pud_uid : rsi->rsi_uid, - pud->pud_uid ? pud->pud_gid : rsi->rsi_gid, - pud->pud_fsuid ? pud->pud_fsuid : rsi->rsi_uid, - pud->pud_fsuid ? pud->pud_fsgid : rsi->rsi_gid, - pud->pud_cap & ~CAP_FS_MASK); - - if (rsi->rsi_uid) { - if (!pud->pud_uid) { - ucred->mu_uid = rsi->rsi_uid; - ucred->mu_squash |= SQUASH_UID; - } else { - ucred->mu_uid = pud->pud_uid; - } - - if (!pud->pud_fsuid) { - ucred->mu_fsuid = rsi->rsi_uid; - ucred->mu_squash |= SQUASH_UID; - } else { - ucred->mu_fsuid = pud->pud_fsuid; - } - } else { - ucred->mu_uid = pud->pud_uid; - ucred->mu_fsuid = pud->pud_fsuid; - } - - if (rsi->rsi_gid) { - int i; - - if (!pud->pud_gid) { - ucred->mu_gid = rsi->rsi_gid; - ucred->mu_squash |= SQUASH_GID; - } else { - ucred->mu_gid = pud->pud_gid; - } - - if (!pud->pud_fsgid) { - ucred->mu_fsgid = rsi->rsi_gid; - ucred->mu_squash |= SQUASH_GID; - } else { - ucred->mu_fsgid = pud->pud_fsgid; - } - - for (i = 0; i < 2; i++) { - if (!ucred->mu_suppgids[i]) { - ucred->mu_suppgids[i] = rsi->rsi_gid; - ucred->mu_squash |= SQUASH_GID; - } - } - - for (i = 0; i < pud->pud_ngroups; i++) { - if (!pud->pud_groups[i]) { - pud->pud_groups[i] = rsi->rsi_gid; - ucred->mu_squash |= SQUASH_GID; - } - } - } else { - ucred->mu_gid = pud->pud_gid; - ucred->mu_fsgid = pud->pud_fsgid; - } - - return 1; -} - static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, void *buf) { @@ -286,19 +96,18 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, struct mdt_device *mdt = info->mti_mdt; struct ptlrpc_user_desc *pud = req->rq_user_desc; struct md_ucred *ucred = mdt_ucred(info); - struct mdt_identity *identity = NULL; - lnet_nid_t peernid = req->rq_peer.nid; - __u32 setxid_perm = 0; - int setuid; - int setgid; - int rc = 0; + lnet_nid_t peernid = req->rq_peer.nid; + __u32 perm = 0; + 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; @@ -316,7 +125,7 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, /* sanity check: we expect the uid which client claimed is true */ if (med->med_rmtclient) { if (req->rq_auth_mapped_uid == INVALID_UID) { - CWARN("remote user not mapped, deny access!\n"); + CDEBUG(D_SEC, "remote user not mapped, deny access!\n"); RETURN(-EACCES); } @@ -324,109 +133,135 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, RETURN(-EACCES); if (req->rq_auth_mapped_uid != pud->pud_uid) { - CERROR("remote client "LPU64": auth uid %u " - "while client claim %u:%u/%u:%u\n", - peernid, req->rq_auth_uid, pud->pud_uid, - pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid); + 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) { - CERROR("local client "LPU64": auth uid %u " - "while client claim %u:%u/%u:%u\n", - peernid, req->rq_auth_uid, pud->pud_uid, - pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid); + 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 (med->med_rmtclient) { - CERROR("remote client must run with identity_get " + CDEBUG(D_SEC, "remote client must run with identity_get " "enabled!\n"); RETURN(-EACCES); } else { - setxid_perm |= LUSTRE_SETGRP_PERM; - goto check_squash; + 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 (!identity) { - CERROR("Deny access without identity: uid %d\n", pud->pud_uid); - RETURN(-EACCES); + identity = mdt_identity_get(mdt->mdt_identity_cache, + pud->pud_uid); + if (IS_ERR(identity)) { + if (unlikely(PTR_ERR(identity) == -EREMCHG && + !med->med_rmtclient)) { + 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, + med->med_rmtclient, + peernid); + } } - setxid_perm = mdt_identity_get_setxid_perm(identity, - med->med_rmtclient, - 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); + setgid = ((pud->pud_gid != pud->pud_fsgid) || + (ucred->mu_identity && + (pud->pud_gid != ucred->mu_identity->mi_gid))); /* check permission of setuid */ - if (setuid && !(setxid_perm & LUSTRE_SETUID_PERM)) { - CWARN("mdt blocked setuid attempt (%u -> %u) from " - LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid); + 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 && !(setxid_perm & LUSTRE_SETGID_PERM)) { - CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) " - "from "LPX64"\n", pud->pud_uid, pud->pud_gid, - pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid, - peernid); + 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); } -check_squash: - /* FIXME: The exact behavior of root_squash is not defined. */ - ucred->mu_squash = SQUASH_NONE; - if (mdt_squash_root(mdt, ucred, pud, peernid) == 0) { - ucred->mu_uid = pud->pud_uid; - ucred->mu_gid = pud->pud_gid; - ucred->mu_fsuid = pud->pud_fsuid; - ucred->mu_fsgid = pud->pud_fsgid; - } - - /* remove fs privilege for non-root user */ - if (ucred->mu_fsuid) - ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK; - else - ucred->mu_cap = pud->pud_cap; - /* * NB: remote client not allowed to setgroups anyway. */ - if (!med->med_rmtclient && pud->pud_ngroups && - (setxid_perm & LUSTRE_SETGRP_PERM)) { - struct group_info *ginfo; - - /* setgroups for local client */ - ginfo = groups_alloc(pud->pud_ngroups); - if (!ginfo) { - CERROR("failed to alloc %d groups\n", - pud->pud_ngroups); - GOTO(out, rc = -ENOMEM); + if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) { + if (pud->pud_ngroups) { + /* setgroups for local client */ + ucred->mu_ginfo = 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; } - groups_from_list(ginfo, pud->pud_groups); - groups_sort(ginfo); - ucred->mu_ginfo = ginfo; } else { + ucred->mu_suppgids[0] = -1; + ucred->mu_suppgids[1] = -1; ucred->mu_ginfo = NULL; } - ucred->mu_identity = identity; + ucred->mu_uid = pud->pud_uid; + ucred->mu_gid = pud->pud_gid; + ucred->mu_fsuid = pud->pud_fsuid; + ucred->mu_fsgid = pud->pud_fsgid; + + /* XXX: need to process root_squash here. */ + mdt_root_squash(info); + + /* 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; ucred->mu_valid = UCRED_NEW; EXIT; out: - if (rc && identity) - mdt_identity_put(mdt->mdt_identity_cache, identity); + if (rc) { + if (ucred->mu_ginfo) { + groups_free(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; } @@ -438,66 +273,181 @@ int mdt_check_ucred(struct mdt_thread_info *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 mdt_identity *identity; - lnet_nid_t peernid = req->rq_peer.nid; + struct md_identity *identity = NULL; + lnet_nid_t peernid = req->rq_peer.nid; + __u32 perm = 0; + int setuid; + int setgid; + int rc = 0; ENTRY; if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW)) RETURN(0); - if (!req->rq_user_desc) + 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 (req->rq_auth_gss) { - if (med->med_rmtclient) { - if (req->rq_auth_mapped_uid == INVALID_UID) { - CWARN("remote user not mapped, deny access!\n"); - RETURN(-EACCES); - } + if (med->med_rmtclient) { + 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 (ptlrpc_user_desc_do_idmap(req, pud)) + RETURN(-EACCES); - if (req->rq_auth_mapped_uid != pud->pud_uid) { - CERROR("remote client "LPU64": auth uid %u " - "while client claim %u:%u/%u:%u\n", - peernid, req->rq_auth_uid, pud->pud_uid, - pud->pud_gid, pud->pud_fsuid, - pud->pud_fsgid); - RETURN(-EACCES); - } - } else { - if (req->rq_auth_uid != pud->pud_uid) { - CERROR("local client "LPU64": auth uid %u " - "while client claim %u:%u/%u:%u\n", - peernid, req->rq_auth_uid, pud->pud_uid, - pud->pud_gid, pud->pud_fsuid, - pud->pud_fsgid); - 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 (med->med_rmtclient) { - CERROR("remote client must run with " - "identity_get enabled!\n"); + CDEBUG(D_SEC, "remote client must run with identity_get " + "enabled!\n"); RETURN(-EACCES); } - } else { - identity = mdt_identity_get(mdt->mdt_identity_cache, - pud->pud_uid); - if (!identity) { - CERROR("Deny access without identity: uid %d\n", + RETURN(0); + } + + identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid); + if (IS_ERR(identity)) { + if (unlikely(PTR_ERR(identity) == -EREMCHG && + !med->med_rmtclient)) { + RETURN(0); + } else { + CDEBUG(D_SEC, "Deny access without identity: uid %u\n", pud->pud_uid); RETURN(-EACCES); + } + } + + perm = mdt_identity_get_perm(identity, med->med_rmtclient, 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 old_init_ucred(struct mdt_thread_info *info, + struct mdt_body *body) +{ + 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_uid = body->uid; + uc->mu_o_gid = uc->mu_gid = body->gid; + uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid; + uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid; + uc->mu_suppgids[0] = body->suppgid; + uc->mu_suppgids[1] = -1; + 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; + + /* XXX: need to process root_squash here. */ + mdt_root_squash(info); + + /* remove fs privilege for non-root user */ + if (uc->mu_fsuid) + uc->mu_cap = body->capability & ~CFS_CAP_FS_MASK; + else + uc->mu_cap = body->capability; + uc->mu_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; - mdt_identity_put(mdt->mdt_identity_cache, identity); + 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; + + /* XXX: need to process root_squash here. */ + mdt_root_squash(info); + + /* 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); } @@ -559,9 +509,10 @@ void mdt_dump_lmm(int level, const struct lov_mds_md *lmm) void mdt_shrink_reply(struct mdt_thread_info *info) { - struct req_capsule *pill = &info->mti_pill; - struct mdt_body *body; - int acl_size, md_size, adjust = 0; + struct req_capsule *pill = info->mti_pill; + struct mdt_body *body; + int md_size; + int acl_size; ENTRY; body = req_capsule_server_get(pill, &RMF_MDT_BODY); @@ -574,11 +525,11 @@ void mdt_shrink_reply(struct mdt_thread_info *info) acl_size = body->aclsize; - CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d" - " MDSCAPA = %d, OSSCAPA = %d\n", + CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d" + " MDSCAPA = "LPX64", OSSCAPA = "LPX64"\n", md_size, acl_size, - (int)(body->valid & OBD_MD_FLMDSCAPA), - (int)(body->valid & OBD_MD_FLOSSCAPA)); + body->valid & OBD_MD_FLMDSCAPA, + body->valid & OBD_MD_FLOSSCAPA); /* &RMF_MDT_BODY, &RMF_MDT_MD, @@ -587,33 +538,23 @@ void mdt_shrink_reply(struct mdt_thread_info *info) (optional) &RMF_CAPA2, (optional) something else */ - adjust += req_capsule_shrink(pill, &RMF_MDT_MD, - md_size, adjust, 1); + if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)) + req_capsule_shrink(pill, &RMF_MDT_MD, md_size, + RCL_SERVER); if (req_capsule_has_field(pill, &RMF_ACL, RCL_SERVER)) - adjust += req_capsule_shrink(pill, &RMF_ACL, - acl_size, adjust, 1); + req_capsule_shrink(pill, &RMF_ACL, acl_size, RCL_SERVER); else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER)) - adjust += req_capsule_shrink(pill, &RMF_LOGCOOKIES, - acl_size, adjust, 1); - - /* RMF_CAPA1 on server-side maybe for OBD_MD_FLMDSCAPA or - * OBD_MD_FLOSSCAPA. If RMF_CAPA2 exist also, RMF_CAPA1 is - * for OBD_MD_FLMDSCAPA only. */ - if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER)) { - if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) && - !(body->valid & OBD_MD_FLMDSCAPA)) || - (!req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) && - !(body->valid & OBD_MD_FLMDSCAPA) && - !(body->valid & OBD_MD_FLOSSCAPA))) - adjust += req_capsule_shrink(pill, &RMF_CAPA1, - 0, adjust, 1); - } + req_capsule_shrink(pill, &RMF_LOGCOOKIES, + acl_size, RCL_SERVER); - /* RMF_CAPA2 on server-side is for OBD_MD_FLOSSCAPA only. */ - if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) && - !(body->valid & OBD_MD_FLOSSCAPA))) - adjust += req_capsule_shrink(pill, &RMF_CAPA2, 0, adjust, 0); + if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) && + !(body->valid & OBD_MD_FLMDSCAPA)) + req_capsule_shrink(pill, &RMF_CAPA1, 0, RCL_SERVER); + + if (req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) && + !(body->valid & OBD_MD_FLOSSCAPA)) + req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER); /* * Some more field should be shrinked if needed. @@ -632,7 +573,7 @@ int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo, const struct lu_attr *la = &ma->ma_attr; ENTRY; - repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY); + repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY); LASSERT(repbody != NULL); if (ma->ma_valid & MA_INODE) @@ -740,7 +681,10 @@ static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr, out |= LA_FLAGS; if (in & MDS_OPEN_OWNEROVERRIDE) - out |= MDS_OPEN_OWNEROVERRIDE; + ma->ma_attr_flags |= MDS_OPEN_OWNEROVERRIDE; + + if (in & (ATTR_KILL_SUID|ATTR_KILL_SGID)) + ma->ma_attr_flags |= MDS_PERM_BYPASS; /*XXX need ATTR_RAW?*/ in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS| @@ -758,12 +702,13 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) struct md_ucred *uc = mdt_ucred(info); struct md_attr *ma = &info->mti_attr; struct lu_attr *la = &ma->ma_attr; - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; struct mdt_reint_record *rr = &info->mti_rr; struct mdt_rec_setattr *rec; ENTRY; - rec = req_capsule_client_get(pill, &RMF_REC_SETATTR); + CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint)); + rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); @@ -795,7 +740,7 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) static int mdt_epoch_unpack(struct mdt_thread_info *info) { - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; ENTRY; if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT)) @@ -806,21 +751,21 @@ static int mdt_epoch_unpack(struct mdt_thread_info *info) } static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) { - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) { info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ); if (info->mti_dlm_req == NULL) RETURN(-EFAULT); } - + RETURN(0); } static int mdt_setattr_unpack(struct mdt_thread_info *info) { struct md_attr *ma = &info->mti_attr; - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; int rc; ENTRY; @@ -866,12 +811,13 @@ static int mdt_create_unpack(struct mdt_thread_info *info) struct mdt_rec_create *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; struct md_op_spec *sp = &info->mti_spec; int rc; ENTRY; - rec = req_capsule_client_get(pill, &RMF_REC_CREATE); + CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint)); + rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); @@ -904,8 +850,8 @@ static int mdt_create_unpack(struct mdt_thread_info *info) rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; - LASSERT(rr->rr_namelen > 0); - + LASSERT(rr->rr_name && rr->rr_namelen > 0); + #ifdef CONFIG_FS_POSIX_ACL if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) { if (S_ISDIR(attr->la_mode)) @@ -915,7 +861,7 @@ static int mdt_create_unpack(struct mdt_thread_info *info) RCL_CLIENT)); sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA); sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA, - RCL_CLIENT); + RCL_CLIENT); sp->u.sp_ea.fid = rr->rr_fid1; RETURN(0); } @@ -962,11 +908,12 @@ static int mdt_link_unpack(struct mdt_thread_info *info) struct mdt_rec_link *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; int rc; ENTRY; - rec = req_capsule_client_get(pill, &RMF_REC_LINK); + CLASSERT(sizeof(struct mdt_rec_link) == sizeof(struct mdt_rec_reint)); + rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); @@ -1010,18 +957,19 @@ static int mdt_unlink_unpack(struct mdt_thread_info *info) struct md_attr *ma = &info->mti_attr; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; int rc; ENTRY; - rec = req_capsule_client_get(pill, &RMF_REC_UNLINK); + CLASSERT(sizeof(struct mdt_rec_unlink) == sizeof(struct mdt_rec_reint)); + rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); uc->mu_fsuid = rec->ul_fsuid; uc->mu_fsgid = rec->ul_fsgid; uc->mu_cap = rec->ul_cap; - uc->mu_suppgids[0] = rec->ul_suppgid; + uc->mu_suppgids[0] = rec->ul_suppgid1; uc->mu_suppgids[1] = -1; attr->la_uid = rec->ul_fsuid; @@ -1060,11 +1008,12 @@ static int mdt_rename_unpack(struct mdt_thread_info *info) struct md_attr *ma = &info->mti_attr; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; int rc; ENTRY; - rec = req_capsule_client_get(pill, &RMF_REC_RENAME); + CLASSERT(sizeof(struct mdt_rec_rename) == sizeof(struct mdt_rec_reint)); + rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); @@ -1115,13 +1064,14 @@ static int mdt_open_unpack(struct mdt_thread_info *info) struct md_ucred *uc = mdt_ucred(info); struct mdt_rec_create *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; - struct req_capsule *pill = &info->mti_pill; + struct req_capsule *pill = info->mti_pill; struct mdt_reint_record *rr = &info->mti_rr; struct ptlrpc_request *req = mdt_info_req(info); struct md_op_spec *sp = &info->mti_spec; ENTRY; - rec = req_capsule_client_get(pill, &RMF_REC_CREATE); + CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint)); + rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); @@ -1184,6 +1134,59 @@ static int mdt_open_unpack(struct mdt_thread_info *info) RETURN(0); } +static int mdt_setxattr_unpack(struct mdt_thread_info *info) +{ + struct mdt_reint_record *rr = &info->mti_rr; + struct md_ucred *uc = mdt_ucred(info); + struct lu_attr *attr = &info->mti_attr.ma_attr; + struct req_capsule *pill = info->mti_pill; + struct mdt_rec_setxattr *rec; + ENTRY; + + + CLASSERT(sizeof(struct mdt_rec_setxattr) == + sizeof(struct mdt_rec_reint)); + + rec = req_capsule_client_get(pill, &RMF_REC_REINT); + if (rec == NULL) + RETURN(-EFAULT); + + uc->mu_fsuid = rec->sx_fsuid; + uc->mu_fsgid = rec->sx_fsgid; + uc->mu_cap = rec->sx_cap; + uc->mu_suppgids[0] = rec->sx_suppgid1; + uc->mu_suppgids[1] = -1; + + rr->rr_opcode = rec->sx_opcode; + rr->rr_fid1 = &rec->sx_fid; + attr->la_valid = rec->sx_valid; + attr->la_ctime = rec->sx_time; + attr->la_size = rec->sx_size; + attr->la_flags = rec->sx_flags; + + if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) + mdt_set_capainfo(info, 0, rr->rr_fid1, + req_capsule_client_get(pill, &RMF_CAPA1)); + else + mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA); + + rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); + if (rr->rr_name == NULL) + RETURN(-EFAULT); + rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; + LASSERT(rr->rr_namelen > 0); + + rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); + if (rr->rr_eadatalen > 0) { + rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA); + if (rr->rr_eadata == NULL) + RETURN(-EFAULT); + } + + RETURN(0); +} + + typedef int (*reint_unpacker)(struct mdt_thread_info *info); static reint_unpacker mdt_reint_unpackers[REINT_MAX] = { @@ -1192,7 +1195,8 @@ static reint_unpacker mdt_reint_unpackers[REINT_MAX] = { [REINT_LINK] = mdt_link_unpack, [REINT_UNLINK] = mdt_unlink_unpack, [REINT_RENAME] = mdt_rename_unpack, - [REINT_OPEN] = mdt_open_unpack + [REINT_OPEN] = mdt_open_unpack, + [REINT_SETXATTR] = mdt_setxattr_unpack }; int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)