GSS srpc contexts for client connections can already be dumped via
proc file <mdc,osc>.*.srpc_contexts.
This patch adds a new proc file to dump server side GSS srpc contexts,
e.g.:
mgs.MGS.gss.srpc_serverctx
mdt.testfs-MDT0000.gss.srpc_serverctx
obdfilter.testfs-OST0000.gss.srpc_serverctx
The GSS context information is dumped as YAML, with one line per
context, like this:
-
0000000013221bdf: { peer_nid: 192.168.56.206@tcp, uid: 0, ctxref: 1,
expire:
1707934985, delta: 3401, flags: [uptodate, cached], seq: 0,
win: 2048, key:
00000000, keyref: 0,
hdl: "0x5ae1a771fd57043:0x65a64972fda4e200",
mech: "krb5 (aes256-cts-hmac-sha1-96)" }
Because of this new syntax, sanity-sec test_28 needs to be fixed.
Test-Parameters: trivial
Test-Parameters: kerberos=true testlist=sanity-krb5
Test-Parameters: testgroup=review-dne-selinux-ssk-part-2
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I37da9ffe6dd5884006b36271185a4d7155ead65b
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53376
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Aurelien Degremont <adegremont@nvidia.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
struct sptlrpc_flavor *flvr);
struct ptlrpc_sec *sptlrpc_import_sec_ref(struct obd_import *imp);
void sptlrpc_import_sec_put(struct obd_import *imp);
+int lprocfs_srpc_serverctx_seq_show(struct seq_file *m, void *data);
int sptlrpc_import_check_ctx(struct obd_import *imp);
void sptlrpc_import_flush_root_ctx(struct obd_import *imp);
struct lprocfs_stats *obd_md_stats;
struct dentry *obd_debugfs_entry;
+ struct dentry *obd_debugfs_gss_dir;
struct proc_dir_entry *obd_proc_entry;
struct proc_dir_entry *obd_proc_exports_entry;
struct dentry *obd_svc_debugfs_entry;
{ NULL }
};
+LDEBUGFS_SEQ_FOPS_RO_TYPE(mdt, srpc_serverctx);
+
+static struct ldebugfs_vars ldebugfs_mdt_gss_vars[] = {
+ { .name = "srpc_serverctx",
+ .fops = &mdt_srpc_serverctx_fops },
+ { NULL }
+};
+
static int
lprocfs_mdt_print_open_files(struct obd_export *exp, void *v)
{
return rc;
}
+ obd->obd_debugfs_gss_dir = debugfs_create_dir("gss",
+ obd->obd_debugfs_entry);
+ if (obd->obd_debugfs_gss_dir)
+ ldebugfs_add_vars(obd->obd_debugfs_gss_dir,
+ ldebugfs_mdt_gss_vars, obd);
+
obd->obd_proc_exports_entry = proc_mkdir("exports",
obd->obd_proc_entry);
if (obd->obd_proc_exports_entry)
LUSTRE_RO_ATTR(num_exports);
LUSTRE_RO_ATTR(eviction_count);
+LDEBUGFS_SEQ_FOPS_RO_TYPE(ofd, srpc_serverctx);
+
+static struct ldebugfs_vars ldebugfs_ofd_gss_vars[] = {
+ { .name = "srpc_serverctx",
+ .fops = &ofd_srpc_serverctx_fops },
+ { NULL }
+};
+
static ssize_t fstype_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
GOTO(out, rc);
}
+ obd->obd_debugfs_gss_dir = debugfs_create_dir("gss",
+ obd->obd_debugfs_entry);
+ if (obd->obd_debugfs_gss_dir)
+ ldebugfs_add_vars(obd->obd_debugfs_gss_dir,
+ ldebugfs_ofd_gss_vars, obd);
+
obd->obd_proc_exports_entry = lprocfs_register("exports",
obd->obd_proc_entry,
NULL, NULL);
if (!obd)
return -EINVAL;
+ debugfs_remove_recursive(obd->obd_debugfs_gss_dir);
+ obd->obd_debugfs_gss_dir = NULL;
+
if (obd->obd_proc_exports_entry) {
/* Should be no exports left */
lprocfs_remove(&obd->obd_proc_exports_entry);
{ NULL }
};
+LDEBUGFS_SEQ_FOPS_RO_TYPE(ofd, srpc_serverctx);
+
+static struct ldebugfs_vars ldebugfs_ofd_gss_vars[] = {
+ { .name = "srpc_serverctx",
+ .fops = &ofd_srpc_serverctx_fops },
+ { NULL }
+};
+
/**
* Initialize OFD statistics counters
*
GOTO(tgt_cleanup, rc);
}
+ obd->obd_debugfs_gss_dir = debugfs_create_dir("gss",
+ obd->obd_debugfs_entry);
+ if (obd->obd_debugfs_gss_dir)
+ ldebugfs_add_vars(obd->obd_debugfs_gss_dir,
+ ldebugfs_ofd_gss_vars, obd);
+
entry = lprocfs_register("exports", obd->obd_proc_entry, NULL, NULL);
if (IS_ERR(entry)) {
rc = PTR_ERR(entry);
struct hlist_node *next;
struct ptlrpc_cli_ctx *ctx;
struct gss_cli_ctx *gctx;
+ struct ptlrpc_connection *conn;
time64_t now = ktime_get_real_seconds();
ENTRY;
spin_lock(&sec->ps_lock);
hlist_for_each_entry_safe(ctx, next, &gsec_kr->gsk_clist,
cc_cache) {
- struct key *key;
- char flags_str[40];
- char mech[40];
+ struct key *key;
+ char flags_str[40];
+ char mech[40];
- gctx = ctx2gctx(ctx);
- key = ctx2gctx_keyring(ctx)->gck_key;
+ gctx = ctx2gctx(ctx);
+ key = ctx2gctx_keyring(ctx)->gck_key;
+ if (sec_is_reverse(sec) &&
+ ctx->cc_sec && ctx->cc_sec->ps_import &&
+ ctx->cc_sec->ps_import->imp_connection)
+ conn = ctx->cc_sec->ps_import->imp_connection;
+ else
+ conn = NULL;
- gss_cli_ctx_flags2str(ctx->cc_flags,
- flags_str, sizeof(flags_str));
+ gss_cli_ctx_flags2str(ctx->cc_flags,
+ flags_str, sizeof(flags_str));
- if (gctx->gc_mechctx)
- lgss_display(gctx->gc_mechctx, mech, sizeof(mech));
- else
- snprintf(mech, sizeof(mech), "N/A");
- mech[sizeof(mech) - 1] = '\0';
+ if (gctx->gc_mechctx)
+ lgss_display(gctx->gc_mechctx, mech, sizeof(mech));
+ else
+ snprintf(mech, sizeof(mech), "N/A");
+ mech[sizeof(mech) - 1] = '\0';
seq_printf(seq,
- "%p: uid %u, ref %d, expire %lld(%+lld), fl %s, seq %d, win %u, key %08x(ref %d), hdl %#llx:%#llx, mech: %s\n",
- ctx, ctx->cc_vcred.vc_uid,
- atomic_read(&ctx->cc_refcount),
+ "- %p: { %s%s%suid: %u, ctxref: %d, expire: %lld, delta: %lld, flags: [%s], seq: %d, win: %u, key: %08x, keyref: %d, hdl: \"%#llx:%#llx\", mech: \"%s\" }\n",
+ ctx, conn ? "peer_nid: " : "",
+ conn ? libcfs_nidstr(&conn->c_peer.nid) : "",
+ conn ? ", " : "",
+ ctx->cc_vcred.vc_uid, atomic_read(&ctx->cc_refcount),
ctx->cc_expire,
ctx->cc_expire ? ctx->cc_expire - now : 0,
- flags_str,
- atomic_read(&gctx->gc_seq),
- gctx->gc_win,
- key ? key->serial : 0,
+ flags_str, atomic_read(&gctx->gc_seq),
+ gctx->gc_win, key ? key->serial : 0,
key ? ll_read_key_usage(key) : 0,
gss_handle_to_u64(&gctx->gc_handle),
gss_handle_to_u64(&gctx->gc_svc_handle),
static inline unsigned long hash_mem_64(char *buf, int length, int bits)
{
- unsigned long hash = 0;
- unsigned long l = 0;
+ __u64 hash = 0;
+ __u64 l = 0;
int len = 0;
unsigned char c;
l = (l << 8) | c;
len++;
- if ((len & (BITS_PER_LONG/8-1)) == 0)
- hash = gss_hash_64(hash^l, BITS_PER_LONG);
+ if ((len & (BITS_PER_LONG / 8 - 1)) == 0)
+ hash = gss_hash_64(hash ^ l, BITS_PER_LONG);
} while (len);
return hash >> (BITS_PER_LONG - bits);
buf[0] = '\0';
if (flags & PTLRPC_CTX_NEW)
- strlcat(buf, "new,", bufsize);
+ strlcat(buf, "new, ", bufsize);
if (flags & PTLRPC_CTX_UPTODATE)
- strlcat(buf, "uptodate,", bufsize);
+ strlcat(buf, "uptodate, ", bufsize);
if (flags & PTLRPC_CTX_DEAD)
- strlcat(buf, "dead,", bufsize);
+ strlcat(buf, "dead, ", bufsize);
if (flags & PTLRPC_CTX_ERROR)
- strlcat(buf, "error,", bufsize);
+ strlcat(buf, "error, ", bufsize);
if (flags & PTLRPC_CTX_CACHED)
- strlcat(buf, "cached,", bufsize);
+ strlcat(buf, "cached, ", bufsize);
if (flags & PTLRPC_CTX_ETERNAL)
- strlcat(buf, "eternal,", bufsize);
- if (buf[0] == '\0')
- strlcat(buf, "-,", bufsize);
+ strlcat(buf, "eternal, ", bufsize);
+ if (buf[strlen(buf) - 2] == ',')
+ buf[strlen(buf) - 2] = '\0';
}
int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
RETURN(sec);
}
+static int print_srpc_serverctx_seq(struct obd_export *exp, void *cb_data)
+{
+ struct seq_file *m = cb_data;
+ struct obd_import *imp = exp->exp_imp_reverse;
+ struct ptlrpc_sec *sec = NULL;
+
+ if (imp)
+ sec = sptlrpc_import_sec_ref(imp);
+ if (sec == NULL)
+ goto out;
+
+ if (sec->ps_policy->sp_cops->display)
+ sec->ps_policy->sp_cops->display(sec, m);
+
+ sptlrpc_sec_put(sec);
+out:
+ return 0;
+}
+
+int lprocfs_srpc_serverctx_seq_show(struct seq_file *m, void *data)
+{
+ struct obd_device *obd = m->private;
+ struct obd_export *exp, *n;
+
+ spin_lock(&obd->obd_dev_lock);
+ list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) {
+ print_srpc_serverctx_seq(exp, m);
+ }
+ spin_unlock(&obd->obd_dev_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(lprocfs_srpc_serverctx_seq_show);
+
struct ptlrpc_sec *sptlrpc_import_sec_ref(struct obd_import *imp)
{
struct ptlrpc_sec *sec;
spin_unlock(&svcpt->scp_lock);
/* go through security check/transform */
+ CDEBUG(D_RPCTRACE, "unwrap req x%llu\n", req->rq_xid);
rc = sptlrpc_svc_unwrap_request(req);
switch (rc) {
case SECSVC_OK:
RETURN(1);
err_req:
+ CDEBUG(D_RPCTRACE, "finish req x%llu\n", req->rq_xid);
ptlrpc_server_finish_request(svcpt, req);
RETURN(1);
error "read before rotation failed"
fi
# store top key identity to ensure rotation has occurred
- SK_IDENTITY_OLD=$(lctl get_param *.*.*srpc* 2>/dev/null | grep "expire"|
- head -1 | awk '{print $15}' | cut -c1-8)
+ SK_IDENTITY_OLD=$($LCTL get_param -n *.*.*srpc_contexts 2>/dev/null |
+ head -n 1 | awk 'BEGIN{RS=", "} $1=="expire:"{print $2}')
do_facet $SINGLEMDS lfs flushctx ||
error "could not run flushctx on $SINGLEMDS"
sleep 5
lfs flushctx || error "could not run flushctx on client"
sleep 5
# verify new key is in place
- SK_IDENTITY_NEW=$(lctl get_param *.*.*srpc* 2>/dev/null | grep "expire"|
- head -1 | awk '{print $15}' | cut -c1-8)
+ SK_IDENTITY_NEW=$($LCTL get_param -n *.*.*srpc_contexts 2>/dev/null |
+ head -n 1 | awk 'BEGIN{RS=", "} $1=="expire:"{print $2}')
if [ $SK_IDENTITY_OLD == $SK_IDENTITY_NEW ]; then
error "key did not rotate correctly"
fi