From 675e2df632d0c8ad1bf936506e2090cdc83b2f7e Mon Sep 17 00:00:00 2001 From: Ido Kalir Date: Sun, 14 Feb 2021 10:33:35 +0200 Subject: [PATCH] rdma: Fix statistics bind/unbing argument handling The dump isn't supported for the statistics bind/unbind commands because they operate on specific QP counters. This is different from query commands that can operate on many objects at the same time. Let's check the user input and ensure that arguments are valid. Fixes: a6d0773ebecc ("rdma: Add stat manual mode support") Signed-off-by: Ido Kalir Signed-off-by: Leon Romanovsky Signed-off-by: Stephen Hemminger --- rdma/rdma.h | 1 + rdma/stat.c | 21 +++++++++++++++++++++ rdma/utils.c | 7 +++++++ 3 files changed, 29 insertions(+) diff --git a/rdma/rdma.h b/rdma/rdma.h index fc8bcf09..ab3b388f 100644 --- a/rdma/rdma.h +++ b/rdma/rdma.h @@ -84,6 +84,7 @@ struct rd_cmd { * Parser interface */ bool rd_no_arg(struct rd *rd); +bool rd_is_multiarg(struct rd *rd); void rd_arg_inc(struct rd *rd); char *rd_argv(struct rd *rd); diff --git a/rdma/stat.c b/rdma/stat.c index a2b5da1c..75d45288 100644 --- a/rdma/stat.c +++ b/rdma/stat.c @@ -502,6 +502,12 @@ static int stat_get_arg(struct rd *rd, const char *arg) return -EINVAL; rd_arg_inc(rd); + + if (rd_is_multiarg(rd)) { + pr_err("The parameter %s shouldn't include range\n", arg); + return -EINVAL; + } + value = strtol(rd_argv(rd), &endp, 10); rd_arg_inc(rd); @@ -523,6 +529,8 @@ static int stat_one_qp_bind(struct rd *rd) return ret; lqpn = stat_get_arg(rd, "lqpn"); + if (lqpn < 0) + return lqpn; rd_prepare_msg(rd, RDMA_NLDEV_CMD_STAT_SET, &seq, (NLM_F_REQUEST | NLM_F_ACK)); @@ -537,6 +545,9 @@ static int stat_one_qp_bind(struct rd *rd) if (rd_argc(rd)) { cntn = stat_get_arg(rd, "cntn"); + if (cntn < 0) + return cntn; + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, cntn); } @@ -607,13 +618,23 @@ static int stat_one_qp_unbind(struct rd *rd) unsigned int portid; uint32_t seq; + if (rd_no_arg(rd)) { + stat_help(rd); + return -EINVAL; + } + ret = rd_build_filter(rd, stat_valid_filters); if (ret) return ret; cntn = stat_get_arg(rd, "cntn"); + if (cntn < 0) + return cntn; + if (rd_argc(rd)) { lqpn = stat_get_arg(rd, "lqpn"); + if (lqpn < 0) + return lqpn; return do_stat_qp_unbind_lqpn(rd, cntn, lqpn); } diff --git a/rdma/utils.c b/rdma/utils.c index 2a201aa4..f84b102d 100644 --- a/rdma/utils.c +++ b/rdma/utils.c @@ -47,6 +47,13 @@ bool rd_no_arg(struct rd *rd) return rd_argc(rd) == 0; } +bool rd_is_multiarg(struct rd *rd) +{ + if (!rd_argc(rd)) + return false; + return strpbrk(rd_argv(rd), ",-") != NULL; +} + /* * Possible input:output * dev/port | first port | is_dump_all