From 4ea24bdabb2b318721605bd185c32bbc1e9bc924 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Thu, 11 Feb 2016 08:36:37 -0600 Subject: [PATCH] LU-5560 security: send file security context for creates Send file security context to MDT along with create RPCs. This closes the insecure window between creation and setting of the security context that existed previously. It also avoids a potential LDLM hang which arises from ll_create_it() when we send a MDS_SETXATTR RPC while holding the lookup+layout lock returned from open. Signed-off-by: John L. Hammond Signed-off-by: Sebastien Buisson Change-Id: I21415593b7dd362fecbb18cf90b1dc9fbf1c13db Reviewed-on: http://review.whamcloud.com/19971 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 18 ++++++++ lustre/include/lustre_req_layout.h | 4 +- lustre/include/md_object.h | 9 +++- lustre/include/obd.h | 5 +++ lustre/llite/dir.c | 62 ++++++++++++++++++++-------- lustre/llite/llite_internal.h | 10 +++-- lustre/llite/llite_lib.c | 16 ++++++++ lustre/llite/namei.c | 54 ++++++++++++++++++------ lustre/llite/xattr_security.c | 52 +++++++++++++++++++++-- lustre/mdc/mdc_internal.h | 4 ++ lustre/mdc/mdc_lib.c | 32 +++++++++++++++ lustre/mdc/mdc_locks.c | 7 ++++ lustre/mdc/mdc_reint.c | 7 ++++ lustre/mdd/mdd_dir.c | 25 ++++++++++-- lustre/mdt/mdt_lib.c | 48 +++++++++++++++++++++- lustre/ptlrpc/layout.c | 84 +++++++++++++++++++++++--------------- 16 files changed, 359 insertions(+), 78 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 41048be..f47d26c 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -1431,6 +1431,23 @@ block_device_ops_release_return_int, [ ]) # LC_BLKDEV_RELEASE_RETURN_INT # +# LC_HAVE_SECURITY_DENTRY_INIT_SECURITY +# +# 3.10 introduced security_dentry_init_security() +# +AC_DEFUN([LC_HAVE_SECURITY_DENTRY_INIT_SECURITY], [ +LB_CHECK_COMPILE([if 'security_dentry_init_security' is defined], +security_dentry_init_security, [ + #include +],[ + security_dentry_init_security(NULL, 0, NULL, NULL, NULL); +],[ + AC_DEFINE(HAVE_SECURITY_DENTRY_INIT_SECURITY, 1, + [security_dentry_init_security' is defined]) +]) +]) # LC_HAVE_SECURITY_DENTRY_INIT_SECURITY + +# # LC_INVALIDATE_RANGE # # 3.11 invalidatepage requires the length of the range to invalidate @@ -2276,6 +2293,7 @@ AC_DEFUN([LC_PROG_LINUX], [ LC_BLKDEV_RELEASE_RETURN_INT LC_HAVE_REMOVE_PROC_SUBTREE LC_HAVE_PROC_REMOVE + LC_HAVE_SECURITY_DENTRY_INIT_SECURITY # 3.11 LC_INVALIDATE_RANGE diff --git a/lustre/include/lustre_req_layout.h b/lustre/include/lustre_req_layout.h index 9fdc1e5..3eef31f 100644 --- a/lustre/include/lustre_req_layout.h +++ b/lustre/include/lustre_req_layout.h @@ -61,7 +61,7 @@ enum req_location { }; /* Maximal number of fields (buffers) in a request message. */ -#define REQ_MAX_FIELD_NR 9 +#define REQ_MAX_FIELD_NR 10 struct req_capsule { struct ptlrpc_request *rc_req; @@ -265,6 +265,8 @@ extern struct req_msg_field RMF_GETINFO_VALLEN; extern struct req_msg_field RMF_GETINFO_KEY; extern struct req_msg_field RMF_IDX_INFO; extern struct req_msg_field RMF_CLOSE_DATA; +extern struct req_msg_field RMF_FILE_SECCTX_NAME; +extern struct req_msg_field RMF_FILE_SECCTX; /* * connection handle received in MDS_CONNECT request. diff --git a/lustre/include/md_object.h b/lustre/include/md_object.h index c34c6e2..1427189 100644 --- a/lustre/include/md_object.h +++ b/lustre/include/md_object.h @@ -139,8 +139,13 @@ struct md_op_spec { } sp_ea; } u; - /** Create flag from client: such as MDS_OPEN_CREAT, and others. */ - __u64 sp_cr_flags; + /** Create flag from client: such as MDS_OPEN_CREAT, and others. */ + __u64 sp_cr_flags; + + /* File security context for creates. */ + const char *sp_cr_file_secctx_name; /* (security) xattr name */ + void *sp_cr_file_secctx; /* xattr value */ + size_t sp_cr_file_secctx_size; /* xattr value size */ /** don't create lov objects or llog cookie - this replay */ unsigned int no_create:1, diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 04cdca5..460ce5b 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -834,6 +834,11 @@ struct md_op_data { __u64 op_data_version; struct lustre_handle op_lease_handle; + /* File security context, for creates. */ + const char *op_file_secctx_name; + void *op_file_secctx; + __u32 op_file_secctx_size; + /* default stripe offset */ __u32 op_default_stripe_offset; }; diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 3536107..2018afa 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -438,22 +438,30 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) /** * Create striped directory with specified stripe(@lump) * - * param[in]parent the parent of the directory. - * param[in]lump the specified stripes. - * param[in]dirname the name of the directory. - * param[in]mode the specified mode of the directory. + * \param[in] dparent the parent of the directory. + * \param[in] lump the specified stripes. + * \param[in] dirname the name of the directory. + * \param[in] mode the specified mode of the directory. * - * retval =0 if striped directory is being created successfully. + * \retval =0 if striped directory is being created successfully. * <0 if the creation is failed. */ -static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, +static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump, const char *dirname, umode_t mode) { + struct inode *parent = dparent->d_inode; struct ptlrpc_request *request = NULL; struct md_op_data *op_data; struct ll_sb_info *sbi = ll_i2sbi(parent); struct inode *inode = NULL; - struct dentry dentry; + struct dentry dentry = { + .d_parent = dparent, + .d_name = { + .name = dirname, + .len = strlen(dirname), + .hash = full_name_hash(dirname, strlen(dirname)), + }, + }; int err; ENTRY; @@ -483,33 +491,50 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, strlen(dirname), mode, LUSTRE_OPC_MKDIR, lump); if (IS_ERR(op_data)) - GOTO(err_exit, err = PTR_ERR(op_data)); + RETURN(PTR_ERR(op_data)); + + if (sbi->ll_flags & LL_SBI_FILE_SECCTX) { + /* selinux_dentry_init_security() uses dentry->d_parent and name + * to determine the security context for the file. So our fake + * dentry should be real enough for this purpose. */ + err = ll_dentry_init_security(&dentry, mode, &dentry.d_name, + &op_data->op_file_secctx_name, + &op_data->op_file_secctx, + &op_data->op_file_secctx_size); + if (err < 0) + GOTO(out_op_data, err); + } op_data->op_cli_flags |= CLI_SET_MEA; err = md_create(sbi->ll_md_exp, op_data, lump, sizeof(*lump), mode, from_kuid(&init_user_ns, current_fsuid()), from_kgid(&init_user_ns, current_fsgid()), cfs_curproc_cap_pack(), 0, &request); - ll_finish_md_op_data(op_data); if (err) - GOTO(err_exit, err); + GOTO(out_request, err); CFS_FAIL_TIMEOUT(OBD_FAIL_LLITE_SETDIRSTRIPE_PAUSE, cfs_fail_val); err = ll_prep_inode(&inode, request, parent->i_sb, NULL); if (err) - GOTO(err_exit, err); + GOTO(out_inode, err); - memset(&dentry, 0, sizeof(dentry)); dentry.d_inode = inode; - err = ll_init_security(&dentry, inode, parent); - iput(inode); - if (err) - GOTO(err_exit, err); + if (!(sbi->ll_flags & LL_SBI_FILE_SECCTX)) { + err = ll_inode_init_security(&dentry, inode, parent); + if (err) + GOTO(out_inode, err); + } -err_exit: +out_inode: + if (inode != NULL) + iput(inode); +out_request: ptlrpc_req_finished(request); +out_op_data: + ll_finish_md_op_data(op_data); + return err; } @@ -1093,6 +1118,7 @@ static char *ll_getname(const char __user *filename) static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + struct dentry *dentry = file_dentry(file); struct inode *inode = file_inode(file); struct ll_sb_info *sbi = ll_i2sbi(inode); struct obd_ioctl_data *data; @@ -1201,7 +1227,7 @@ out_free: #else mode = data->ioc_type; #endif - rc = ll_dir_setdirstripe(inode, lum, filename, mode); + rc = ll_dir_setdirstripe(dentry, lum, filename, mode); lmv_out_free: obd_ioctl_freedata(buf, len); RETURN(rc); diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index f2971e5..f11ecdd 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -291,9 +291,11 @@ int ll_xattr_cache_get(struct inode *inode, size_t size, __u64 valid); -int ll_init_security(struct dentry *dentry, - struct inode *inode, - struct inode *dir); +int ll_dentry_init_security(struct dentry *dentry, int mode, struct qstr *name, + const char **secctx_name, void **secctx, + __u32 *secctx_size); +int ll_inode_init_security(struct dentry *dentry, struct inode *inode, + struct inode *dir); /* * Locking to guarantee consistency of non-atomic updates to long long i_size, @@ -424,6 +426,7 @@ enum stats_track_type { #define LL_SBI_ALWAYS_PING 0x200000 /* always ping even if server * suppress_pings */ #define LL_SBI_FAST_READ 0x400000 /* fast read support */ +#define LL_SBI_FILE_SECCTX 0x800000 /* set file security context at create */ #define LL_SBI_FLAGS { \ "nolck", \ @@ -449,6 +452,7 @@ enum stats_track_type { "norootsquash", \ "always_ping", \ "fast_read", \ + "file_secctx", \ } /* This is embedded into llite super-blocks to keep track of connect diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index be4fc6f..edae212 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -50,6 +50,7 @@ #ifdef HAVE_UIDGID_HEADER # include #endif +#include #include #include @@ -161,6 +162,12 @@ static void ll_free_sbi(struct super_block *sb) EXIT; } +static inline int obd_connect_has_secctx(struct obd_connect_data *data) +{ + return data->ocd_connect_flags & OBD_CONNECT_FLAGS2 && + data->ocd_connect_flags2 & OBD_CONNECT2_FILE_SECCTX; +} + static int client_common_fill_super(struct super_block *sb, char *md, char *dt, struct vfsmount *mnt) { @@ -248,6 +255,10 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (sbi->ll_flags & LL_SBI_ALWAYS_PING) data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS; +#ifdef HAVE_SECURITY_DENTRY_INIT_SECURITY + data->ocd_connect_flags2 |= OBD_CONNECT2_FILE_SECCTX; +#endif /* HAVE_SECURITY_DENTRY_INIT_SECURITY */ + data->ocd_brw_size = MD_MAX_BRW_SIZE; err = obd_connect(NULL, &sbi->ll_md_exp, obd, &sbi->ll_sb_uuid, data, NULL); @@ -352,6 +363,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; + if (obd_connect_has_secctx(data)) + sbi->ll_flags |= LL_SBI_FILE_SECCTX; + if (data->ocd_ibits_known & MDS_INODELOCK_XATTR) { if (!(data->ocd_connect_flags & OBD_CONNECT_MAX_EASIZE)) { LCONSOLE_INFO("%s: disabling xattr cache due to " @@ -2465,6 +2479,8 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, void ll_finish_md_op_data(struct md_op_data *op_data) { + security_release_secctx(op_data->op_file_secctx, + op_data->op_file_secctx_size); OBD_FREE_PTR(op_data); } diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 1427c6a..89624e6 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -591,12 +591,23 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, op_data = ll_prep_md_op_data(NULL, parent, NULL, dentry->d_name.name, dentry->d_name.len, 0, opc, NULL); if (IS_ERR(op_data)) - RETURN((void *)op_data); + GOTO(out, retval = ERR_CAST(op_data)); /* enforce umask if acl disabled or MDS doesn't support umask */ if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent))) it->it_create_mode &= ~current_umask(); + if (it->it_op & IT_CREAT && + ll_i2sbi(parent)->ll_flags & LL_SBI_FILE_SECCTX) { + rc = ll_dentry_init_security(dentry, it->it_create_mode, + &dentry->d_name, + &op_data->op_file_secctx_name, + &op_data->op_file_secctx, + &op_data->op_file_secctx_size); + if (rc < 0) + GOTO(out, retval = ERR_PTR(rc)); + } + rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req, &ll_md_blocking_ast, 0); /* If the MDS allows the client to chgrp (CFS_SETGRP_PERM), but the @@ -920,9 +931,11 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, d_instantiate(dentry, inode); - rc = ll_init_security(dentry, inode, dir); - if (rc) - RETURN(rc); + if (!(ll_i2sbi(inode)->ll_flags & LL_SBI_FILE_SECCTX)) { + rc = ll_inode_init_security(dentry, inode, dir); + if (rc) + RETURN(rc); + } RETURN(0); } @@ -962,16 +975,26 @@ static int ll_new_node(struct inode *dir, struct dentry *dchild, tgt_len = strlen(tgt) + 1; again: - op_data = ll_prep_md_op_data(NULL, dir, NULL, name->name, - name->len, 0, opc, NULL); - if (IS_ERR(op_data)) - GOTO(err_exit, err = PTR_ERR(op_data)); + op_data = ll_prep_md_op_data(NULL, dir, NULL, name->name, + name->len, 0, opc, NULL); + if (IS_ERR(op_data)) + GOTO(err_exit, err = PTR_ERR(op_data)); + + if (sbi->ll_flags & LL_SBI_FILE_SECCTX) { + err = ll_dentry_init_security(dchild, mode, &dchild->d_name, + &op_data->op_file_secctx_name, + &op_data->op_file_secctx, + &op_data->op_file_secctx_size); + if (err < 0) + GOTO(err_exit, err); + } err = md_create(sbi->ll_md_exp, op_data, tgt, tgt_len, mode, from_kuid(&init_user_ns, current_fsuid()), from_kgid(&init_user_ns, current_fsgid()), cfs_curproc_cap_pack(), rdev, &request); ll_finish_md_op_data(op_data); + op_data = NULL; if (err < 0 && err != -EREMOTE) GOTO(err_exit, err); @@ -1018,16 +1041,21 @@ again: d_instantiate(dchild, inode); - err = ll_init_security(dchild, inode, dir); - if (err) - GOTO(err_exit, err); + if (!(sbi->ll_flags & LL_SBI_FILE_SECCTX)) { + err = ll_inode_init_security(dchild, inode, dir); + if (err) + GOTO(err_exit, err); + } - EXIT; + EXIT; err_exit: if (request != NULL) ptlrpc_req_finished(request); - return err; + if (!IS_ERR_OR_NULL(op_data)) + ll_finish_md_op_data(op_data); + + return err; } static int ll_mknod(struct inode *dir, struct dentry *dchild, ll_umode_t mode, diff --git a/lustre/llite/xattr_security.c b/lustre/llite/xattr_security.c index 4cb17b5..37ba2a4 100644 --- a/lustre/llite/xattr_security.c +++ b/lustre/llite/xattr_security.c @@ -29,12 +29,56 @@ * Handler for storing security labels as extended attributes. */ - +#include #include #include #include #include "llite_internal.h" +#ifndef XATTR_SELINUX_SUFFIX +# define XATTR_SELINUX_SUFFIX "selinux" +#endif + +#ifndef XATTR_NAME_SELINUX +# define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX +#endif + +/* + * Check for LL_SBI_FILE_SECCTX before calling. + */ +int ll_dentry_init_security(struct dentry *dentry, int mode, struct qstr *name, + const char **secctx_name, void **secctx, + __u32 *secctx_size) +{ +#ifdef HAVE_SECURITY_DENTRY_INIT_SECURITY + int rc; + + /* security_dentry_init_security() is strange. Like + * security_inode_init_security() it may return a context (provided a + * Linux security module is enabled) but unlike + * security_inode_init_security() it does not return to us the name of + * the extended attribute to store the context under (for example + * "security.selinux"). So we only call it when we think we know what + * the name of the extended attribute will be. This is OK-ish since + * SELinux is the only module that implements + * security_dentry_init_security(). Note that the NFS client code just + * calls it and assumes that if anything is returned then it must come + * from SELinux. */ + + if (!selinux_is_enabled()) + return 0; + + rc = security_dentry_init_security(dentry, mode, name, secctx, + secctx_size); + if (rc < 0) + return rc; + + *secctx_name = XATTR_NAME_SELINUX; +#endif /* HAVE_SECURITY_DENTRY_INIT_SECURITY */ + + return 0; +} + #ifdef HAVE_SECURITY_IINITSEC_CALLBACK /** * A helper function for ll_security_inode_init_security() @@ -89,7 +133,8 @@ ll_initxattrs(struct inode *inode, const struct xattr *xattr_array, * \retval < 0 failure to get security context or set xattr */ int -ll_init_security(struct dentry *dentry, struct inode *inode, struct inode *dir) +ll_inode_init_security(struct dentry *dentry, struct inode *inode, + struct inode *dir) { if (!selinux_is_enabled()) return 0; @@ -109,7 +154,8 @@ ll_init_security(struct dentry *dentry, struct inode *inode, struct inode *dir) * \retval < 0 failure to get security context or set xattr */ int -ll_init_security(struct dentry *dentry, struct inode *inode, struct inode *dir) +ll_inode_init_security(struct dentry *dentry, struct inode *inode, + struct inode *dir) { int err; size_t len, name_len; diff --git a/lustre/mdc/mdc_internal.h b/lustre/mdc/mdc_internal.h index 48bad01..b88d7f5 100644 --- a/lustre/mdc/mdc_internal.h +++ b/lustre/mdc/mdc_internal.h @@ -59,6 +59,10 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, umode_t mode, __u64 rdev, __u64 flags, const void *data, size_t datalen); +void mdc_file_secctx_pack(struct ptlrpc_request *req, + const char *secctx_name, + const void *secctx, size_t secctx_size); + void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_getxattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); diff --git a/lustre/mdc/mdc_lib.c b/lustre/mdc/mdc_lib.c index 62e1cf9..f79c3a9 100644 --- a/lustre/mdc/mdc_lib.c +++ b/lustre/mdc/mdc_lib.c @@ -119,6 +119,30 @@ static void mdc_pack_name(struct ptlrpc_request *req, LASSERT(cpy_len == name_len && lu_name_is_valid_2(buf, cpy_len)); } +void mdc_file_secctx_pack(struct ptlrpc_request *req, const char *secctx_name, + const void *secctx, size_t secctx_size) +{ + void *buf; + size_t buf_size; + + if (secctx_name == NULL) + return; + + buf = req_capsule_client_get(&req->rq_pill, &RMF_FILE_SECCTX_NAME); + buf_size = req_capsule_get_size(&req->rq_pill, &RMF_FILE_SECCTX_NAME, + RCL_CLIENT); + + LASSERT(buf_size == strlen(secctx_name) + 1); + memcpy(buf, secctx_name, buf_size); + + buf = req_capsule_client_get(&req->rq_pill, &RMF_FILE_SECCTX); + buf_size = req_capsule_get_size(&req->rq_pill, &RMF_FILE_SECCTX, + RCL_CLIENT); + + LASSERT(buf_size == secctx_size); + memcpy(buf, secctx, buf_size); +} + void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, size_t size, const struct lu_fid *fid) { @@ -168,6 +192,10 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA); memcpy(tmp, data, datalen); } + + mdc_file_secctx_pack(req, op_data->op_file_secctx_name, + op_data->op_file_secctx, + op_data->op_file_secctx_size); } static inline __u64 mds_pack_open_flags(__u64 flags) @@ -237,6 +265,10 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, if (op_data->op_bias & MDS_CREATE_VOLATILE) cr_flags |= MDS_OPEN_VOLATILE; } + + mdc_file_secctx_pack(req, op_data->op_file_secctx_name, + op_data->op_file_secctx, + op_data->op_file_secctx_size); } if (lmm) { diff --git a/lustre/mdc/mdc_locks.c b/lustre/mdc/mdc_locks.c index 53c74e7..08f226e 100644 --- a/lustre/mdc/mdc_locks.c +++ b/lustre/mdc/mdc_locks.c @@ -295,6 +295,13 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, max(lmmsize, obddev->u.cli.cl_default_mds_easize)); + 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); + + req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX, RCL_CLIENT, + op_data->op_file_secctx_size); + rc = ldlm_prep_enqueue_req(exp, req, &cancels, count); if (rc < 0) { ptlrpc_request_free(req); diff --git a/lustre/mdc/mdc_reint.c b/lustre/mdc/mdc_reint.c index 4abd2bc..5044b89 100644 --- a/lustre/mdc/mdc_reint.c +++ b/lustre/mdc/mdc_reint.c @@ -197,6 +197,13 @@ rebuild: req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, data && datalen ? datalen : 0); + 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); + + req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX, RCL_CLIENT, + op_data->op_file_secctx_size); + rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); if (rc) { ptlrpc_request_free(req); diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index bb96d7c..0e4d287 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -2016,6 +2016,7 @@ static int mdd_declare_object_create(const struct lu_env *env, struct lu_buf *acl_buf, struct dt_allocation_hint *hint) { + const struct lu_buf *buf; int rc; rc = mdd_declare_object_create_internal(env, p, c, attr, handle, spec, @@ -2051,8 +2052,6 @@ static int mdd_declare_object_create(const struct lu_env *env, /* replay case, create LOV EA from client data */ if (spec->no_create || (spec->sp_cr_flags & MDS_OPEN_HAS_EA && S_ISREG(attr->la_mode))) { - const struct lu_buf *buf; - buf = mdd_buf_get_const(env, spec->u.sp_ea.eadata, spec->u.sp_ea.eadatalen); rc = mdo_declare_xattr_set(env, c, buf, XATTR_NAME_LOV, 0, @@ -2072,6 +2071,16 @@ static int mdd_declare_object_create(const struct lu_env *env, if (rc) GOTO(out, rc); } + + if (spec->sp_cr_file_secctx_name != NULL) { + buf = mdd_buf_get_const(env, spec->sp_cr_file_secctx, + spec->sp_cr_file_secctx_size); + rc = mdo_declare_xattr_set(env, c, buf, + spec->sp_cr_file_secctx_name, 0, + handle); + if (rc < 0) + GOTO(out, rc); + } out: return rc; } @@ -2182,6 +2191,7 @@ static int mdd_object_create(const struct lu_env *env, struct mdd_object *pobj, struct dt_allocation_hint *hint, struct thandle *handle) { + const struct lu_buf *buf; int rc; mdd_write_lock(env, son, MOR_TGT_CHILD); @@ -2217,8 +2227,6 @@ static int mdd_object_create(const struct lu_env *env, struct mdd_object *pobj, if (spec->no_create || (S_ISREG(attr->la_mode) && spec->sp_cr_flags & MDS_OPEN_HAS_EA) || S_ISDIR(attr->la_mode)) { - const struct lu_buf *buf; - buf = mdd_buf_get_const(env, spec->u.sp_ea.eadata, spec->u.sp_ea.eadatalen); rc = mdo_xattr_set(env, son, buf, @@ -2268,6 +2276,15 @@ static int mdd_object_create(const struct lu_env *env, struct mdd_object *pobj, GOTO(err_initlized, rc = -EFAULT); } + if (spec->sp_cr_file_secctx_name != NULL) { + buf = mdd_buf_get_const(env, spec->sp_cr_file_secctx, + spec->sp_cr_file_secctx_size); + rc = mdo_xattr_set(env, son, buf, spec->sp_cr_file_secctx_name, + 0, handle); + if (rc < 0) + GOTO(err_initlized, rc); + } + err_initlized: if (unlikely(rc != 0)) { int rc2; diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index 990b482..de68b11 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -852,6 +852,41 @@ int mdt_name_unpack(struct req_capsule *pill, return 0; } +static int mdt_file_secctx_unpack(struct req_capsule *pill, + const char **secctx_name, + void **secctx, size_t *secctx_size) +{ + const char *name; + size_t name_size; + + *secctx_name = NULL; + *secctx = NULL; + *secctx_size = 0; + + if (!req_capsule_has_field(pill, &RMF_FILE_SECCTX_NAME, RCL_CLIENT) || + !req_capsule_field_present(pill, &RMF_FILE_SECCTX_NAME, RCL_CLIENT)) + return 0; + + name_size = req_capsule_get_size(pill, &RMF_FILE_SECCTX_NAME, + RCL_CLIENT); + if (name_size == 0) + return 0; + + name = req_capsule_client_get(pill, &RMF_FILE_SECCTX_NAME); + if (strnlen(name, name_size) != name_size - 1) + return -EPROTO; + + if (!req_capsule_has_field(pill, &RMF_FILE_SECCTX, RCL_CLIENT) || + !req_capsule_field_present(pill, &RMF_FILE_SECCTX, RCL_CLIENT)) + return -EPROTO; + + *secctx_name = name; + *secctx = req_capsule_client_get(pill, &RMF_FILE_SECCTX); + *secctx_size = req_capsule_get_size(pill, &RMF_FILE_SECCTX, RCL_CLIENT); + + return 0; +} + static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) { struct lu_ucred *uc = mdt_ucred(info); @@ -1087,6 +1122,12 @@ static int mdt_create_unpack(struct mdt_thread_info *info) } } + rc = mdt_file_secctx_unpack(pill, &sp->sp_cr_file_secctx_name, + &sp->sp_cr_file_secctx, + &sp->sp_cr_file_secctx_size); + if (rc < 0) + RETURN(rc); + rc = mdt_dlmreq_unpack(info); RETURN(rc); } @@ -1278,6 +1319,7 @@ static int mdt_open_unpack(struct mdt_thread_info *info) struct mdt_reint_record *rr = &info->mti_rr; struct ptlrpc_request *req = mdt_info_req(info); struct md_op_spec *sp = &info->mti_spec; + int rc; ENTRY; CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint)); @@ -1337,7 +1379,11 @@ static int mdt_open_unpack(struct mdt_thread_info *info) rr->rr_eadatalen = MIN_MD_SIZE; } - RETURN(0); + rc = mdt_file_secctx_unpack(pill, &sp->sp_cr_file_secctx_name, + &sp->sp_cr_file_secctx, + &sp->sp_cr_file_secctx_size); + + RETURN(rc); } static int mdt_setxattr_unpack(struct mdt_thread_info *info) diff --git a/lustre/ptlrpc/layout.c b/lustre/ptlrpc/layout.c index 92f31e2..6bb87ec 100644 --- a/lustre/ptlrpc/layout.c +++ b/lustre/ptlrpc/layout.c @@ -216,30 +216,36 @@ static const struct req_msg_field *mds_reint_create_slave_client[] = { }; static const struct req_msg_field *mds_reint_create_acl_client[] = { - &RMF_PTLRPC_BODY, - &RMF_REC_REINT, - &RMF_CAPA1, - &RMF_NAME, - &RMF_EADATA, - &RMF_DLM_REQ + &RMF_PTLRPC_BODY, + &RMF_REC_REINT, + &RMF_CAPA1, + &RMF_NAME, + &RMF_EADATA, + &RMF_DLM_REQ, + &RMF_FILE_SECCTX_NAME, + &RMF_FILE_SECCTX }; static const struct req_msg_field *mds_reint_create_sym_client[] = { - &RMF_PTLRPC_BODY, - &RMF_REC_REINT, - &RMF_CAPA1, - &RMF_NAME, - &RMF_SYMTGT, - &RMF_DLM_REQ + &RMF_PTLRPC_BODY, + &RMF_REC_REINT, + &RMF_CAPA1, + &RMF_NAME, + &RMF_SYMTGT, + &RMF_DLM_REQ, + &RMF_FILE_SECCTX_NAME, + &RMF_FILE_SECCTX }; static const struct req_msg_field *mds_reint_open_client[] = { - &RMF_PTLRPC_BODY, - &RMF_REC_REINT, - &RMF_CAPA1, - &RMF_CAPA2, - &RMF_NAME, - &RMF_EADATA + &RMF_PTLRPC_BODY, + &RMF_REC_REINT, + &RMF_CAPA1, + &RMF_CAPA2, + &RMF_NAME, + &RMF_EADATA, + &RMF_FILE_SECCTX_NAME, + &RMF_FILE_SECCTX }; static const struct req_msg_field *mds_reint_open_server[] = { @@ -453,24 +459,28 @@ static const struct req_msg_field *ldlm_intent_getattr_server[] = { }; static const struct req_msg_field *ldlm_intent_create_client[] = { - &RMF_PTLRPC_BODY, - &RMF_DLM_REQ, - &RMF_LDLM_INTENT, - &RMF_REC_REINT, /* coincides with mds_reint_create_client[] */ - &RMF_CAPA1, - &RMF_NAME, - &RMF_EADATA + &RMF_PTLRPC_BODY, + &RMF_DLM_REQ, + &RMF_LDLM_INTENT, + &RMF_REC_REINT, /* coincides with mds_reint_create_client[] */ + &RMF_CAPA1, + &RMF_NAME, + &RMF_EADATA, + &RMF_FILE_SECCTX_NAME, + &RMF_FILE_SECCTX }; static const struct req_msg_field *ldlm_intent_open_client[] = { - &RMF_PTLRPC_BODY, - &RMF_DLM_REQ, - &RMF_LDLM_INTENT, - &RMF_REC_REINT, /* coincides with mds_reint_open_client[] */ - &RMF_CAPA1, - &RMF_CAPA2, - &RMF_NAME, - &RMF_EADATA + &RMF_PTLRPC_BODY, + &RMF_DLM_REQ, + &RMF_LDLM_INTENT, + &RMF_REC_REINT, /* coincides with mds_reint_open_client[] */ + &RMF_CAPA1, + &RMF_CAPA2, + &RMF_NAME, + &RMF_EADATA, + &RMF_FILE_SECCTX_NAME, + &RMF_FILE_SECCTX }; static const struct req_msg_field *ldlm_intent_unlink_client[] = { @@ -997,6 +1007,14 @@ struct req_msg_field RMF_STRING = DEFINE_MSGF("string", RMF_F_STRING, -1, NULL, NULL); EXPORT_SYMBOL(RMF_STRING); +struct req_msg_field RMF_FILE_SECCTX_NAME = + DEFINE_MSGF("file_secctx_name", RMF_F_STRING, -1, NULL, NULL); +EXPORT_SYMBOL(RMF_FILE_SECCTX_NAME); + +struct req_msg_field RMF_FILE_SECCTX = + DEFINE_MSGF("file_secctx", 0, -1, NULL, NULL); +EXPORT_SYMBOL(RMF_FILE_SECCTX); + struct req_msg_field RMF_LLOGD_BODY = DEFINE_MSGF("llogd_body", 0, sizeof(struct llogd_body), lustre_swab_llogd_body, NULL); -- 1.8.3.1