* in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see [sun.com URL with a
- * copy of GPLv2].
+ * 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
#define DEBUG_SUBSYSTEM S_MDS
#include "mdt_internal.h"
+#include <lnet/lib-lnet.h>
typedef enum ucred_init_type {
if (uc->mu_valid != UCRED_INIT) {
uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
if (uc->mu_ginfo) {
- groups_free(uc->mu_ginfo);
+ put_group_info(uc->mu_ginfo);
uc->mu_ginfo = NULL;
}
if (uc->mu_identity) {
}
}
-/* 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,
void *buf)
{
struct ptlrpc_request *req = mdt_info_req(info);
- struct mdt_export_data *med = mdt_req2med(req);
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;
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;
}
/* sanity check: we expect the uid which client claimed is true */
- if (med->med_rmtclient) {
+ if (remote) {
if (req->rq_auth_mapped_uid == INVALID_UID) {
CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
RETURN(-EACCES);
}
if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
- if (med->med_rmtclient) {
+ if (remote) {
CDEBUG(D_SEC, "remote client must run with identity_get "
"enabled!\n");
RETURN(-EACCES);
pud->pud_uid);
if (IS_ERR(identity)) {
if (unlikely(PTR_ERR(identity) == -EREMCHG &&
- !med->med_rmtclient)) {
+ !remote)) {
ucred->mu_identity = NULL;
perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
CFS_SETGRP_PERM;
} else {
ucred->mu_identity = identity;
perm = mdt_identity_get_perm(ucred->mu_identity,
- med->med_rmtclient,
- peernid);
+ remote, peernid);
}
}
/*
* NB: remote client not allowed to setgroups anyway.
*/
- if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) {
+ if (!remote && perm & CFS_SETGRP_PERM) {
if (pud->pud_ngroups) {
/* setgroups for local client */
ucred->mu_ginfo = groups_alloc(pud->pud_ngroups);
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 */
+ /* remove fs privilege for non-root user. */
if (ucred->mu_fsuid)
- ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
+ 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) {
- groups_free(ucred->mu_ginfo);
+ put_group_info(ucred->mu_ginfo);
ucred->mu_ginfo = NULL;
}
if (ucred->mu_identity) {
int mdt_check_ucred(struct mdt_thread_info *info)
{
struct ptlrpc_request *req = mdt_info_req(info);
- struct mdt_export_data *med = mdt_req2med(req);
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;
/* sanity check: if we use strong authentication, we expect the
* uid which client claimed is true */
- if (med->med_rmtclient) {
+ if (remote) {
if (req->rq_auth_mapped_uid == INVALID_UID) {
CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
RETURN(-EACCES);
}
if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
- if (med->med_rmtclient) {
+ if (remote) {
CDEBUG(D_SEC, "remote client must run with identity_get "
"enabled!\n");
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)) {
+ !remote)) {
RETURN(0);
} else {
CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
}
}
- perm = mdt_identity_get_perm(identity, med->med_rmtclient, peernid);
+ 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 ||
}
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 */
+ /* remove fs privilege for non-root user. */
if (uc->mu_fsuid)
- uc->mu_cap = body->capability & ~CAP_FS_MASK;
+ uc->mu_cap = body->capability & ~CFS_CAP_FS_MASK;
else
uc->mu_cap = body->capability;
uc->mu_valid = UCRED_OLD;
}
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 */
+ /* remove fs privilege for non-root user. */
if (uc->mu_fsuid)
- uc->mu_cap &= ~CAP_FS_MASK;
+ uc->mu_cap &= ~CFS_CAP_FS_MASK;
uc->mu_valid = UCRED_OLD;
RETURN(0);
acl_size = body->aclsize;
- CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d"
+ /* this replay - not send info to client */
+ if (info->mti_spec.no_create == 1) {
+ md_size = 0;
+ acl_size = 0;
+ }
+
+ CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d"
" MDSCAPA = "LPX64", OSSCAPA = "LPX64"\n",
md_size, acl_size,
body->valid & OBD_MD_FLMDSCAPA,
req_capsule_shrink(pill, &RMF_ACL, acl_size, RCL_SERVER);
else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
req_capsule_shrink(pill, &RMF_LOGCOOKIES,
- acl_size, RCL_SERVER);
+ acl_size, RCL_SERVER);
if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) &&
- !(body->valid & OBD_MD_FLMDSCAPA))
+ !(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))
+ !(body->valid & OBD_MD_FLOSSCAPA))
req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER);
/*
{
struct mdt_body *repbody;
const struct lu_attr *la = &ma->ma_attr;
+ int rc;
ENTRY;
repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
repbody->valid |= OBD_MD_FLCOOKIE;
}
+ if (info->mti_mdt->mdt_opts.mo_oss_capa &&
+ info->mti_exp->exp_connect_flags & OBD_CONNECT_OSS_CAPA &&
+ repbody->valid & OBD_MD_FLEASIZE) {
+ struct lustre_capa *capa;
+
+ capa = req_capsule_server_get(info->mti_pill, &RMF_CAPA2);
+ LASSERT(capa);
+ capa->lc_opc = CAPA_OPC_OSS_DESTROY;
+ rc = mo_capa_get(info->mti_env, mdt_object_child(mo), capa, 0);
+ if (rc)
+ RETURN(rc);
+
+ repbody->valid |= OBD_MD_FLOSSCAPA;
+ }
+
RETURN(0);
}
if (in & 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|
ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
- ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
+ ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE|
+ ATTR_FORCE|ATTR_KILL_SUID|ATTR_KILL_SGID);
if (in != 0)
CERROR("Unknown attr bits: %#llx\n", in);
return out;
if (info->mti_dlm_req == NULL)
RETURN(-EFAULT);
}
-
+
RETURN(0);
}
req_capsule_client_get(pill, &RMF_CAPA1));
mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
- 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_name && rr->rr_namelen > 0);
-
+ if (!info->mti_cross_ref) {
+ 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_name && rr->rr_namelen > 0);
+ } else {
+ rr->rr_name = NULL;
+ rr->rr_namelen = 0;
+ }
+
#ifdef CONFIG_FS_POSIX_ACL
if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
if (S_ISDIR(attr->la_mode))
mdt_set_capainfo(info, 1, rr->rr_fid2,
req_capsule_client_get(pill, &RMF_CAPA2));
+ info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
+ info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
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);
- info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
- info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
+ if (!info->mti_cross_ref)
+ LASSERT(rr->rr_namelen > 0);
rc = mdt_dlmreq_unpack(info);
RETURN(rc);
mdt_set_capainfo(info, 0, rr->rr_fid1,
req_capsule_client_get(pill, &RMF_CAPA1));
- 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);
- info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
+ if (!info->mti_cross_ref) {
+ rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
+ rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
+ if (rr->rr_name == NULL || rr->rr_namelen == 0)
+ RETURN(-EFAULT);
+ } else {
+ rr->rr_name = NULL;
+ rr->rr_namelen = 0;
+ }
+ info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
if (rec->ul_bias & MDS_VTX_BYPASS)
ma->ma_attr_flags |= MDS_VTX_BYPASS;
else
ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
+ if (lustre_msg_get_flags(mdt_info_req(info)->rq_reqmsg) & MSG_REPLAY)
+ info->mti_spec.no_create = 1;
+
rc = mdt_dlmreq_unpack(info);
RETURN(rc);
}
mdt_set_capainfo(info, 1, rr->rr_fid2,
req_capsule_client_get(pill, &RMF_CAPA2));
+ info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
+ info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
if (rr->rr_name == NULL || rr->rr_tgt == NULL)
RETURN(-EFAULT);
rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
- LASSERT(rr->rr_namelen > 0);
rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
- LASSERT(rr->rr_tgtlen > 0);
- info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
- info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
+ if (!info->mti_cross_ref)
+ LASSERT(rr->rr_namelen > 0 && rr->rr_tgtlen > 0);
if (rec->rn_bias & MDS_VTX_BYPASS)
ma->ma_attr_flags |= MDS_VTX_BYPASS;
else
ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
+ if (lustre_msg_get_flags(mdt_info_req(info)->rq_reqmsg) & MSG_REPLAY)
+ info->mti_spec.no_create = 1;
+
rc = mdt_dlmreq_unpack(info);
RETURN(rc);
}
if (sp->u.sp_ea.eadatalen) {
sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
- sp->u.sp_ea.no_lov_create = 1;
+ sp->no_create = 1;
}
RETURN(0);