From 338381574b643da064e90e44d75be85d1be3a93c Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Fri, 10 Jan 2020 14:18:53 -0700 Subject: [PATCH] LU-11407 tgt: cleanup job_stats output printing Escape non-printable and other special characters in the JobID name, which may be passed from the client environment, to avoid breaking YAML format parsing. We can't use the kernel "%*pE" escape format, because that doesn't have any option to escape printable characters like quotes or regular spaces. Signed-off-by: Andreas Dilger Change-Id: If6a0bc4276fae03305f94e8c85d8f109913ebbe5 Reviewed-on: https://review.whamcloud.com/37764 Tested-by: jenkins Reviewed-by: Ben Evans Tested-by: Maloo Reviewed-by: Arshad Hussain Reviewed-by: Oleg Drokin --- lustre/obdclass/lprocfs_jobstats.c | 32 ++++++++++++++++++++++---------- lustre/tests/sanity.sh | 32 +++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/lustre/obdclass/lprocfs_jobstats.c b/lustre/obdclass/lprocfs_jobstats.c index ca5ae3b..5eca82e 100644 --- a/lustre/obdclass/lprocfs_jobstats.c +++ b/lustre/obdclass/lprocfs_jobstats.c @@ -439,24 +439,35 @@ static int lprocfs_jobstats_seq_show(struct seq_file *p, void *v) struct lprocfs_stats *s; struct lprocfs_counter ret; struct lprocfs_counter_header *cntr_header; - int i; + char escaped[LUSTRE_JOBID_SIZE * 4] = ""; + char *quote = "", *c, *end; + int i, joblen = 0; if (v == SEQ_START_TOKEN) { seq_printf(p, "job_stats:\n"); return 0; } - /* Replace the non-printable character in jobid with '?', so - * that the output of jobid will be confined in single line. */ - seq_printf(p, "- %-16s ", "job_id:"); - for (i = 0; i < strlen(job->js_jobid); i++) { - if (isprint(job->js_jobid[i]) != 0) - seq_putc(p, job->js_jobid[i]); - else - seq_putc(p, '?'); + /* Quote and escape jobid characters to escape hex codes "\xHH" if + * it contains any non-standard characters (space, newline, etc), + * so it will be confined to single line and not break parsing. + */ + for (c = job->js_jobid, end = job->js_jobid + sizeof(job->js_jobid); + c < end && *c != '\0'; + c++, joblen++) { + if (!isalnum(*c) && + *c != '.' && *c != '@' && *c != '-' && *c != '_') { + quote = "\""; + snprintf(escaped + joblen, sizeof(escaped), "\\x%02X", + (unsigned char)*c); + joblen += 3; + } else { + escaped[joblen] = *c; + } } - seq_putc(p, '\n'); + seq_printf(p, "- %-16s %s%*s%s\n", + "job_id:", quote, joblen, escaped, quote); lprocfs_stats_header(p, job->js_time_latest, job->js_time_init, 16, ":", true); @@ -486,6 +497,7 @@ static int lprocfs_jobstats_seq_show(struct seq_file *p, void *v) seq_printf(p, " }\n"); } + return 0; } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index a63333d..e098c80 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -18807,18 +18807,32 @@ test_205b() { (( $MDS1_VERSION >= $(version_code 2.13.54.91) )) || skip "Need MDS version at least 2.13.54.91" - job_stats="mdt.*.job_stats" - $LCTL set_param $job_stats=clear + local job_stats="mdt.*.job_stats" + local old_jobid=$(do_facet mds1 $LCTL get_param jobid_var) + + do_facet mds1 $LCTL set_param $job_stats=clear + # Setting jobid_var to USER might not be supported + [[ -n "$old_jobid" ]] && stack_trap "$LCTL set_param $old_jobid" $LCTL set_param jobid_var=USER || true - $LCTL set_param jobid_name="%e.%u" + stack_trap "$LCTL set_param $($LCTL get_param jobid_name)" + $LCTL set_param jobid_name="%j.%e.%u" + env -i USERTESTJOBSTATS=foolish touch $DIR/$tfile.1 - do_facet $SINGLEMDS $LCTL get_param $job_stats | - grep "job_id:.*foolish" && - error "Unexpected jobid found" - do_facet $SINGLEMDS $LCTL get_param $job_stats | - grep "open:.*min.*max.*sum" || - error "wrong job_stats format found" + do_facet mds1 $LCTL get_param $job_stats | grep "job_id:.*foolish" && + { do_facet mds1 $LCTL get_param $job_stats; + error "Unexpected jobid found"; } + do_facet mds1 $LCTL get_param $job_stats | grep "open:.*min.*max.*sum"|| + { do_facet mds1 $LCTL get_param $job_stats; + error "wrong job_stats format found"; } + + (( $MDS1_VERSION <= $(version_code 2.15.0) )) && + echo "MDS does not yet escape jobid" && return 0 + $LCTL set_param jobid_var=TEST205b + env -i TEST205b="has sp" touch $DIR/$tfile.2 + do_facet mds1 $LCTL get_param $job_stats | grep "has.*x20sp" || + { do_facet mds1 $LCTL get_param $job_stats; + error "jobid not escaped"; } } run_test 205b "Verify job stats jobid and output format" -- 1.8.3.1