* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2013, Intel Corporation.
+ * Copyright (c) 2011, 2014, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#define DEBUG_SUBSYSTEM S_MDS
#include "mdt_internal.h"
-#include <lnet/lib-lnet.h>
-
+#include <lnet/nidstr.h>
+#include <lustre_nodemap.h>
typedef enum ucred_init_type {
NONE_INIT = 0,
}
static int match_nosquash_list(struct rw_semaphore *sem,
- cfs_list_t *nidlist,
+ struct list_head *nidlist,
lnet_nid_t peernid)
{
int rc;
RETURN(0);
}
+static void ucred_set_jobid(struct mdt_thread_info *info, struct lu_ucred *uc)
+{
+ struct ptlrpc_request *req = mdt_info_req(info);
+ const char *jobid = mdt_req_get_jobid(req);
+
+ /* set jobid if specified. */
+ if (jobid)
+ strlcpy(uc->uc_jobid, jobid, sizeof(uc->uc_jobid));
+ else
+ uc->uc_jobid[0] = '\0';
+}
+
static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
void *buf)
{
if (remote) {
if (!uid_valid(make_kuid(&init_user_ns, req->rq_auth_mapped_uid))) {
CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
- CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
RETURN(-EACCES);
}
ucred->uc_cap &= ~(CFS_CAP_SYS_RESOURCE_MASK |
CFS_CAP_CHOWN_MASK);
ucred->uc_valid = UCRED_NEW;
+ ucred_set_jobid(info, ucred);
EXIT;
return rc;
}
+/**
+ * Check whether allow the client to set supplementary group IDs or not.
+ *
+ * \param[in] info pointer to the thread context
+ * \param[in] uc pointer to the RPC user descriptor
+ *
+ * \retval true if allow to set supplementary group IDs
+ * \retval false for other cases
+ */
+bool allow_client_chgrp(struct mdt_thread_info *info, struct lu_ucred *uc)
+{
+ __u32 remote = exp_connect_rmtclient(info->mti_exp);
+ __u32 perm;
+
+ /* 1. If identity_upcall is disabled, then forbid remote client to set
+ * supplementary group IDs, but permit local client to do that. */
+ if (is_identity_get_disabled(info->mti_mdt->mdt_identity_cache)) {
+ if (remote)
+ return false;
+
+ return true;
+ }
+
+ /* 2. If fail to get related identities, then forbid any client to
+ * set supplementary group IDs. */
+ if (uc->uc_identity == NULL)
+ return false;
+
+ /* 3. Check the permission in the identities. */
+ perm = mdt_identity_get_perm(uc->uc_identity, remote,
+ mdt_info_req(info)->rq_peer.nid);
+ if (perm & CFS_SETGRP_PERM)
+ return true;
+
+ return false;
+}
+
int mdt_check_ucred(struct mdt_thread_info *info)
{
struct ptlrpc_request *req = mdt_info_req(info);
return rc;
}
+static void mdt_squash_nodemap_id(struct lu_ucred *ucred,
+ struct lu_nodemap *nodemap)
+{
+ if (ucred->uc_o_uid == nodemap->nm_squash_uid) {
+ ucred->uc_fsuid = nodemap->nm_squash_uid;
+ ucred->uc_fsgid = nodemap->nm_squash_gid;
+ ucred->uc_cap = 0;
+ ucred->uc_suppgids[0] = -1;
+ ucred->uc_suppgids[1] = -1;
+ }
+}
+
+
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;
-
+ struct lu_ucred *uc = mdt_ucred(info);
+ struct mdt_device *mdt = info->mti_mdt;
+ struct md_identity *identity = NULL;
+ struct lu_nodemap *nodemap =
+ info->mti_exp->exp_target_data.ted_nodemap;
ENTRY;
+ body->mbo_uid = nodemap_map_id(nodemap, NODEMAP_UID,
+ NODEMAP_CLIENT_TO_FS, body->mbo_uid);
+ body->mbo_gid = nodemap_map_id(nodemap, NODEMAP_GID,
+ NODEMAP_CLIENT_TO_FS, body->mbo_gid);
+ body->mbo_fsuid = nodemap_map_id(nodemap, NODEMAP_UID,
+ NODEMAP_CLIENT_TO_FS, body->mbo_fsuid);
+ body->mbo_fsgid = nodemap_map_id(nodemap, NODEMAP_GID,
+ NODEMAP_CLIENT_TO_FS, body->mbo_fsgid);
+
LASSERT(uc != NULL);
uc->uc_valid = UCRED_INVALID;
uc->uc_o_uid = uc->uc_uid = body->mbo_uid;
}
uc->uc_identity = identity;
+ mdt_squash_nodemap_id(uc, nodemap);
+
/* process root_squash here. */
mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid);
else
uc->uc_cap = body->mbo_capability;
uc->uc_valid = UCRED_OLD;
+ ucred_set_jobid(info, uc);
RETURN(0);
}
static int old_init_ucred_reint(struct mdt_thread_info *info)
{
- struct lu_ucred *uc = mdt_ucred(info);
- struct mdt_device *mdt = info->mti_mdt;
- struct md_identity *identity = NULL;
-
+ struct lu_ucred *uc = mdt_ucred(info);
+ struct mdt_device *mdt = info->mti_mdt;
+ struct md_identity *identity = NULL;
+ struct lu_nodemap *nodemap =
+ info->mti_exp->exp_target_data.ted_nodemap;
ENTRY;
LASSERT(uc != NULL);
+
+ uc->uc_fsuid = nodemap_map_id(nodemap, NODEMAP_UID,
+ NODEMAP_CLIENT_TO_FS, uc->uc_fsuid);
+ uc->uc_fsgid = nodemap_map_id(nodemap, NODEMAP_GID,
+ NODEMAP_CLIENT_TO_FS, uc->uc_fsgid);
+
uc->uc_valid = UCRED_INVALID;
uc->uc_o_uid = uc->uc_o_fsuid = uc->uc_uid = uc->uc_fsuid;
uc->uc_o_gid = uc->uc_o_fsgid = uc->uc_gid = uc->uc_fsgid;
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 (uc->uc_fsuid)
uc->uc_cap &= ~CFS_CAP_FS_MASK;
uc->uc_valid = UCRED_OLD;
+ ucred_set_jobid(info, uc);
RETURN(0);
}
static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
{
- struct lu_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 mdt_reint_record *rr = &info->mti_rr;
- struct mdt_rec_setattr *rec;
+ struct lu_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 mdt_reint_record *rr = &info->mti_rr;
+ struct mdt_rec_setattr *rec;
+ struct lu_nodemap *nodemap =
+ info->mti_exp->exp_target_data.ted_nodemap;
ENTRY;
CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint));
(rec->sa_valid & MDS_ATTR_CTIME))
la->la_valid |= LA_CTIME;
}
- la->la_mode = rec->sa_mode;
- la->la_flags = rec->sa_attr_flags;
- la->la_uid = rec->sa_uid;
- la->la_gid = rec->sa_gid;
- la->la_size = rec->sa_size;
- la->la_blocks = rec->sa_blocks;
- la->la_ctime = rec->sa_ctime;
- la->la_atime = rec->sa_atime;
- la->la_mtime = rec->sa_mtime;
- ma->ma_valid = MA_INODE;
+ la->la_mode = rec->sa_mode;
+ la->la_flags = rec->sa_attr_flags;
+ la->la_uid = nodemap_map_id(nodemap, NODEMAP_UID,
+ NODEMAP_CLIENT_TO_FS, rec->sa_uid);
+ la->la_gid = nodemap_map_id(nodemap, NODEMAP_GID,
+ NODEMAP_CLIENT_TO_FS, rec->sa_gid);
+ la->la_size = rec->sa_size;
+ la->la_blocks = rec->sa_blocks;
+ la->la_ctime = rec->sa_ctime;
+ la->la_atime = rec->sa_atime;
+ la->la_mtime = rec->sa_mtime;
+ ma->ma_valid = MA_INODE;
if (rec->sa_bias & MDS_DATA_MODIFIED)
ma->ma_attr_flags |= MDS_DATA_MODIFIED;