extern struct req_format RQF_OBD_PING;
extern struct req_format RQF_OBD_SET_INFO;
+extern struct req_format RQF_MDT_SET_INFO;
extern struct req_format RQF_SEC_CTX;
extern struct req_format RQF_OBD_IDX_READ;
/* MGS req_format */
__swab32s(&cs->cs_id);
}
+ if (!mdt_is_rootadmin(tsi2mdt_info(tsi)))
+ RETURN(-EACCES);
rc = mdt_iocontrol(OBD_IOC_CHANGELOG_CLEAR, req->rq_export,
vallen, val, NULL);
} else if (KEY_IS(KEY_EVICT_BY_NID)) {
return rc;
}
+static int mdt_llog_open(struct tgt_session_info *tsi)
+{
+ ENTRY;
+
+ if (!mdt_is_rootadmin(tsi2mdt_info(tsi)))
+ RETURN(err_serious(-EACCES));
+
+ RETURN(tgt_llog_open(tsi));
+}
+
#define OBD_FAIL_OST_READ_NET OBD_FAIL_OST_BRW_NET
#define OBD_FAIL_OST_WRITE_NET OBD_FAIL_OST_BRW_NET
#define OST_BRW_READ OST_READ
&RQF_MDS_DISCONNECT, LUSTRE_OBD_VERSION),
TGT_RPC_HANDLER(MDS_FIRST_OPC,
HAS_REPLY, MDS_SET_INFO, mdt_set_info,
- &RQF_OBD_SET_INFO, LUSTRE_MDS_VERSION),
+ &RQF_MDT_SET_INFO, LUSTRE_MDS_VERSION),
TGT_MDT_HDL(0, MDS_GET_INFO, mdt_get_info),
TGT_MDT_HDL(HAS_REPLY, MDS_GET_ROOT, mdt_get_root),
TGT_MDT_HDL(HAS_BODY, MDS_GETATTR, mdt_getattr),
TGT_QUOTA_HDL(HAS_REPLY, QUOTA_DQACQ, mdt_quota_dqacq),
};
+static struct tgt_handler mdt_llog_handlers[] = {
+ TGT_LLOG_HDL(0, LLOG_ORIGIN_HANDLE_CREATE, mdt_llog_open),
+ TGT_LLOG_HDL(0, LLOG_ORIGIN_HANDLE_NEXT_BLOCK, tgt_llog_next_block),
+ TGT_LLOG_HDL(0, LLOG_ORIGIN_HANDLE_READ_HEADER, tgt_llog_read_header),
+ TGT_LLOG_HDL(0, LLOG_ORIGIN_HANDLE_PREV_BLOCK, tgt_llog_prev_block),
+};
+
static struct tgt_opc_slice mdt_common_slice[] = {
{
.tos_opc_start = MDS_FIRST_OPC,
{
.tos_opc_start = LLOG_FIRST_OPC,
.tos_opc_end = LLOG_LAST_OPC,
- .tos_hs = tgt_llog_handlers
+ .tos_hs = mdt_llog_handlers
},
{
.tos_opc_start = LFSCK_FIRST_OPC,
u64 want, bool conservative);
extern struct kmem_cache *ldlm_glimpse_work_kmem;
+static inline bool mdt_is_rootadmin(struct mdt_thread_info *info)
+{
+ struct lu_ucred *uc = NULL;
+ bool is_admin;
+ int rc;
+
+ if (info == NULL || info->mti_body == NULL)
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 17, 3, 0)
+ /* return true in case old client did not send mdt body */
+ return true;
+#else
+ return false
+#endif
+
+ rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
+ if (rc < 0)
+ return false;
+
+ uc = mdt_ucred(info);
+ is_admin = (uc->uc_uid == 0 && uc->uc_gid == 0 &&
+ md_capable(uc, CFS_CAP_SYS_ADMIN));
+
+ mdt_exit_ucred(info);
+
+ return is_admin;
+}
+
+
#endif /* _MDT_INTERNAL_H */
&RMF_SETINFO_VAL
};
+static const struct req_msg_field *mdt_set_info_client[] = {
+ &RMF_PTLRPC_BODY,
+ &RMF_SETINFO_KEY,
+ &RMF_SETINFO_VAL,
+ &RMF_MDT_BODY
+};
+
static const struct req_msg_field *ost_grant_shrink_client[] = {
&RMF_PTLRPC_BODY,
&RMF_SETINFO_KEY,
};
static const struct req_msg_field *llog_origin_handle_create_client[] = {
- &RMF_PTLRPC_BODY,
- &RMF_LLOGD_BODY,
- &RMF_NAME
+ &RMF_PTLRPC_BODY,
+ &RMF_LLOGD_BODY,
+ &RMF_NAME,
+ &RMF_MDT_BODY
};
static const struct req_msg_field *llogd_body_only[] = {
static struct req_format *req_formats[] = {
&RQF_OBD_PING,
&RQF_OBD_SET_INFO,
+ &RQF_MDT_SET_INFO,
&RQF_OBD_IDX_READ,
&RQF_SEC_CTX,
&RQF_MGS_TARGET_REG,
DEFINE_REQ_FMT0("OBD_SET_INFO", obd_set_info_client, empty);
EXPORT_SYMBOL(RQF_OBD_SET_INFO);
+struct req_format RQF_MDT_SET_INFO =
+ DEFINE_REQ_FMT0("MDT_SET_INFO", mdt_set_info_client, empty);
+EXPORT_SYMBOL(RQF_MDT_SET_INFO);
+
/* Read index file through the network */
struct req_format RQF_OBD_IDX_READ =
DEFINE_REQ_FMT0("OBD_IDX_READ",
#include <lustre_log.h>
#include <lustre_net.h>
+#include "ptlrpc_internal.h"
+
#define LLOG_CLIENT_ENTRY(ctxt, imp) do { \
mutex_lock(&ctxt->loc_mutex); \
if (ctxt->loc_imp) { \
strlen(name) + 1);
LASSERT(tmp);
strcpy(tmp, name);
+
+ do_pack_body(req);
}
rc = ptlrpc_queue_wait(req);
int rc;
ENTRY;
- req = ptlrpc_request_alloc(imp, &RQF_OBD_SET_INFO);
+
+ req = ptlrpc_request_alloc(imp, KEY_IS(KEY_CHANGELOG_CLEAR) ?
+ &RQF_MDT_SET_INFO :
+ &RQF_OBD_SET_INFO);
if (req == NULL)
RETURN(-ENOMEM);
RETURN(rc);
}
+ if (KEY_IS(KEY_CHANGELOG_CLEAR))
+ do_pack_body(req);
+
tmp = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_KEY);
memcpy(tmp, key, keylen);
tmp = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_VAL);
return false;
}
+static inline void do_pack_body(struct ptlrpc_request *req)
+{
+ struct mdt_body *b = req_capsule_client_get(&req->rq_pill,
+ &RMF_MDT_BODY);
+
+ if (b == NULL)
+ return;
+
+ b->mbo_valid = 0;
+ b->mbo_eadatasize = 0;
+ b->mbo_flags = 0;
+ b->mbo_suppgid = -1;
+ b->mbo_uid = from_kuid(&init_user_ns, current_uid());
+ b->mbo_gid = from_kgid(&init_user_ns, current_gid());
+ b->mbo_fsuid = from_kuid(&init_user_ns, current_fsuid());
+ b->mbo_fsgid = from_kgid(&init_user_ns, current_fsgid());
+ b->mbo_capability = cfs_curproc_cap_pack();
+}
+
#endif /* PTLRPC_INTERNAL_H */
h->th_fmt != NULL));
if (h->th_fmt != NULL) {
req_capsule_set(pill, h->th_fmt);
- if (req_capsule_has_field(pill, &RMF_MDT_BODY, RCL_CLIENT)) {
+ if (req_capsule_has_field(pill, &RMF_MDT_BODY, RCL_CLIENT) &&
+ req_capsule_field_present(pill, &RMF_MDT_BODY,
+ RCL_CLIENT)) {
rc = tgt_mdt_body_unpack(tsi, flags);
if (rc < 0)
RETURN(rc);
} else if (req_capsule_has_field(pill, &RMF_OST_BODY,
+ RCL_CLIENT) &&
+ req_capsule_field_present(pill, &RMF_OST_BODY,
RCL_CLIENT)) {
rc = tgt_ost_body_unpack(tsi, flags);
if (rc < 0)
}
run_test 34 "deny_unknown on default nodemap"
+test_35() {
+ [ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.13.50) ] ||
+ skip "Need MDS >= 2.13.50"
+
+ # activate changelogs
+ changelog_register || error "changelog_register failed"
+ local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
+ changelog_users $SINGLEMDS | grep -q $cl_user ||
+ error "User $cl_user not found in changelog_users"
+ changelog_chmask ALL
+
+ # do some IOs
+ mkdir $DIR/$tdir || error "failed to mkdir $tdir"
+ touch $DIR/$tdir/$tfile || error "failed to touch $tfile"
+
+ # access changelogs with root
+ changelog_dump || error "failed to dump changelogs"
+ changelog_clear 0 || error "failed to clear changelogs"
+
+ # put clients in non-admin nodemap
+ nodemap_test_setup
+ stack_trap nodemap_test_cleanup EXIT
+ for i in $(seq 0 $((num_clients-1))); do
+ do_facet mgs $LCTL nodemap_modify --name c${i} \
+ --property admin --value 0
+ done
+ for i in $(seq 0 $((num_clients-1))); do
+ wait_nm_sync c${i} admin_nodemap
+ done
+
+ # access with mapped root
+ changelog_dump && error "dump changelogs should have failed"
+ changelog_clear 0 && error "clear changelogs should have failed"
+
+ exit 0
+}
+run_test 35 "Check permissions when accessing changelogs"
+
log "cleanup: ======================================================"
sec_unsetup() {
}
changelog_dump() {
+ local rc
+
for M in $(seq $MDSCOUNT); do
local facet=mds$M
local mdt="$(facet_svc $facet)"
-
- $LFS changelog $mdt | sed -e 's/^/'$mdt'./'
+ local output
+ local ret
+
+ output=$($LFS changelog $mdt)
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ rc=${rc:-$ret}
+ elif [ -n "$output" ]; then
+ echo "$output" | sed -e 's/^/'$mdt'./'
+ fi
done
+
+ return ${rc:-0}
}
changelog_extract_field() {