]) # LC_HAVE_SECURITY_DENTRY_INIT_SECURITY
#
+# 3.10 exports security_inode_listsecurity
+#
+AC_DEFUN([LC_HAVE_SECURITY_INODE_LISTSECURITY], [
+LB_CHECK_COMPILE([if security_inode_listsecurity() is available/exported],
+security_inode_listsecurity, [
+ #include <linux/security.h>
+],[
+ security_inode_listsecurity(NULL, NULL, 0);
+],[
+ AC_DEFINE(HAVE_SECURITY_INODE_LISTSECURITY, 1,
+ [security_inode_listsecurity() is available/exported])
+])
+]) # LC_HAVE_SECURITY_INODE_LISTSECURITY
+
+#
# LC_INVALIDATE_RANGE
#
# 3.11 invalidatepage requires the length of the range to invalidate
LC_HAVE_PROC_REMOVE
LC_HAVE_PROJECT_QUOTA
LC_HAVE_SECURITY_DENTRY_INIT_SECURITY
+ LC_HAVE_SECURITY_INODE_LISTSECURITY
# 3.11
LC_INVALIDATE_RANGE
__u64 op_data_version;
struct lustre_handle op_lease_handle;
- /* File security context, for creates. */
+ /* File security context, for creates/metadata ops */
const char *op_file_secctx_name;
+ __u32 op_file_secctx_name_size;
void *op_file_secctx;
__u32 op_file_secctx_size;
#define OBD_MD_DEFAULT_MEA (0x0040000000000000ULL) /* default MEA */
#define OBD_MD_FLOSTLAYOUT (0x0080000000000000ULL) /* contain ost_layout */
#define OBD_MD_FLPROJID (0x0100000000000000ULL) /* project ID */
+#define OBD_MD_SECCTX (0x0200000000000000ULL) /* embed security xattr */
#define OBD_MD_FLALLQUOTA (OBD_MD_FLUSRQUOTA | \
OBD_MD_FLGRPQUOTA | \
int ll_inode_init_security(struct dentry *dentry, struct inode *inode,
struct inode *dir);
+int ll_listsecurity(struct inode *inode, char *secctx_name,
+ size_t secctx_name_size);
+
/*
* Locking to guarantee consistency of non-atomic updates to long long i_size,
* consistency between file size and KMS.
static int ll_lookup_it_finish(struct ptlrpc_request *request,
struct lookup_intent *it,
- struct inode *parent, struct dentry **de)
+ struct inode *parent, struct dentry **de,
+ void *secctx, __u32 secctxlen)
{
struct inode *inode = NULL;
__u64 bits = 0;
CDEBUG(D_DENTRY, "it %p it_disposition %x\n", it,
it->it_disposition);
if (!it_disposition(it, DISP_LOOKUP_NEG)) {
+ struct req_capsule *pill = &request->rq_pill;
+ struct mdt_body *body = req_capsule_server_get(pill,
+ &RMF_MDT_BODY);
+
rc = ll_prep_inode(&inode, request, (*de)->d_sb, it);
if (rc)
RETURN(rc);
* ll_glimpse_size or some equivalent themselves anyway.
* Also see bug 7198.
*/
+
+ /* If security context was returned by MDT, put it in
+ * inode now to save an extra getxattr from security hooks,
+ * and avoid deadlock.
+ */
+ if (body->mbo_valid & OBD_MD_SECCTX) {
+ secctx = req_capsule_server_get(pill, &RMF_FILE_SECCTX);
+ secctxlen = req_capsule_get_size(pill,
+ &RMF_FILE_SECCTX,
+ RCL_SERVER);
+
+ if (secctxlen)
+ CDEBUG(D_SEC, "server returned security context"
+ " for "DFID"\n",
+ PFID(ll_inode2fid(inode)));
+ }
+
+ if (secctx != NULL && secctxlen != 0) {
+ inode_lock(inode);
+ rc = security_inode_notifysecctx(inode, secctx,
+ secctxlen);
+ inode_unlock(inode);
+ if (rc)
+ CWARN("cannot set security context for "
+ DFID": rc = %d\n",
+ PFID(ll_inode2fid(inode)), rc);
+ }
}
/* Only hash *de if it is unhashed (new dentry).
struct dentry *save = dentry, *retval;
struct ptlrpc_request *req = NULL;
struct md_op_data *op_data = NULL;
- __u32 opc;
- int rc;
- ENTRY;
+ __u32 opc;
+ int rc;
+ char secctx_name[XATTR_NAME_MAX + 1];
+
+ ENTRY;
if (dentry->d_name.len > ll_i2sbi(parent)->ll_namelen)
RETURN(ERR_PTR(-ENAMETOOLONG));
*secctx = op_data->op_file_secctx;
if (secctxlen != NULL)
*secctxlen = op_data->op_file_secctx_size;
+ } else {
+ if (secctx != NULL)
+ *secctx = NULL;
+ if (secctxlen != NULL)
+ *secctxlen = 0;
+ }
+
+ /* ask for security context upon intent */
+ if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_OPEN)) {
+ /* get name of security xattr to request to server */
+ rc = ll_listsecurity(parent, secctx_name,
+ sizeof(secctx_name));
+ if (rc < 0) {
+ CDEBUG(D_SEC, "cannot get security xattr name for "
+ DFID": rc = %d\n",
+ PFID(ll_inode2fid(parent)), rc);
+ } else if (rc > 0) {
+ op_data->op_file_secctx_name = secctx_name;
+ op_data->op_file_secctx_name_size = rc;
+ CDEBUG(D_SEC, "'%.*s' is security xattr for "DFID"\n",
+ rc, secctx_name, PFID(ll_inode2fid(parent)));
+ }
}
rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req,
/* dir layout may change */
ll_unlock_md_op_lsm(op_data);
- rc = ll_lookup_it_finish(req, it, parent, &dentry);
+ rc = ll_lookup_it_finish(req, it, parent, &dentry,
+ secctx != NULL ? *secctx : NULL,
+ secctxlen != NULL ? *secctxlen : 0);
if (rc != 0) {
ll_intent_release(it);
GOTO(out, retval = ERR_PTR(rc));
return err;
}
#endif /* HAVE_SECURITY_IINITSEC_CALLBACK */
+
+/**
+ * Get security context xattr name used by policy.
+ *
+ * \retval >= 0 length of xattr name
+ * \retval < 0 failure to get security context xattr name
+ */
+int
+ll_listsecurity(struct inode *inode, char *secctx_name, size_t secctx_name_size)
+{
+ int rc;
+
+ if (!selinux_is_enabled())
+ return 0;
+
+#ifdef HAVE_SECURITY_INODE_LISTSECURITY
+ rc = security_inode_listsecurity(inode, secctx_name, secctx_name_size);
+ if (rc >= secctx_name_size)
+ rc = -ERANGE;
+ else if (rc >= 0)
+ secctx_name[rc] = '\0';
+ return rc;
+#else /* !HAVE_SECURITY_INODE_LISTSECURITY */
+ rc = sizeof(XATTR_NAME_SELINUX);
+ if (secctx_name && rc < secctx_name_size) {
+ memcpy(secctx_name, XATTR_NAME_SELINUX, rc);
+ secctx_name[rc] = '\0';
+ } else {
+ rc = -ERANGE;
+ }
+ return rc;
+#endif /* HAVE_SECURITY_INODE_LISTSECURITY */
+}
const struct lu_fid *parent_fid,
struct ptlrpc_request **reqp,
ldlm_blocking_callback cb_blocking,
- __u64 extra_lock_flags)
+ __u64 extra_lock_flags,
+ const char *secctx_name, __u32 secctx_name_size)
{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%u\n",
PFID(&body->mbo_fid1), tgt->ltd_idx);
+ /* ask for security context upon intent */
+ if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_OPEN) &&
+ secctx_name_size != 0 && secctx_name != NULL) {
+ op_data->op_file_secctx_name = secctx_name;
+ op_data->op_file_secctx_name_size = secctx_name_size;
+ CDEBUG(D_SEC, "'%.*s' is security xattr to fetch for "
+ DFID"\n",
+ secctx_name_size, secctx_name, PFID(&body->mbo_fid1));
+ }
+
rc = md_intent_lock(tgt->ltd_exp, op_data, it, &req, cb_blocking,
extra_lock_flags);
if (rc)
/* Not cross-ref case, just get out of here. */
if (unlikely((body->mbo_valid & OBD_MD_MDS))) {
rc = lmv_intent_remote(exp, it, &op_data->op_fid1, reqp,
- cb_blocking, extra_lock_flags);
+ cb_blocking, extra_lock_flags,
+ op_data->op_file_secctx_name,
+ op_data->op_file_secctx_name_size);
if (rc != 0)
RETURN(rc);
/* Not cross-ref case, just get out of here. */
if (unlikely((body->mbo_valid & OBD_MD_MDS))) {
rc = lmv_intent_remote(exp, it, NULL, reqp, cb_blocking,
- extra_lock_flags);
+ extra_lock_flags,
+ op_data->op_file_secctx_name,
+ op_data->op_file_secctx_name_size);
if (rc != 0)
RETURN(rc);
body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX_NAME,
RCL_CLIENT, op_data->op_file_secctx_name != NULL ?
- strlen(op_data->op_file_secctx_name) + 1 : 0);
+ op_data->op_file_secctx_name_size : 0);
req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX, RCL_CLIENT,
op_data->op_file_secctx_size);
obddev->u.cli.cl_max_mds_easize);
req_capsule_set_size(&req->rq_pill, &RMF_ACL, RCL_SERVER, acl_bufsize);
+ if (!(it->it_op & IT_CREAT) && it->it_op & IT_OPEN &&
+ req_capsule_has_field(&req->rq_pill, &RMF_FILE_SECCTX_NAME,
+ RCL_CLIENT) &&
+ op_data->op_file_secctx_name_size > 0 &&
+ op_data->op_file_secctx_name != NULL) {
+ char *secctx_name;
+
+ secctx_name = req_capsule_client_get(&req->rq_pill,
+ &RMF_FILE_SECCTX_NAME);
+ memcpy(secctx_name, op_data->op_file_secctx_name,
+ op_data->op_file_secctx_name_size);
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX,
+ RCL_SERVER,
+ obddev->u.cli.cl_max_mds_easize);
+
+ CDEBUG(D_SEC, "packed '%.*s' as security xattr name\n",
+ op_data->op_file_secctx_name_size,
+ op_data->op_file_secctx_name);
+
+ } else {
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX,
+ RCL_SERVER, 0);
+ }
+
/**
* Inline buffer for possible data from Data-on-MDT files.
*/
/* pack the intent */
lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT);
lit->opc = IT_GETXATTR;
+ CDEBUG(D_INFO, "%s: get xattrs for "DFID"\n",
+ exp->exp_obd->obd_name, PFID(&op_data->op_fid1));
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
/* If the supplied buffer is too small then the server will
struct ldlm_intent *lit;
int rc;
__u32 easize;
+ bool have_secctx = false;
ENTRY;
- req = ptlrpc_request_alloc(class_exp2cliimp(exp),
- &RQF_LDLM_INTENT_GETATTR);
- if (req == NULL)
- RETURN(ERR_PTR(-ENOMEM));
+ req = ptlrpc_request_alloc(class_exp2cliimp(exp),
+ &RQF_LDLM_INTENT_GETATTR);
+ if (req == NULL)
+ RETURN(ERR_PTR(-ENOMEM));
- req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
- op_data->op_namelen + 1);
+ /* send name of security xattr to get upon intent */
+ if (it->it_op & (IT_LOOKUP | IT_GETATTR) &&
+ req_capsule_has_field(&req->rq_pill, &RMF_FILE_SECCTX_NAME,
+ RCL_CLIENT) &&
+ op_data->op_file_secctx_name_size > 0 &&
+ op_data->op_file_secctx_name != NULL) {
+ have_secctx = true;
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX_NAME,
+ RCL_CLIENT,
+ op_data->op_file_secctx_name_size);
+ }
- rc = ldlm_prep_enqueue_req(exp, req, NULL, 0);
- if (rc) {
- ptlrpc_request_free(req);
- RETURN(ERR_PTR(rc));
- }
+ req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
+ op_data->op_namelen + 1);
+
+ rc = ldlm_prep_enqueue_req(exp, req, NULL, 0);
+ if (rc) {
+ ptlrpc_request_free(req);
+ RETURN(ERR_PTR(rc));
+ }
/* pack the intent */
- lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT);
- lit->opc = (__u64)it->it_op;
+ lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT);
+ lit->opc = (__u64)it->it_op;
if (obddev->u.cli.cl_default_mds_easize > 0)
easize = obddev->u.cli.cl_default_mds_easize;
req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, easize);
req_capsule_set_size(&req->rq_pill, &RMF_ACL, RCL_SERVER, acl_bufsize);
+
+ if (have_secctx) {
+ char *secctx_name;
+
+ secctx_name = req_capsule_client_get(&req->rq_pill,
+ &RMF_FILE_SECCTX_NAME);
+ memcpy(secctx_name, op_data->op_file_secctx_name,
+ op_data->op_file_secctx_name_size);
+
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX,
+ RCL_SERVER, easize);
+
+ CDEBUG(D_SEC, "packed '%.*s' as security xattr name\n",
+ op_data->op_file_secctx_name_size,
+ op_data->op_file_secctx_name);
+ } else {
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX,
+ RCL_SERVER, 0);
+ }
+
ptlrpc_request_set_replen(req);
RETURN(req);
}
LASSERT(obd_md_valid == OBD_MD_FLXATTR ||
obd_md_valid == OBD_MD_FLXATTRLS);
+ CDEBUG(D_INFO, "%s: get xattr '%s' for "DFID"\n",
+ exp->exp_obd->obd_name, name, PFID(fid));
rc = mdc_xattr_common(exp, &RQF_MDS_GETXATTR, fid, MDS_GETXATTR,
obd_md_valid, name, NULL, 0, buf_size, 0, -1,
req);
struct lu_name *lname = NULL;
struct mdt_lock_handle *lhp = NULL;
struct ldlm_lock *lock;
+ struct req_capsule *pill = info->mti_pill;
__u64 try_bits = 0;
bool is_resent;
int ma_need = 0;
+ bool deal_with_dom = false;
int rc;
ENTRY;
if (unlikely(rc != 0))
mdt_object_unlock(info, child, lhc, 1);
- RETURN(rc);
- }
+ mdt_pack_secctx_in_reply(info, child);
+
+ RETURN(rc);
+ }
lname = &info->mti_name;
- mdt_name_unpack(info->mti_pill, &RMF_NAME, lname, MNF_FIX_ANON);
+ mdt_name_unpack(pill, &RMF_NAME, lname, MNF_FIX_ANON);
if (lu_name_is_valid(lname)) {
CDEBUG(D_INODE, "getattr with lock for "DFID"/"DNAME", "
"ldlm_rep = %p\n", PFID(mdt_object_fid(parent)),
PNAME(lname), ldlm_rep);
} else {
- reqbody = req_capsule_client_get(info->mti_pill, &RMF_MDT_BODY);
+ reqbody = req_capsule_client_get(pill, &RMF_MDT_BODY);
if (unlikely(reqbody == NULL))
RETURN(err_serious(-EPROTO));
child_bits &= ~MDS_INODELOCK_UPDATE;
rc = mdt_object_lock(info, child, lhc, child_bits);
}
- if (unlikely(rc != 0))
- GOTO(out_child, rc);
- }
+ if (unlikely(rc != 0))
+ GOTO(out_child, rc);
+ }
- lock = ldlm_handle2lock(&lhc->mlh_reg_lh);
+ lock = ldlm_handle2lock(&lhc->mlh_reg_lh);
- /* finally, we can get attr for child. */
- rc = mdt_getattr_internal(info, child, ma_need);
- if (unlikely(rc != 0)) {
- mdt_object_unlock(info, child, lhc, 1);
+ /* finally, we can get attr for child. */
+ rc = mdt_getattr_internal(info, child, ma_need);
+ if (unlikely(rc != 0)) {
+ mdt_object_unlock(info, child, lhc, 1);
+ GOTO(out_lock, rc);
} else if (lock) {
/* Debugging code. */
LDLM_DEBUG(lock, "Returning lock to client");
if (S_ISREG(lu_object_attr(&child->mot_obj)) &&
mdt_object_exists(child) && !mdt_object_remote(child) &&
- child != parent) {
- LDLM_LOCK_PUT(lock);
- mdt_object_put(info->mti_env, child);
- /* NB: call the mdt_pack_size2body always after
- * mdt_object_put(), that is why this special
- * exit path is used. */
- rc = mdt_pack_size2body(info, child_fid,
- &lhc->mlh_reg_lh);
- if (rc != 0 && child_bits & MDS_INODELOCK_DOM) {
- /* DOM lock was taken in advance but this is
- * not DoM file. Drop the lock. */
- lock_res_and_lock(lock);
- ldlm_inodebits_drop(lock, MDS_INODELOCK_DOM);
- unlock_res_and_lock(lock);
- }
-
- GOTO(out_parent, rc = 0);
- }
+ child != parent)
+ deal_with_dom = true;
}
+
+ mdt_pack_secctx_in_reply(info, child);
+
+out_lock:
if (lock)
LDLM_LOCK_PUT(lock);
EXIT;
out_child:
mdt_object_put(info->mti_env, child);
+ if (deal_with_dom) {
+ rc = mdt_pack_size2body(info, child_fid,
+ &lhc->mlh_reg_lh);
+ if (rc != 0 && child_bits & MDS_INODELOCK_DOM) {
+ /* DOM lock was taken in advance but this is
+ * not DoM file. Drop the lock.
+ */
+ lock_res_and_lock(lock);
+ ldlm_inodebits_drop(lock, MDS_INODELOCK_DOM);
+ unlock_res_and_lock(lock);
+ }
+ rc = 0;
+ }
out_parent:
if (lhp)
mdt_object_unlock(info, parent, lhp, 1);
!(info->mti_spec.sp_cr_flags & (MDS_FMODE_WRITE | MDS_OPEN_CREAT));
}
+static void mdt_preset_secctx_size(struct mdt_thread_info *info)
+{
+ struct req_capsule *pill = info->mti_pill;
+
+ if (req_capsule_has_field(pill, &RMF_FILE_SECCTX,
+ RCL_SERVER) &&
+ req_capsule_has_field(pill, &RMF_FILE_SECCTX_NAME,
+ RCL_CLIENT)) {
+ if (req_capsule_get_size(pill, &RMF_FILE_SECCTX_NAME,
+ RCL_CLIENT) != 0) {
+ /* pre-set size in server part with max size */
+ req_capsule_set_size(pill, &RMF_FILE_SECCTX,
+ RCL_SERVER,
+ info->mti_mdt->mdt_max_ea_size);
+ } else {
+ req_capsule_set_size(pill, &RMF_FILE_SECCTX,
+ RCL_SERVER, 0);
+ }
+ }
+
+}
+
static int mdt_reint_internal(struct mdt_thread_info *info,
struct mdt_lock_handle *lhc,
__u32 op)
DEF_REP_MD_SIZE);
/* llog cookies are always 0, the field is kept for compatibility */
- if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
+ if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
req_capsule_set_size(pill, &RMF_LOGCOOKIES, RCL_SERVER, 0);
/* Set ACL reply buffer size as LUSTRE_POSIX_ACL_MAX_SIZE_OLD
req_capsule_set_size(pill, &RMF_ACL, RCL_SERVER,
LUSTRE_POSIX_ACL_MAX_SIZE_OLD);
- rc = req_capsule_server_pack(pill);
- if (rc != 0) {
- CERROR("Can't pack response, rc %d\n", rc);
- RETURN(err_serious(rc));
- }
+ mdt_preset_secctx_size(info);
+
+ rc = req_capsule_server_pack(pill);
+ if (rc != 0) {
+ CERROR("Can't pack response, rc %d\n", rc);
+ RETURN(err_serious(rc));
+ }
- if (req_capsule_has_field(pill, &RMF_MDT_BODY, RCL_SERVER)) {
- repbody = req_capsule_server_get(pill, &RMF_MDT_BODY);
- LASSERT(repbody);
+ if (req_capsule_has_field(pill, &RMF_MDT_BODY, RCL_SERVER)) {
+ repbody = req_capsule_server_get(pill, &RMF_MDT_BODY);
+ LASSERT(repbody);
repbody->mbo_eadatasize = 0;
repbody->mbo_aclsize = 0;
- }
+ }
- OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_REINT_DELAY, 10);
+ OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_REINT_DELAY, 10);
- /* for replay no cookkie / lmm need, because client have this already */
- if (info->mti_spec.no_create)
- if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER))
- req_capsule_set_size(pill, &RMF_MDT_MD, RCL_SERVER, 0);
+ /* for replay no cookkie / lmm need, because client have this already */
+ if (info->mti_spec.no_create)
+ if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER))
+ req_capsule_set_size(pill, &RMF_MDT_MD, RCL_SERVER, 0);
- rc = mdt_init_ucred_reint(info);
- if (rc)
- GOTO(out_shrink, rc);
+ rc = mdt_init_ucred_reint(info);
+ if (rc)
+ GOTO(out_shrink, rc);
- rc = mdt_fix_attr_ucred(info, op);
- if (rc != 0)
- GOTO(out_ucred, rc = err_serious(rc));
+ rc = mdt_fix_attr_ucred(info, op);
+ if (rc != 0)
+ GOTO(out_ucred, rc = err_serious(rc));
rc = mdt_check_resent(info, mdt_reconstruct, lhc);
if (rc < 0) {
} else if (rc == 1) {
DEBUG_REQ(D_INODE, mdt_info_req(info), "resent opt.");
rc = lustre_msg_get_status(mdt_info_req(info)->rq_repmsg);
- GOTO(out_ucred, rc);
- }
- rc = mdt_reint_rec(info, lhc);
- EXIT;
+ GOTO(out_ucred, rc);
+ }
+ rc = mdt_reint_rec(info, lhc);
+ EXIT;
out_ucred:
- mdt_exit_ucred(info);
+ mdt_exit_ucred(info);
out_shrink:
mdt_client_compatibility(info);
req_capsule_set_size(pill, &RMF_ACL, RCL_SERVER,
LUSTRE_POSIX_ACL_MAX_SIZE_OLD);
+ mdt_preset_secctx_size(info);
+
rc = req_capsule_server_pack(pill);
+ if (rc)
+ CWARN("%s: cannot pack response: rc = %d\n",
+ mdt_obd_name(info->mti_mdt), rc);
}
RETURN(rc);
}
struct linkea_data *ldata);
int mdt_close_internal(struct mdt_thread_info *info, struct ptlrpc_request *req,
struct mdt_body *repbody);
+void mdt_pack_secctx_in_reply(struct mdt_thread_info *info,
+ struct mdt_object *child);
static inline struct mdt_device *mdt_dev(struct lu_device *d)
{
}
RETURN(rc);
}
+
+void mdt_pack_secctx_in_reply(struct mdt_thread_info *info,
+ struct mdt_object *child)
+{
+ char *secctx_name;
+ struct lu_buf *buffer;
+ struct mdt_body *repbody;
+ struct req_capsule *pill = info->mti_pill;
+ int rc;
+
+ if (req_capsule_has_field(pill, &RMF_FILE_SECCTX, RCL_SERVER) &&
+ req_capsule_get_size(pill, &RMF_FILE_SECCTX, RCL_SERVER) != 0) {
+ secctx_name =
+ req_capsule_client_get(pill, &RMF_FILE_SECCTX_NAME);
+ buffer = &info->mti_buf;
+
+ /* fill reply buffer with security context now */
+ buffer->lb_len = req_capsule_get_size(pill, &RMF_FILE_SECCTX,
+ RCL_SERVER);
+ buffer->lb_buf = req_capsule_server_get(info->mti_pill,
+ &RMF_FILE_SECCTX);
+ rc = mo_xattr_get(info->mti_env, mdt_object_child(child),
+ buffer, secctx_name);
+ if (rc >= 0) {
+ CDEBUG(D_SEC,
+ "found security context of size %d for "DFID"\n",
+ rc, PFID(mdt_object_fid(child)));
+
+ repbody = req_capsule_server_get(pill, &RMF_MDT_BODY);
+ repbody->mbo_valid |= OBD_MD_SECCTX;
+ if (rc < buffer->lb_len)
+ req_capsule_shrink(pill, &RMF_FILE_SECCTX, rc,
+ RCL_SERVER);
+ } else {
+ CDEBUG(D_SEC,
+ "security context not found for "DFID": rc = %d\n",
+ PFID(mdt_object_fid(child)), rc);
+ req_capsule_shrink(pill, &RMF_FILE_SECCTX, 0,
+ RCL_SERVER);
+ }
+ }
+}
if (rc != 0)
GOTO(out, rc);
+ mdt_pack_secctx_in_reply(info, o);
+
rc = mdt_finish_open(info, NULL, o, open_flags, 0, rep);
} else {
/*
PNAME(&rr->rr_name), PFID(child_fid));
GOTO(out_child, result = -EIO);
}
- }
+ }
+
+ mdt_pack_secctx_in_reply(info, child);
rc = mdt_check_resent_lock(info, child, lhc);
if (rc < 0) {
&RMF_CAPA1,
&RMF_CAPA2,
&RMF_NIOBUF_INLINE,
+ &RMF_FILE_SECCTX
};
static const struct req_msg_field *ldlm_intent_getattr_client[] = {
- &RMF_PTLRPC_BODY,
- &RMF_DLM_REQ,
- &RMF_LDLM_INTENT,
- &RMF_MDT_BODY, /* coincides with mds_getattr_name_client[] */
- &RMF_CAPA1,
- &RMF_NAME
+ &RMF_PTLRPC_BODY,
+ &RMF_DLM_REQ,
+ &RMF_LDLM_INTENT,
+ &RMF_MDT_BODY, /* coincides with mds_getattr_name_client[] */
+ &RMF_CAPA1,
+ &RMF_NAME,
+ &RMF_FILE_SECCTX_NAME
};
static const struct req_msg_field *ldlm_intent_getattr_server[] = {
- &RMF_PTLRPC_BODY,
- &RMF_DLM_REP,
- &RMF_MDT_BODY,
- &RMF_MDT_MD,
- &RMF_ACL,
- &RMF_CAPA1
+ &RMF_PTLRPC_BODY,
+ &RMF_DLM_REP,
+ &RMF_MDT_BODY,
+ &RMF_MDT_MD,
+ &RMF_ACL,
+ &RMF_CAPA1,
+ &RMF_FILE_SECCTX
};
static const struct req_msg_field *ldlm_intent_create_client[] = {
EXPORT_SYMBOL(RMF_FILE_SECCTX_NAME);
struct req_msg_field RMF_FILE_SECCTX =
- DEFINE_MSGF("file_secctx", 0, -1, NULL, NULL);
+ DEFINE_MSGF("file_secctx", RMF_F_NO_SIZE_CHECK, -1, NULL, NULL);
EXPORT_SYMBOL(RMF_FILE_SECCTX);
struct req_msg_field RMF_LLOGD_BODY =
}
run_test 20c "[atomicity] concurrent access from another client (dir via lfs)"
+cleanup_20d() {
+ umount_client $MOUNT || error "umount $MOUNT failed"
+ mountcli
+}
+
+trace_cmd() {
+ local cmd="$@"
+ local xattr_prefix=$(grep -E \
+ "#define[[:space:]]+XATTR_SECURITY_PREFIX[[:space:]]+" \
+ /usr/include/linux/xattr.h 2>/dev/null |
+ awk '{print $3}' | sed s+\"++g)
+ local xattr_suffix=$(grep -E \
+ "#define[[:space:]]+XATTR_SELINUX_SUFFIX[[:space:]]+" \
+ /usr/include/linux/xattr.h 2>/dev/null |
+ awk '{print $3}' | sed s+\"++g)
+ local xattr_name=${xattr_prefix}${xattr_suffix}
+
+ [ -z "$xattr_name" ] && xattr_name="security.selinux"
+
+ # umount client
+ if [ "$MOUNT_2" ] && $(grep -q $MOUNT2' ' /proc/mounts); then
+ umount_client $MOUNT2 || error "umount $MOUNT2 failed"
+ fi
+ if $(grep -q $MOUNT' ' /proc/mounts); then
+ umount_client $MOUNT || error "umount $MOUNT failed"
+ fi
+ lustre_rmmod
+ # remount client
+ mount_client $MOUNT ${MOUNT_OPTS} || error "mount client failed"
+
+ $LCTL set_param debug=+info
+ $LCTL clear
+
+ echo $cmd
+ eval $cmd
+
+ $LCTL dk | grep "get xattr '${xattr_name}'"
+ [ $? -eq 0 ] && error "get xattr event was triggered" || true
+}
+
+test_20d() {
+ if [ $MDS1_VERSION -lt $(version_code 2.12.50) ] ||
+ [ $CLIENT_VERSION -lt $(version_code 2.12.50) ]; then
+ skip "Need version >= 2.12.50"
+ fi
+ [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
+
+ stack_trap cleanup_20d EXIT
+
+ local dirname=$DIR/$tdir/subdir
+
+ mkdir -p $DIR/$tdir
+ mkdir $dirname
+
+ trace_cmd stat $dirname
+ trace_cmd touch $dirname/f1
+ trace_cmd stat $dirname/f1
+ trace_cmd cat $dirname/f1
+ dd if=/dev/zero of=$dirname/f1 bs=1M count=10
+ trace_cmd /usr/bin/truncate -s 10240 $dirname/f1
+ trace_cmd lfs setstripe -E -1 -S 4M $dirname/f2
+ trace_cmd lfs migrate -E -1 -S 256K $dirname/f2
+ trace_cmd lfs setdirstripe -i 1 $dirname/d2
+ trace_cmd lfs migrate -m 0 $dirname/d2
+
+ lfs setdirstripe -i 1 -c 1 $dirname/d3
+ dirname=$dirname/d3/subdir
+ mkdir $dirname
+
+ trace_cmd stat $dirname
+ trace_cmd touch $dirname/f1
+ trace_cmd stat $dirname/f1
+ trace_cmd cat $dirname/f1
+ dd if=/dev/zero of=$dirname/f1 bs=1M count=10
+ trace_cmd /usr/bin/truncate -s 10240 $dirname/f1
+ trace_cmd lfs setstripe -E -1 -S 4M $dirname/f2
+ trace_cmd lfs migrate -E -1 -S 256K $dirname/f2
+}
+run_test 20d "[atomicity] avoid getxattr for security context"
complete $SECONDS
check_and_cleanup_lustre