コード例 #1
0
ファイル: mdt_lib.c プロジェクト: hocks/lustre-release
static int mdt_rename_unpack(struct mdt_thread_info *info)
{
	struct lu_ucred         *uc = mdt_ucred(info);
        struct mdt_rec_rename   *rec;
        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;
        int rc;
        ENTRY;

        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);

	/* This prior initialization is needed for old_init_ucred_reint() */
	uc->uc_fsuid = rec->rn_fsuid;
	uc->uc_fsgid = rec->rn_fsgid;
	uc->uc_cap   = rec->rn_cap;
	uc->uc_suppgids[0] = rec->rn_suppgid1;
	uc->uc_suppgids[1] = rec->rn_suppgid2;

        attr->la_uid = rec->rn_fsuid;
        attr->la_gid = rec->rn_fsgid;
        rr->rr_fid1 = &rec->rn_fid1;
        rr->rr_fid2 = &rec->rn_fid2;
        attr->la_ctime = rec->rn_time;
        attr->la_mtime = rec->rn_time;
        /* rename_tgt contains the mode already */
        attr->la_mode = rec->rn_mode;
        attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;

        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));
        if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
                mdt_set_capainfo(info, 1, rr->rr_fid2,
                                 req_capsule_client_get(pill, &RMF_CAPA2));

	rc = mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, 0);
	if (rc < 0)
		RETURN(rc);

	rc = mdt_name_unpack(pill, &RMF_SYMTGT, &rr->rr_tgt_name, 0);
	if (rc < 0)
		RETURN(rc);

        if (rec->rn_bias & MDS_VTX_BYPASS)
                ma->ma_attr_flags |= MDS_VTX_BYPASS;
        else
                ma->ma_attr_flags &= ~MDS_VTX_BYPASS;

        info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info));


	rc = mdt_dlmreq_unpack(info);

	RETURN(rc);
}
コード例 #2
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
/* 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);
}
コード例 #3
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;
        ENTRY;

        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);

	/* This prior initialization is needed for old_init_ucred_reint() */
	uc->uc_fsuid = rec->sa_fsuid;
	uc->uc_fsgid = rec->sa_fsgid;
	uc->uc_cap   = rec->sa_cap;
	uc->uc_suppgids[0] = rec->sa_suppgid;
	uc->uc_suppgids[1] = -1;

        rr->rr_fid1 = &rec->sa_fid;
	la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
	/*  If MDS_ATTR_xTIME is set without MDS_ATTR_xTIME_SET and
	 *  the client does not have OBD_CONNECT_FULL20, convert it
	 *  to LA_xTIME. LU-3036 */
	if (!(exp_connect_flags(info->mti_exp) & OBD_CONNECT_FULL20)) {
		if (!(rec->sa_valid & MDS_ATTR_ATIME_SET) &&
		     (rec->sa_valid & MDS_ATTR_ATIME))
			la->la_valid |= LA_ATIME;
		if (!(rec->sa_valid & MDS_ATTR_MTIME_SET) &&
		     (rec->sa_valid & MDS_ATTR_MTIME))
			la->la_valid |= LA_MTIME;
		if (!(rec->sa_valid & MDS_ATTR_CTIME_SET) &&
		     (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;

	if (rec->sa_bias & MDS_DATA_MODIFIED)
		ma->ma_attr_flags |= MDS_DATA_MODIFIED;
	else
		ma->ma_attr_flags &= ~MDS_DATA_MODIFIED;

        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));

        RETURN(0);
}
コード例 #4
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
static int mdt_rename_unpack(struct mdt_thread_info *info)
{
        struct md_ucred         *uc = mdt_ucred(info);
        struct mdt_rec_rename   *rec;
        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;
        int rc;
        ENTRY;

        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);

        uc->mu_fsuid = rec->rn_fsuid;
        uc->mu_fsgid = rec->rn_fsgid;
        uc->mu_cap   = rec->rn_cap;
        uc->mu_suppgids[0] = rec->rn_suppgid1;
        uc->mu_suppgids[1] = rec->rn_suppgid2;

        attr->la_uid = rec->rn_fsuid;
        attr->la_gid = rec->rn_fsgid;
        rr->rr_fid1 = &rec->rn_fid1;
        rr->rr_fid2 = &rec->rn_fid2;
        attr->la_ctime = rec->rn_time;
        attr->la_mtime = rec->rn_time;
        /* rename_tgt contains the mode already */
        attr->la_mode = rec->rn_mode;
        attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;

        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));
        if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
                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;
        rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
        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;

        info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info));

        rc = mdt_dlmreq_unpack(info);
        RETURN(rc);
}
コード例 #5
0
ファイル: mdt_xattr.c プロジェクト: hocks/lustre-release
static int mdt_getxattr_all(struct mdt_thread_info *info,
			    struct mdt_body *reqbody, struct mdt_body *repbody,
			    struct lu_buf *buf, struct md_object *next)
{
	const struct lu_env *env = info->mti_env;
	struct ptlrpc_request *req = mdt_info_req(info);
	struct mdt_export_data *med = mdt_req2med(req);
	struct lu_ucred        *uc  = mdt_ucred(info);
	char *v, *b, *eadatahead, *eadatatail;
	__u32 *sizes;
	int eadatasize, eavallen = 0, eavallens = 0, rc;

	ENTRY;

	/*
	 * The format of the pill is the following:
	 * EADATA:      attr1\0attr2\0...attrn\0
	 * EAVALS:      val1val2...valn
	 * EAVALS_LENS: 4,4,...4
	 */

	eadatahead = buf->lb_buf;

	/* Fill out EADATA first */
	eadatasize = mo_xattr_list(env, next, buf);
	if (eadatasize < 0)
		GOTO(out, rc = eadatasize);

	eadatatail = eadatahead + eadatasize;

	v = req_capsule_server_get(info->mti_pill, &RMF_EAVALS);
	sizes = req_capsule_server_get(info->mti_pill, &RMF_EAVALS_LENS);

	/* Fill out EAVALS and EAVALS_LENS */
	for (b = eadatahead; b < eadatatail; b += strlen(b) + 1, v += rc) {
		buf->lb_buf = v;
		buf->lb_len = reqbody->eadatasize - eavallen;
		rc = mdt_getxattr_one(info, b, next, buf, med, uc);
		if (rc < 0)
			GOTO(out, rc);

		sizes[eavallens] = rc;
		eavallens++;
		eavallen += rc;
	}

	repbody->aclsize = eavallen;
	repbody->max_mdsize = eavallens;

	req_capsule_shrink(info->mti_pill, &RMF_EAVALS, eavallen, RCL_SERVER);
	req_capsule_shrink(info->mti_pill, &RMF_EAVALS_LENS,
			   eavallens * sizeof(__u32), RCL_SERVER);
	req_capsule_shrink(info->mti_pill, &RMF_EADATA, eadatasize, RCL_SERVER);

	GOTO(out, rc = eadatasize);
out:
	return rc;
}
コード例 #6
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
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);
}
コード例 #7
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
int mdt_init_ucred_reint(struct mdt_thread_info *info)
{
        struct ptlrpc_request *req = mdt_info_req(info);
        struct md_ucred       *uc  = mdt_ucred(info);

        if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
                return 0;

        mdt_exit_ucred(info);

        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
                return old_init_ucred_reint(info);
        else
                return new_init_ucred(info, REC_INIT, NULL);
}
コード例 #8
0
ファイル: mdt_idmap.c プロジェクト: DCteam/lustre
/* Do not ignore root_squash for non-setattr case. */
int mdt_fix_attr_ucred(struct mdt_thread_info *info, __u32 op)
{
        struct ptlrpc_request     *req = mdt_info_req(info);
        struct md_ucred           *uc = mdt_ucred(info);
        struct lu_attr            *attr = &info->mti_attr.ma_attr;
        struct mdt_export_data    *med = mdt_req2med(req);
        struct lustre_idmap_table *idmap = med->med_idmap;

        if ((uc->mu_valid != UCRED_OLD) && (uc->mu_valid != UCRED_NEW))
                return -EINVAL;

        if (op != REINT_SETATTR) {
                if ((attr->la_valid & LA_UID) && (attr->la_uid != -1))
                        attr->la_uid = uc->mu_fsuid;
                /* for S_ISGID, inherit gid from his parent, such work will be
                 * done in cmm/mdd layer, here set all cases as uc->mu_fsgid. */
                if ((attr->la_valid & LA_GID) && (attr->la_gid != -1))
                        attr->la_gid = uc->mu_fsgid;
        } else if (exp_connect_rmtclient(info->mti_exp)) {
                /* NB: -1 case will be handled by mdt_fix_attr() later. */
                if ((attr->la_valid & LA_UID) && (attr->la_uid != -1)) {
                        uid_t uid = lustre_idmap_lookup_uid(uc, idmap, 0,
                                                            attr->la_uid);

                        if (uid == CFS_IDMAP_NOTFOUND) {
                                CDEBUG(D_SEC, "Deny chown to uid %u\n",
                                       attr->la_uid);
                                return -EPERM;
                        }

                        attr->la_uid = uid;
                }
                if ((attr->la_valid & LA_GID) && (attr->la_gid != -1)) {
                        gid_t gid = lustre_idmap_lookup_gid(uc, idmap, 0,
                                                            attr->la_gid);

                        if (gid == CFS_IDMAP_NOTFOUND) {
                                CDEBUG(D_SEC, "Deny chown to gid %u\n",
                                       attr->la_gid);
                                return -EPERM;
                        }

                        attr->la_gid = gid;
                }
        }

        return 0;
}
コード例 #9
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
static int mdt_link_unpack(struct mdt_thread_info *info)
{
        struct md_ucred         *uc  = mdt_ucred(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;
        int rc;
        ENTRY;

        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);

        uc->mu_fsuid = rec->lk_fsuid;
        uc->mu_fsgid = rec->lk_fsgid;
        uc->mu_cap   = rec->lk_cap;
        uc->mu_suppgids[0] = rec->lk_suppgid1;
        uc->mu_suppgids[1] = rec->lk_suppgid2;

        attr->la_uid = rec->lk_fsuid;
        attr->la_gid = rec->lk_fsgid;
        rr->rr_fid1 = &rec->lk_fid1;
        rr->rr_fid2 = &rec->lk_fid2;
        attr->la_ctime = rec->lk_time;
        attr->la_mtime = rec->lk_time;
        attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;

        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));
        if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
                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;
        if (!info->mti_cross_ref)
                LASSERT(rr->rr_namelen > 0);

        rc = mdt_dlmreq_unpack(info);
        RETURN(rc);
}
コード例 #10
0
ファイル: mdt_lib.c プロジェクト: hocks/lustre-release
int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
{
        struct ptlrpc_request *req = mdt_info_req(info);
	struct lu_ucred       *uc  = mdt_ucred(info);

	LASSERT(uc != NULL);
	if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW))
		return 0;

        mdt_exit_ucred(info);

        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
                return old_init_ucred(info, body);
        else
                return new_init_ucred(info, BODY_INIT, body);
}
コード例 #11
0
static int mdt_link_unpack(struct mdt_thread_info *info)
{
	struct lu_ucred         *uc  = mdt_ucred(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;
        int rc;
        ENTRY;

        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);

	/* This prior initialization is needed for old_init_ucred_reint() */
	uc->uc_fsuid = rec->lk_fsuid;
	uc->uc_fsgid = rec->lk_fsgid;
	uc->uc_cap   = rec->lk_cap;
	uc->uc_suppgids[0] = rec->lk_suppgid1;
	uc->uc_suppgids[1] = rec->lk_suppgid2;

        attr->la_uid = rec->lk_fsuid;
        attr->la_gid = rec->lk_fsgid;
        rr->rr_fid1 = &rec->lk_fid1;
        rr->rr_fid2 = &rec->lk_fid2;
        attr->la_ctime = rec->lk_time;
        attr->la_mtime = rec->lk_time;
        attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;

        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));
        if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
                mdt_set_capainfo(info, 1, rr->rr_fid2,
                                 req_capsule_client_get(pill, &RMF_CAPA2));

        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);

        rc = mdt_dlmreq_unpack(info);
        RETURN(rc);
}
コード例 #12
0
ファイル: mdt_xattr.c プロジェクト: LLNL/lustre
static int mdt_rmtlsetfacl(struct mdt_thread_info *info,
                           struct md_object *next,
                           const char *xattr_name,
                           ext_acl_xattr_header *header,
                           posix_acl_xattr_header **out)
{
        struct ptlrpc_request  *req = mdt_info_req(info);
        struct mdt_export_data *med = mdt_req2med(req);
        struct md_ucred        *uc = mdt_ucred(info);
        struct lu_buf          *buf = &info->mti_buf;
        int                     rc;
        ENTRY;

        rc = lustre_ext_acl_xattr_id2server(uc, med->med_idmap, header);
        if (rc)
                RETURN(rc);

        rc = mo_xattr_get(info->mti_env, next, &LU_BUF_NULL, xattr_name);
        if (rc == -ENODATA)
                rc = 0;
        else if (rc < 0)
                RETURN(rc);

        buf->lb_len = rc;
        if (buf->lb_len > 0) {
                OBD_ALLOC_LARGE(buf->lb_buf, buf->lb_len);
                if (unlikely(buf->lb_buf == NULL))
                        RETURN(-ENOMEM);

                rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
                if (rc < 0) {
                        CERROR("getxattr failed: %d\n", rc);
                        GOTO(_out, rc);
                }
        } else
                buf->lb_buf = NULL;

        rc = lustre_acl_xattr_merge2posix((posix_acl_xattr_header *)(buf->lb_buf),
                                          buf->lb_len, header, out);
        EXIT;

_out:
        if (rc <= 0 && buf->lb_buf != NULL)
                OBD_FREE_LARGE(buf->lb_buf, buf->lb_len);
        return rc;
}
コード例 #13
0
ファイル: mdt_lib.c プロジェクト: hocks/lustre-release
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);
}
コード例 #14
0
ファイル: mdt_hsm.c プロジェクト: bhanug/lustre
static inline bool mdt_hsm_is_admin(struct mdt_thread_info *info)
{
	bool is_admin;
	int rc;

	if (info->mti_body == NULL)
		return false;

	rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
	if (rc < 0)
		return false;

	is_admin = md_capable(mdt_ucred(info), CFS_CAP_SYS_ADMIN);

	mdt_exit_ucred(info);

	return is_admin;
}
コード例 #15
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
void mdt_exit_ucred(struct mdt_thread_info *info)
{
        struct md_ucred   *uc  = mdt_ucred(info);
        struct mdt_device *mdt = info->mti_mdt;

        if (uc->mu_valid != UCRED_INIT) {
                uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
                if (uc->mu_ginfo) {
                        cfs_put_group_info(uc->mu_ginfo);
                        uc->mu_ginfo = NULL;
                }
                if (uc->mu_identity) {
                        mdt_identity_put(mdt->mdt_identity_cache,
                                         uc->mu_identity);
                        uc->mu_identity = NULL;
                }
                uc->mu_valid = UCRED_INIT;
        }
}
コード例 #16
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
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 mdt_reint_record *rr = &info->mti_rr;
        struct mdt_rec_setattr  *rec;
        ENTRY;

        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);

        uc->mu_fsuid = rec->sa_fsuid;
        uc->mu_fsgid = rec->sa_fsgid;
        uc->mu_cap   = rec->sa_cap;
        uc->mu_suppgids[0] = rec->sa_suppgid;
        uc->mu_suppgids[1] = -1;

        rr->rr_fid1 = &rec->sa_fid;
        la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma);
        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;

        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));

        RETURN(0);
}
コード例 #17
0
ファイル: mdt_idmap.c プロジェクト: bacaldwell/lustre
/*
 * Reverse mapping
 */
void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
{
        struct ptlrpc_request     *req = mdt_info_req(info);
	struct lu_ucred           *uc = mdt_ucred(info);
        struct mdt_export_data    *med = mdt_req2med(req);
        struct lustre_idmap_table *idmap = med->med_idmap;

        if (!exp_connect_rmtclient(info->mti_exp))
                return;

	if (body->mbo_valid & OBD_MD_FLUID) {
		uid_t uid;

		uid = lustre_idmap_lookup_uid(uc, idmap, 1, body->mbo_uid);

		if (uid == CFS_IDMAP_NOTFOUND) {
			uid = NOBODY_UID;
			if (body->mbo_valid & OBD_MD_FLMODE)
				body->mbo_mode = (body->mbo_mode & ~S_IRWXU) |
					     ((body->mbo_mode & S_IRWXO) << 6);
		}

		body->mbo_uid = uid;
	}

	if (body->mbo_valid & OBD_MD_FLGID) {
		gid_t gid;

		gid = lustre_idmap_lookup_gid(uc, idmap, 1, body->mbo_gid);

		if (gid == CFS_IDMAP_NOTFOUND) {
			gid = NOBODY_GID;
			if (body->mbo_valid & OBD_MD_FLMODE)
				body->mbo_mode = (body->mbo_mode & ~S_IRWXG) |
					     ((body->mbo_mode & S_IRWXO) << 3);
		}

		body->mbo_gid = gid;
        }
}
コード例 #18
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
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);
}
コード例 #19
0
ファイル: mdt_xattr.c プロジェクト: LLNL/lustre
int mdt_reint_setxattr(struct mdt_thread_info *info,
                       struct mdt_lock_handle *unused)
{
        struct ptlrpc_request   *req = mdt_info_req(info);
        struct md_ucred         *uc  = mdt_ucred(info);
        struct mdt_lock_handle  *lh;
        const struct lu_env     *env  = info->mti_env;
        struct lu_buf           *buf  = &info->mti_buf;
        struct mdt_reint_record *rr   = &info->mti_rr;
        struct md_attr          *ma = &info->mti_attr;
        struct lu_attr          *attr = &info->mti_attr.ma_attr;
        struct mdt_object       *obj;
        struct md_object        *child;
        __u64                    valid = attr->la_valid;
        const char              *xattr_name = rr->rr_name;
        int                      xattr_len = rr->rr_eadatalen;
        __u64                    lockpart;
        int                      rc;
        posix_acl_xattr_header  *new_xattr = NULL;
        __u32                    remote = exp_connect_rmtclient(info->mti_exp);
        __u32                    perm;
        ENTRY;

        CDEBUG(D_INODE, "setxattr for "DFID"\n", PFID(rr->rr_fid1));

        if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SETXATTR))
                RETURN(err_serious(-ENOMEM));

        CDEBUG(D_INODE, "%s xattr %s\n",
               valid & OBD_MD_FLXATTR ? "set" : "remove", xattr_name);

        rc = mdt_init_ucred_reint(info);
        if (rc != 0)
                RETURN(rc);

        if (valid & OBD_MD_FLRMTRSETFACL) {
                if (unlikely(!remote))
                        GOTO(out, rc = err_serious(-EINVAL));

                perm = mdt_identity_get_perm(uc->mu_identity, remote,
                                             req->rq_peer.nid);
                if (!(perm & CFS_RMTACL_PERM))
                        GOTO(out, rc = err_serious(-EPERM));
        }

        if (strncmp(xattr_name, XATTR_USER_PREFIX,
                    sizeof(XATTR_USER_PREFIX) - 1) == 0) {
                if (!(req->rq_export->exp_connect_flags & OBD_CONNECT_XATTR))
                        GOTO(out, rc = -EOPNOTSUPP);
                if (strcmp(xattr_name, XATTR_NAME_LOV) == 0)
                        GOTO(out, rc = -EACCES);
                if (strcmp(xattr_name, XATTR_NAME_LMA) == 0)
                        GOTO(out, rc = 0);
                if (strcmp(xattr_name, XATTR_NAME_LINK) == 0)
                        GOTO(out, rc = 0);
        } else if ((valid & OBD_MD_FLXATTR) &&
                   (strncmp(xattr_name, XATTR_NAME_ACL_ACCESS,
                            sizeof(XATTR_NAME_ACL_ACCESS) - 1) == 0 ||
                    strncmp(xattr_name, XATTR_NAME_ACL_DEFAULT,
                            sizeof(XATTR_NAME_ACL_DEFAULT) - 1) == 0)) {
                /* currently lustre limit acl access size */
                if (xattr_len > LUSTRE_POSIX_ACL_MAX_SIZE)
                        GOTO(out, -ERANGE);
        }

        lockpart = MDS_INODELOCK_UPDATE;
        /* Revoke all clients' lookup lock, since the access
         * permissions for this inode is changed when ACL_ACCESS is
         * set. This isn't needed for ACL_DEFAULT, since that does
         * not change the access permissions of this inode, nor any
         * other existing inodes. It is setting the ACLs inherited
         * by new directories/files at create time. */
        if (!strcmp(xattr_name, XATTR_NAME_ACL_ACCESS))
                lockpart |= MDS_INODELOCK_LOOKUP;

        lh = &info->mti_lh[MDT_LH_PARENT];
        /* ACLs were sent to clients under LCK_CR locks, so taking LCK_EX
         * to cancel them. */
        mdt_lock_reg_init(lh, LCK_EX);
        obj = mdt_object_find_lock(info, rr->rr_fid1, lh, lockpart);
        if (IS_ERR(obj))
                GOTO(out, rc =  PTR_ERR(obj));

        info->mti_mos = obj;
        rc = mdt_version_get_check_save(info, obj, 0);
        if (rc)
                GOTO(out_unlock, rc);

        if (unlikely(!(valid & OBD_MD_FLCTIME))) {
                /* This isn't strictly an error, but all current clients
                 * should set OBD_MD_FLCTIME when setting attributes. */
                CWARN("%s: client miss to set OBD_MD_FLCTIME when "
                      "setxattr %s: [object "DFID"] [valid "LPU64"]\n",
                      info->mti_exp->exp_obd->obd_name, xattr_name,
                      PFID(rr->rr_fid1), valid);
                attr->la_ctime = cfs_time_current_sec();
        }
        attr->la_valid = LA_CTIME;
        child = mdt_object_child(obj);
        if (valid & OBD_MD_FLXATTR) {
                char *xattr = (void *)rr->rr_eadata;

                if (xattr_len > 0) {
                        int flags = 0;

                        if (valid & OBD_MD_FLRMTLSETFACL) {
                                if (unlikely(!remote))
                                        GOTO(out_unlock, rc = -EINVAL);

                                xattr_len = mdt_rmtlsetfacl(info, child,
                                                xattr_name,
                                                (ext_acl_xattr_header *)xattr,
                                                &new_xattr);
                                if (xattr_len < 0)
                                        GOTO(out_unlock, rc = xattr_len);

                                xattr = (char *)new_xattr;
                        }

                        if (attr->la_flags & XATTR_REPLACE)
                                flags |= LU_XATTR_REPLACE;

                        if (attr->la_flags & XATTR_CREATE)
                                flags |= LU_XATTR_CREATE;

                        mdt_fail_write(env, info->mti_mdt->mdt_bottom,
                                       OBD_FAIL_MDS_SETXATTR_WRITE);

                        buf->lb_buf = xattr;
                        buf->lb_len = xattr_len;
                        rc = mo_xattr_set(env, child, buf, xattr_name, flags);
                        /* update ctime after xattr changed */
                        if (rc == 0) {
                                ma->ma_attr_flags |= MDS_PERM_BYPASS;
                                mo_attr_set(env, child, ma);
                        }
                }
        } else if (valid & OBD_MD_FLXATTRRM) {
                rc = mo_xattr_del(env, child, xattr_name);
                /* update ctime after xattr changed */
                if (rc == 0) {
                        ma->ma_attr_flags |= MDS_PERM_BYPASS;
                        mo_attr_set(env, child, ma);
                }
        } else {
                CDEBUG(D_INFO, "valid bits: "LPX64"\n", valid);
                rc = -EINVAL;
        }
        if (rc == 0)
                mdt_counter_incr(req->rq_export, LPROC_MDT_SETXATTR);

        EXIT;
out_unlock:
        mdt_object_unlock_put(info, obj, lh, rc);
        if (unlikely(new_xattr != NULL))
                lustre_posix_acl_xattr_free(new_xattr, xattr_len);
out:
        mdt_exit_ucred(info);
        return rc;
}
コード例 #20
0
ファイル: mdt_xattr.c プロジェクト: LLNL/lustre
int mdt_getxattr(struct mdt_thread_info *info)
{
        struct ptlrpc_request  *req = mdt_info_req(info);
        struct mdt_export_data *med = mdt_req2med(req);
        struct md_ucred        *uc  = mdt_ucred(info);
        struct mdt_body        *reqbody;
        struct mdt_body        *repbody = NULL;
        struct md_object       *next;
        struct lu_buf          *buf;
        __u32                   remote = exp_connect_rmtclient(info->mti_exp);
        __u32                   perm;
        int                     easize, rc;
        ENTRY;

        LASSERT(info->mti_object != NULL);
        LASSERT(lu_object_assert_exists(&info->mti_object->mot_obj.mo_lu));

        CDEBUG(D_INODE, "getxattr "DFID"\n", PFID(&info->mti_body->fid1));

        reqbody = req_capsule_client_get(info->mti_pill, &RMF_MDT_BODY);
        if (reqbody == NULL)
                RETURN(err_serious(-EFAULT));

        rc = mdt_init_ucred(info, reqbody);
        if (rc)
                RETURN(err_serious(rc));

        next = mdt_object_child(info->mti_object);

        if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL) {
                if (unlikely(!remote))
                        GOTO(out, rc = err_serious(-EINVAL));

                perm = mdt_identity_get_perm(uc->mu_identity, remote,
                                             req->rq_peer.nid);
                if (!(perm & CFS_RMTACL_PERM))
                        GOTO(out, rc = err_serious(-EPERM));

                rc = mo_permission(info->mti_env, NULL, next, NULL,
                                   MAY_RGETFACL);
                if (rc)
                        GOTO(out, rc = err_serious(rc));
        }

        easize = mdt_getxattr_pack_reply(info);
        if (easize < 0)
                GOTO(out, rc = err_serious(easize));

        repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
        LASSERT(repbody != NULL);

        /* No need further getxattr. */
        if (easize == 0 || reqbody->eadatasize == 0)
                GOTO(out, rc = easize);


        buf = &info->mti_buf;
        buf->lb_buf = req_capsule_server_get(info->mti_pill, &RMF_EADATA);
        buf->lb_len = easize;

        if (info->mti_body->valid & OBD_MD_FLXATTR) {
                int flags = CFS_IC_NOTHING;
                char *xattr_name = req_capsule_client_get(info->mti_pill,
                                                          &RMF_NAME);
                CDEBUG(D_INODE, "getxattr %s\n", xattr_name);

                rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
                if (rc < 0) {
                        CERROR("getxattr failed: %d\n", rc);
                        GOTO(out, rc);
                }

                if (info->mti_body->valid &
                    (OBD_MD_FLRMTLSETFACL | OBD_MD_FLRMTLGETFACL))
                        flags = CFS_IC_ALL;
                else if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL)
                        flags = CFS_IC_MAPPED;

                if (rc > 0 && flags != CFS_IC_NOTHING) {
                        int rc1;

                        if (unlikely(!remote))
                                GOTO(out, rc = -EINVAL);

                        rc1 = lustre_posix_acl_xattr_id2client(uc,
                                        med->med_idmap,
                                        (posix_acl_xattr_header *)(buf->lb_buf),
                                        rc, flags);
                        if (unlikely(rc1 < 0))
                                rc = rc1;
                }
        } else if (info->mti_body->valid & OBD_MD_FLXATTRLS) {
                CDEBUG(D_INODE, "listxattr\n");

                rc = mo_xattr_list(info->mti_env, next, buf);
                if (rc < 0)
                        CDEBUG(D_INFO, "listxattr failed: %d\n", rc);
        } else
                LBUG();

        EXIT;
out:
        if (rc >= 0) {
                mdt_counter_incr(req->rq_export, LPROC_MDT_GETXATTR);
                repbody->eadatasize = rc;
                rc = 0;
        }
        mdt_exit_ucred(info);
        return rc;
}
コード例 #21
0
ファイル: mdt_lib.c プロジェクト: hocks/lustre-release
static int mdt_create_unpack(struct mdt_thread_info *info)
{
	struct lu_ucred         *uc  = mdt_ucred(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 md_op_spec       *sp = &info->mti_spec;
        int rc;
        ENTRY;

        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);

	/* This prior initialization is needed for old_init_ucred_reint() */
	uc->uc_fsuid = rec->cr_fsuid;
	uc->uc_fsgid = rec->cr_fsgid;
	uc->uc_cap   = rec->cr_cap;
	uc->uc_suppgids[0] = rec->cr_suppgid1;
	uc->uc_suppgids[1] = -1;
	uc->uc_umask = rec->cr_umask;

        rr->rr_fid1 = &rec->cr_fid1;
        rr->rr_fid2 = &rec->cr_fid2;
        attr->la_mode = rec->cr_mode;
        attr->la_rdev  = rec->cr_rdev;
        attr->la_uid   = rec->cr_fsuid;
        attr->la_gid   = rec->cr_fsgid;
        attr->la_ctime = rec->cr_time;
        attr->la_mtime = rec->cr_time;
        attr->la_atime = rec->cr_time;
	attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID | LA_TYPE |
			 LA_CTIME | LA_MTIME | LA_ATIME;
        memset(&sp->u, 0, sizeof(sp->u));
        sp->sp_cr_flags = get_mrc_cr_flags(rec);

        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));
        mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);

	rc = mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, 0);
	if (rc < 0)
		RETURN(rc);

	if (S_ISLNK(attr->la_mode)) {
                const char *tgt = NULL;

                req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
                if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
                        tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
                        sp->u.sp_symname = tgt;
                }
                if (tgt == NULL)
                        RETURN(-EFAULT);
        } else {
                req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
		if (S_ISDIR(attr->la_mode) &&
		    req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT) > 0) {
			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);
			sp->sp_cr_flags |= MDS_OPEN_HAS_EA;
		}
	}

	rc = mdt_dlmreq_unpack(info);
	RETURN(rc);
}
コード例 #22
0
ファイル: mdt_lib.c プロジェクト: hocks/lustre-release
static int mdt_setxattr_unpack(struct mdt_thread_info *info)
{
	struct mdt_reint_record	*rr	= &info->mti_rr;
	struct lu_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;
	int			 rc;
	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);

	/* This prior initialization is needed for old_init_ucred_reint() */
	uc->uc_fsuid  = rec->sx_fsuid;
	uc->uc_fsgid  = rec->sx_fsgid;
	uc->uc_cap    = rec->sx_cap;
	uc->uc_suppgids[0] = rec->sx_suppgid1;
	uc->uc_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);

	rc = mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, 0);
	if (rc < 0)
		RETURN(rc);

        if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
                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);
                } else {
                        rr->rr_eadata = NULL;
                }
        } else if (!(attr->la_valid & OBD_MD_FLXATTRRM)) {
                CDEBUG(D_INFO, "no xattr data supplied\n");
                RETURN(-EFAULT);
        }

	if (mdt_dlmreq_unpack(info) < 0)
		RETURN(-EPROTO);

        RETURN(0);
}
コード例 #23
0
ファイル: mdt_lib.c プロジェクト: hocks/lustre-release
static int mdt_open_unpack(struct mdt_thread_info *info)
{
	struct lu_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 mdt_reint_record *rr   = &info->mti_rr;
        struct ptlrpc_request   *req  = mdt_info_req(info);
        struct md_op_spec       *sp   = &info->mti_spec;
        ENTRY;

        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);

	/* This prior initialization is needed for old_init_ucred_reint() */
	uc->uc_fsuid = rec->cr_fsuid;
	uc->uc_fsgid = rec->cr_fsgid;
	uc->uc_cap   = rec->cr_cap;
	uc->uc_suppgids[0] = rec->cr_suppgid1;
	uc->uc_suppgids[1] = rec->cr_suppgid2;
	uc->uc_umask = rec->cr_umask;

        rr->rr_fid1   = &rec->cr_fid1;
        rr->rr_fid2   = &rec->cr_fid2;
        rr->rr_handle = &rec->cr_old_handle;
        attr->la_mode = rec->cr_mode;
        attr->la_rdev  = rec->cr_rdev;
        attr->la_uid   = rec->cr_fsuid;
        attr->la_gid   = rec->cr_fsgid;
        attr->la_ctime = rec->cr_time;
        attr->la_mtime = rec->cr_time;
        attr->la_atime = rec->cr_time;
        attr->la_valid = LA_MODE  | LA_RDEV  | LA_UID   | LA_GID |
                         LA_CTIME | LA_MTIME | LA_ATIME;
        memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
        info->mti_spec.sp_cr_flags = get_mrc_cr_flags(rec);
        /* Do not trigger ASSERTION if client miss to set such flags. */
        if (unlikely(info->mti_spec.sp_cr_flags == 0))
                RETURN(-EPROTO);
        info->mti_replayepoch = rec->cr_ioepoch;

        info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);

        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));
        if (req_is_replay(req) &&
            req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)) {
#if 0
                mdt_set_capainfo(info, 1, rr->rr_fid2,
                                 req_capsule_client_get(pill, &RMF_CAPA2));
#else
                /*
                 * FIXME: capa in replay open request might have expired,
                 * bypass capa check. Security hole?
                 */
                mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
                mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
#endif
        }

	mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, MNF_FIX_ANON);

        if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
                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);
                        sp->u.sp_ea.eadatalen = rr->rr_eadatalen;
                        sp->u.sp_ea.eadata = rr->rr_eadata;
                        sp->no_create = !!req_is_replay(req);
			mdt_fix_lov_magic(info);
                }

                /*
                 * Client default md_size may be 0 right after client start,
                 * until all osc are connected, set here just some reasonable
                 * value to prevent misbehavior.
                 */
                if (rr->rr_eadatalen == 0 &&
                    !(info->mti_spec.sp_cr_flags & MDS_OPEN_DELAY_CREATE))
			rr->rr_eadatalen = MIN_MD_SIZE;
	}

        RETURN(0);
}
コード例 #24
0
ファイル: mdt_xattr.c プロジェクト: Xyratex/lustre-stable
int mdt_reint_setxattr(struct mdt_thread_info *info,
                       struct mdt_lock_handle *unused)
{
	struct ptlrpc_request	*req = mdt_info_req(info);
	struct mdt_lock_handle	*lh;
	const struct lu_env	*env  = info->mti_env;
	struct lu_buf		*buf  = &info->mti_buf;
	struct mdt_reint_record	*rr   = &info->mti_rr;
	struct md_attr		*ma = &info->mti_attr;
	struct lu_attr		*attr = &info->mti_attr.ma_attr;
	struct mdt_object	*obj;
	struct md_object	*child;
	__u64			 valid = attr->la_valid;
	const char		*xattr_name = rr->rr_name.ln_name;
	int			 xattr_len = rr->rr_eadatalen;
	__u64			 lockpart = MDS_INODELOCK_UPDATE;
	int			 rc;
	ENTRY;

	CDEBUG(D_INODE, "setxattr for "DFID": %s %s\n", PFID(rr->rr_fid1),
	       valid & OBD_MD_FLXATTR ? "set" : "remove", xattr_name);

	if (info->mti_dlm_req)
		ldlm_request_cancel(req, info->mti_dlm_req, 0, LATF_SKIP);

        if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SETXATTR))
                RETURN(err_serious(-ENOMEM));

	rc = mdt_init_ucred_reint(info);
        if (rc != 0)
                RETURN(rc);

	if (strncmp(xattr_name, XATTR_USER_PREFIX,
		    sizeof(XATTR_USER_PREFIX) - 1) == 0) {
		if (!(exp_connect_flags(req->rq_export) & OBD_CONNECT_XATTR))
			GOTO(out, rc = -EOPNOTSUPP);
	} else if (strncmp(xattr_name, XATTR_TRUSTED_PREFIX,
		    sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0) {

		/* setxattr(LMV) with lum is used to shrink dir layout */
		if (strcmp(xattr_name, XATTR_NAME_LMV) == 0) {
			__u32 *magic = rr->rr_eadata;

			/* we don't let to remove LMV? */
			if (!rr->rr_eadata)
				GOTO(out, rc = 0);

			if (le32_to_cpu(*magic) == LMV_USER_MAGIC ||
			    le32_to_cpu(*magic) == LMV_USER_MAGIC_SPECIFIC) {
				rc = mdt_dir_layout_shrink(info);
				GOTO(out, rc);
			}
		}

		if (!md_capable(mdt_ucred(info), CFS_CAP_SYS_ADMIN))
			GOTO(out, rc = -EPERM);

		if (strcmp(xattr_name, XATTR_NAME_LOV) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_LMA) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_LMV) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_LINK) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_FID) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_VERSION) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_SOM) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_HSM) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_LFSCK_NAMESPACE) == 0)
			GOTO(out, rc = 0);
	} else if ((valid & OBD_MD_FLXATTR) &&
		   (strcmp(xattr_name, XATTR_NAME_ACL_ACCESS) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_ACL_DEFAULT) == 0)) {
		rc = mdt_nodemap_map_acl(info, rr->rr_eadata, xattr_len,
					 xattr_name, NODEMAP_CLIENT_TO_FS);
		if (rc < 0)
			GOTO(out, rc);
		/* ACLs were mapped out, return an error so the user knows */
		if (rc != xattr_len)
			GOTO(out, rc = -EPERM);
	} else if ((strlen(xattr_name) > strlen(XATTR_LUSTRE_LOV) + 1) &&
		   strncmp(xattr_name, XATTR_LUSTRE_LOV,
			   strlen(XATTR_LUSTRE_LOV)) == 0) {

		if (strncmp(xattr_name, XATTR_LUSTRE_LOV".add",
			    strlen(XATTR_LUSTRE_LOV".add")) &&
		    strncmp(xattr_name, XATTR_LUSTRE_LOV".set",
			    strlen(XATTR_LUSTRE_LOV".set")) &&
		    strncmp(xattr_name, XATTR_LUSTRE_LOV".del",
			    strlen(XATTR_LUSTRE_LOV".del"))) {
			CERROR("%s: invalid xattr name: %s\n",
			       mdt_obd_name(info->mti_mdt), xattr_name);
			GOTO(out, rc = -EINVAL);
		}

		lockpart |= MDS_INODELOCK_LAYOUT;
	}

        /* Revoke all clients' lookup lock, since the access
         * permissions for this inode is changed when ACL_ACCESS is
         * set. This isn't needed for ACL_DEFAULT, since that does
         * not change the access permissions of this inode, nor any
         * other existing inodes. It is setting the ACLs inherited
         * by new directories/files at create time. */
	/* We need revoke both LOOKUP|PERM lock here, see mdt_attr_set. */
        if (!strcmp(xattr_name, XATTR_NAME_ACL_ACCESS))
		lockpart |= MDS_INODELOCK_PERM | MDS_INODELOCK_LOOKUP;
	/* We need to take the lock on behalf of old clients so that newer
	 * clients flush their xattr caches */
	else
		lockpart |= MDS_INODELOCK_XATTR;

        lh = &info->mti_lh[MDT_LH_PARENT];
        /* ACLs were sent to clients under LCK_CR locks, so taking LCK_EX
         * to cancel them. */
        mdt_lock_reg_init(lh, LCK_EX);
        obj = mdt_object_find_lock(info, rr->rr_fid1, lh, lockpart);
	if (IS_ERR(obj))
		GOTO(out, rc = PTR_ERR(obj));

	tgt_vbr_obj_set(env, mdt_obj2dt(obj));
	rc = mdt_version_get_check_save(info, obj, 0);
	if (rc)
		GOTO(out_unlock, rc);

	if (unlikely(!(valid & OBD_MD_FLCTIME))) {
		/* This isn't strictly an error, but all current clients
		 * should set OBD_MD_FLCTIME when setting attributes. */
		CWARN("%s: client miss to set OBD_MD_FLCTIME when "
		      "setxattr %s: [object "DFID"] [valid %llu]\n",
		      mdt_obd_name(info->mti_mdt), xattr_name,
		      PFID(rr->rr_fid1), valid);
		attr->la_ctime = ktime_get_real_seconds();
	}
	attr->la_valid = LA_CTIME;
	child = mdt_object_child(obj);
	if (valid & OBD_MD_FLXATTR) {
		int	flags = 0;

		if (attr->la_flags & XATTR_REPLACE)
			flags |= LU_XATTR_REPLACE;

		if (attr->la_flags & XATTR_CREATE)
			flags |= LU_XATTR_CREATE;

		mdt_fail_write(env, info->mti_mdt->mdt_bottom,
			       OBD_FAIL_MDS_SETXATTR_WRITE);

		buf->lb_buf = rr->rr_eadata;
		buf->lb_len = xattr_len;
		rc = mo_xattr_set(env, child, buf, xattr_name, flags);
		/* update ctime after xattr changed */
		if (rc == 0) {
			ma->ma_attr_flags |= MDS_PERM_BYPASS;
			mo_attr_set(env, child, ma);
		}
        } else if (valid & OBD_MD_FLXATTRRM) {
                rc = mo_xattr_del(env, child, xattr_name);
                /* update ctime after xattr changed */
                if (rc == 0) {
                        ma->ma_attr_flags |= MDS_PERM_BYPASS;
                        mo_attr_set(env, child, ma);
                }
	} else {
		CDEBUG(D_INFO, "valid bits: %#llx\n", valid);
		rc = -EINVAL;
	}

	if (rc == 0)
		mdt_counter_incr(req, LPROC_MDT_SETXATTR);

        EXIT;
out_unlock:
        mdt_object_unlock_put(info, obj, lh, rc);
out:
	mdt_exit_ucred(info);
	return rc;
}
コード例 #25
0
ファイル: mdt_hsm.c プロジェクト: bhanug/lustre
/**
 * Change HSM state and archive number of a file.
 *
 * Archive number is changed iif the value is not 0.
 * The new flagset that will be computed should result in a coherent state.
 * This function checks that flags are compatible.
 *
 * This is MDS_HSM_STATE_SET RPC handler.
 */
int mdt_hsm_state_set(struct tgt_session_info *tsi)
{
	struct mdt_thread_info	*info = tsi2mdt_info(tsi);
	struct mdt_object	*obj = info->mti_object;
	struct md_attr          *ma = &info->mti_attr;
	struct hsm_state_set	*hss;
	struct mdt_lock_handle	*lh;
	int			 rc;
	__u64			 flags;
	ENTRY;

	hss = req_capsule_client_get(info->mti_pill, &RMF_HSM_STATE_SET);

	if (info->mti_body == NULL || obj == NULL || hss == NULL)
		GOTO(out, rc = -EPROTO);

	/* Only valid if client is remote */
	rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
	if (rc < 0)
		GOTO(out, rc = err_serious(rc));

	lh = &info->mti_lh[MDT_LH_CHILD];
	mdt_lock_reg_init(lh, LCK_PW);
	rc = mdt_object_lock(info, obj, lh, MDS_INODELOCK_LOOKUP |
			     MDS_INODELOCK_XATTR);
	if (rc < 0)
		GOTO(out_ucred, rc);

	/* Detect out-of range masks */
	if ((hss->hss_setmask | hss->hss_clearmask) & ~HSM_FLAGS_MASK) {
		CDEBUG(D_HSM, "Incompatible masks provided (set "LPX64
		       ", clear "LPX64") vs supported set (%#x).\n",
		       hss->hss_setmask, hss->hss_clearmask, HSM_FLAGS_MASK);
		GOTO(out_unlock, rc = -EINVAL);
	}

	/* Non-root users are forbidden to set or clear flags which are
	 * NOT defined in HSM_USER_MASK. */
	if (((hss->hss_setmask | hss->hss_clearmask) & ~HSM_USER_MASK) &&
	    !md_capable(mdt_ucred(info), CFS_CAP_SYS_ADMIN)) {
		CDEBUG(D_HSM, "Incompatible masks provided (set "LPX64
		       ", clear "LPX64") vs unprivileged set (%#x).\n",
		       hss->hss_setmask, hss->hss_clearmask, HSM_USER_MASK);
		GOTO(out_unlock, rc = -EPERM);
	}

	/* Read current HSM info */
	ma->ma_valid = 0;
	ma->ma_need = MA_HSM;
	rc = mdt_attr_get_complex(info, obj, ma);
	if (rc)
		GOTO(out_unlock, rc);

	/* Change HSM flags depending on provided masks */
	if (hss->hss_valid & HSS_SETMASK)
		ma->ma_hsm.mh_flags |= hss->hss_setmask;
	if (hss->hss_valid & HSS_CLEARMASK)
		ma->ma_hsm.mh_flags &= ~hss->hss_clearmask;

	/* Change archive_id if provided. */
	if (hss->hss_valid & HSS_ARCHIVE_ID) {
		if (!(ma->ma_hsm.mh_flags & HS_EXISTS)) {
			CDEBUG(D_HSM, "Could not set an archive number for "
			       DFID "if HSM EXISTS flag is not set.\n",
			       PFID(&info->mti_body->mbo_fid1));
			GOTO(out_unlock, rc);
		}

		/* Detect out-of range archive id */
		if (hss->hss_archive_id > LL_HSM_MAX_ARCHIVE) {
			CDEBUG(D_HSM, "archive id %u exceeds maximum %zu.\n",
			       hss->hss_archive_id, LL_HSM_MAX_ARCHIVE);
			GOTO(out_unlock, rc = -EINVAL);
		}

		ma->ma_hsm.mh_arch_id = hss->hss_archive_id;
	}

	/* Check for inconsistant HSM flagset.
	 * DIRTY without EXISTS: no dirty if no archive was created.
	 * DIRTY and RELEASED: a dirty file could not be released.
	 * RELEASED without ARCHIVED: do not release a non-archived file.
	 * LOST without ARCHIVED: cannot lost a non-archived file.
	 */
	flags = ma->ma_hsm.mh_flags;
	if ((flags & HS_DIRTY    && !(flags & HS_EXISTS)) ||
	    (flags & HS_RELEASED && flags & HS_DIRTY) ||
	    (flags & HS_RELEASED && !(flags & HS_ARCHIVED)) ||
	    (flags & HS_LOST     && !(flags & HS_ARCHIVED))) {
		CDEBUG(D_HSM, "Incompatible flag change on "DFID
			      "flags="LPX64"\n",
		       PFID(&info->mti_body->mbo_fid1), flags);
		GOTO(out_unlock, rc = -EINVAL);
	}

	/* Save the modified flags */
	rc = mdt_hsm_attr_set(info, obj, &ma->ma_hsm);
	if (rc)
		GOTO(out_unlock, rc);

	EXIT;

out_unlock:
	mdt_object_unlock(info, obj, lh, 1);
out_ucred:
	mdt_exit_ucred(info);
out:
	mdt_thread_info_fini(info);
	return rc;
}
コード例 #26
0
ファイル: mdt_xattr.c プロジェクト: Xyratex/lustre-stable
/* shrink dir layout after migration */
static int mdt_dir_layout_shrink(struct mdt_thread_info *info)
{
	const struct lu_env *env = info->mti_env;
	struct mdt_device *mdt = info->mti_mdt;
	struct lu_ucred *uc = mdt_ucred(info);
	struct mdt_reint_record *rr = &info->mti_rr;
	struct lmv_user_md *lmu = rr->rr_eadata;
	__u32 lum_stripe_count = lmu->lum_stripe_count;
	struct lu_buf *buf = &info->mti_buf;
	struct lmv_mds_md_v1 *lmv;
	struct md_attr *ma = &info->mti_attr;
	struct ldlm_enqueue_info *einfo = &info->mti_einfo[0];
	struct mdt_object *pobj = NULL;
	struct mdt_object *obj;
	struct mdt_lock_handle *lhp = NULL;
	struct mdt_lock_handle *lhc;
	int rc;

	ENTRY;

	if (!mdt->mdt_enable_dir_migration)
		RETURN(-EPERM);

	if (!md_capable(uc, CFS_CAP_SYS_ADMIN) &&
	    uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
	    mdt->mdt_enable_remote_dir_gid != -1)
		RETURN(-EPERM);

	/* mti_big_lmm is used to save LMV, but it may be uninitialized. */
	if (unlikely(!info->mti_big_lmm)) {
		info->mti_big_lmmsize = lmv_mds_md_size(64, LMV_MAGIC);
		OBD_ALLOC(info->mti_big_lmm, info->mti_big_lmmsize);
		if (!info->mti_big_lmm)
			RETURN(-ENOMEM);
	}

	obj = mdt_object_find(env, mdt, rr->rr_fid1);
	if (IS_ERR(obj))
		RETURN(PTR_ERR(obj));

	/* get parent from PFID */
	rc = mdt_attr_get_pfid(info, obj, &ma->ma_pfid);
	if (rc)
		GOTO(put_obj, rc);

	pobj = mdt_object_find(env, mdt, &ma->ma_pfid);
	if (IS_ERR(pobj))
		GOTO(put_obj, rc = PTR_ERR(pobj));

	/* revoke object remote LOOKUP lock */
	if (mdt_object_remote(pobj)) {
		rc = mdt_revoke_remote_lookup_lock(info, pobj, obj);
		if (rc)
			GOTO(put_pobj, rc);
	}

	/*
	 * lock parent if dir will be shrunk to 1 stripe, because dir will be
	 * converted to normal directory, as will change dir fid and update
	 * namespace of parent.
	 */
	lhp = &info->mti_lh[MDT_LH_PARENT];
	mdt_lock_reg_init(lhp, LCK_PW);

	if (le32_to_cpu(lmu->lum_stripe_count) < 2) {
		rc = mdt_reint_object_lock(info, pobj, lhp,
					   MDS_INODELOCK_UPDATE, true);
		if (rc)
			GOTO(put_pobj, rc);
	}

	/* lock object */
	lhc = &info->mti_lh[MDT_LH_CHILD];
	mdt_lock_reg_init(lhc, LCK_EX);
	rc = mdt_reint_striped_lock(info, obj, lhc, MDS_INODELOCK_FULL, einfo,
				    true);
	if (rc)
		GOTO(unlock_pobj, rc);

	ma->ma_lmv = info->mti_big_lmm;
	ma->ma_lmv_size = info->mti_big_lmmsize;
	ma->ma_valid = 0;
	rc = mdt_stripe_get(info, obj, ma, XATTR_NAME_LMV);
	if (rc)
		GOTO(unlock_obj, rc);

	/* user may run 'lfs migrate' multiple times, so it's shrunk already */
	if (!(ma->ma_valid & MA_LMV))
		GOTO(unlock_obj, rc = -EALREADY);

	lmv = &ma->ma_lmv->lmv_md_v1;

	/* ditto */
	if (!(le32_to_cpu(lmv->lmv_hash_type) & LMV_HASH_FLAG_MIGRATION))
		GOTO(unlock_obj, rc = -EALREADY);

	lum_stripe_count = lmu->lum_stripe_count;
	if (!lum_stripe_count)
		lum_stripe_count = cpu_to_le32(1);

	if (lmv->lmv_migrate_offset != lum_stripe_count) {
		CERROR("%s: "DFID" migrate mdt count mismatch %u != %u\n",
			mdt_obd_name(info->mti_mdt), PFID(rr->rr_fid1),
			lmv->lmv_migrate_offset, lmu->lum_stripe_count);
		GOTO(unlock_obj, rc = -EINVAL);
	}

	if (lmv->lmv_master_mdt_index != lmu->lum_stripe_offset) {
		CERROR("%s: "DFID" migrate mdt index mismatch %u != %u\n",
			mdt_obd_name(info->mti_mdt), PFID(rr->rr_fid1),
			lmv->lmv_master_mdt_index, lmu->lum_stripe_offset);
		GOTO(unlock_obj, rc = -EINVAL);
	}

	if (lum_stripe_count > 1 &&
	    (lmv->lmv_hash_type & cpu_to_le32(LMV_HASH_TYPE_MASK)) !=
	    lmu->lum_hash_type) {
		CERROR("%s: "DFID" migrate mdt hash mismatch %u != %u\n",
			mdt_obd_name(info->mti_mdt), PFID(rr->rr_fid1),
			lmv->lmv_hash_type, lmu->lum_hash_type);
		GOTO(unlock_obj, rc = -EINVAL);
	}

	buf->lb_buf = rr->rr_eadata;
	buf->lb_len = rr->rr_eadatalen;
	rc = mo_xattr_set(env, mdt_object_child(obj), buf, XATTR_NAME_LMV, 0);
	GOTO(unlock_obj, rc);

unlock_obj:
	mdt_reint_striped_unlock(info, obj, lhc, einfo, rc);
unlock_pobj:
	mdt_object_unlock(info, pobj, lhp, rc);
put_pobj:
	mdt_object_put(env, pobj);
put_obj:
	mdt_object_put(env, obj);

	return rc;
}
コード例 #27
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
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 mdt_reint_record *rr   = &info->mti_rr;
        struct ptlrpc_request   *req  = mdt_info_req(info);
        struct md_op_spec       *sp   = &info->mti_spec;
        ENTRY;

        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);

        uc->mu_fsuid = rec->cr_fsuid;
        uc->mu_fsgid = rec->cr_fsgid;
        uc->mu_cap   = rec->cr_cap;
        uc->mu_suppgids[0] = rec->cr_suppgid1;
        uc->mu_suppgids[1] = rec->cr_suppgid2;

        rr->rr_fid1   = &rec->cr_fid1;
        rr->rr_fid2   = &rec->cr_fid2;
        rr->rr_handle = &rec->cr_old_handle;
        attr->la_mode = rec->cr_mode;
        attr->la_rdev  = rec->cr_rdev;
        attr->la_uid   = rec->cr_fsuid;
        attr->la_gid   = rec->cr_fsgid;
        attr->la_ctime = rec->cr_time;
        attr->la_mtime = rec->cr_time;
        attr->la_atime = rec->cr_time;
        attr->la_valid = LA_MODE  | LA_RDEV  | LA_UID   | LA_GID |
                         LA_CTIME | LA_MTIME | LA_ATIME;
        memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
        info->mti_spec.sp_cr_flags = get_mrc_cr_flags(rec);
        /* Do not trigger ASSERTION if client miss to set such flags. */
        if (unlikely(info->mti_spec.sp_cr_flags == 0))
                RETURN(-EPROTO);
        info->mti_replayepoch = rec->cr_ioepoch;

        info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
        info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);

        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));
        if (req_is_replay(req) &&
            req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)) {
#if 0
                mdt_set_capainfo(info, 1, rr->rr_fid2,
                                 req_capsule_client_get(pill, &RMF_CAPA2));
#else
                /*
                 * FIXME: capa in replay open request might have expired,
                 * bypass capa check. Security hole?
                 */
                mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
                mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
#endif
        }

        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;

        sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
                                                     RCL_CLIENT);
        if (sp->u.sp_ea.eadatalen) {
                sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
                sp->no_create = !!req_is_replay(req);
        }

        RETURN(0);
}
コード例 #28
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
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;
}
コード例 #29
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
static int mdt_create_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 mdt_reint_record *rr = &info->mti_rr;
        struct req_capsule      *pill = info->mti_pill;
        struct md_op_spec       *sp = &info->mti_spec;
        int rc;
        ENTRY;

        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);

        uc->mu_fsuid = rec->cr_fsuid;
        uc->mu_fsgid = rec->cr_fsgid;
        uc->mu_cap   = rec->cr_cap;
        uc->mu_suppgids[0] = rec->cr_suppgid1;
        uc->mu_suppgids[1] = -1;

        rr->rr_fid1 = &rec->cr_fid1;
        rr->rr_fid2 = &rec->cr_fid2;
        attr->la_mode = rec->cr_mode;
        attr->la_rdev  = rec->cr_rdev;
        attr->la_uid   = rec->cr_fsuid;
        attr->la_gid   = rec->cr_fsgid;
        attr->la_ctime = rec->cr_time;
        attr->la_mtime = rec->cr_time;
        attr->la_atime = rec->cr_time;
        attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
                         LA_CTIME | LA_MTIME | LA_ATIME;
        memset(&sp->u, 0, sizeof(sp->u));
        sp->sp_cr_flags = get_mrc_cr_flags(rec);
        sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
        info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);

        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));
        mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);

        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))
                        sp->u.sp_pfid = rr->rr_fid1;
                req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
                LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
                                                  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);
                sp->u.sp_ea.fid = rr->rr_fid1;
                RETURN(0);
        }
#endif
        if (S_ISDIR(attr->la_mode)) {
                /* pass parent fid for cross-ref cases */
                sp->u.sp_pfid = rr->rr_fid1;
                if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
                        /* create salve object req, need
                         * unpack split ea here
                         */
                       req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
                       LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
                                                         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);
                       sp->u.sp_ea.fid = rr->rr_fid1;
                       RETURN(0);
                }
                req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
        } else if (S_ISLNK(attr->la_mode)) {
                const char *tgt = NULL;

                req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
                if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
                        tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
                        sp->u.sp_symname = tgt;
                }
                if (tgt == NULL)
                        RETURN(-EFAULT);
        } else {
                req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
        }
        rc = mdt_dlmreq_unpack(info);
        RETURN(rc);
}
コード例 #30
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
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;
}