summaryrefslogtreecommitdiffstats
path: root/lib/route
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-04-22 20:10:47 (GMT)
committerThomas Haller <thaller@redhat.com>2022-04-22 20:20:00 (GMT)
commit1f61096c82c0b8f1eecef1d74f67985158a306e1 (patch)
treed28208f2d2896cd90235c48006f652577665bed8 /lib/route
parentf918c3a427d3470cf3b7885537310e7a73c501bf (diff)
downloadlibnl-1f61096c82c0b8f1eecef1d74f67985158a306e1.zip
libnl-1f61096c82c0b8f1eecef1d74f67985158a306e1.tar.gz
libnl-1f61096c82c0b8f1eecef1d74f67985158a306e1.tar.bz2
route/qdisc/mqprio: fix bufferoverflow and argument checking in rtnl_qdisc_mqprio_set_*()
rtnl_qdisc_mqprio_set_priomap() would access the input array prio after len. Also these setters did the wrong argument checking (arguably, the caller is not supposed to provide an invalid argument, so that part is less severe). Coverity: Error: OVERRUN (CWE-119): libnl-3.6.0/lib/route/qdisc/mqprio.c:363: cond_at_most: Checking "len / 2UL > 16UL" implies that "len" may be up to 33 on the false branch. libnl-3.6.0/lib/route/qdisc/mqprio.c:366: overrun-buffer-arg: Overrunning array "mqprio->qm_count" of 32 bytes by passing it to a function which accesses it at byte offset 65 using argument "len * 2UL" (which evaluates to 66). [Note: The source code implementation of the function has been overridden by a builtin model.] # 364| return -NLE_RANGE; # 365|··· # 366|-> memcpy(mqprio->qm_count, count, len * sizeof(uint16_t)); # 367| memcpy(mqprio->qm_offset, offset, len * sizeof(uint16_t)); # 368| mqprio->qm_mask |= SCH_MQPRIO_ATTR_QUEUE; Error: OVERRUN (CWE-119): libnl-3.6.0/lib/route/qdisc/mqprio.c:363: cond_at_most: Checking "len / 2UL > 16UL" implies that "len" may be up to 33 on the false branch. libnl-3.6.0/lib/route/qdisc/mqprio.c:367: overrun-buffer-arg: Overrunning array "mqprio->qm_offset" of 32 bytes by passing it to a function which accesses it at byte offset 65 using argument "len * 2UL" (which evaluates to 66). [Note: The source code implementation of the function has been overridden by a builtin model.] # 365|··· # 366| memcpy(mqprio->qm_count, count, len * sizeof(uint16_t)); # 367|-> memcpy(mqprio->qm_offset, offset, len * sizeof(uint16_t)); # 368| mqprio->qm_mask |= SCH_MQPRIO_ATTR_QUEUE; # 369|··· Error: OVERRUN (CWE-119): libnl-3.6.0/lib/route/qdisc/mqprio.c:496: cond_at_most: Checking "len / 8UL > 16UL" implies that "len" may be up to 135 on the false branch. libnl-3.6.0/lib/route/qdisc/mqprio.c:499: overrun-buffer-arg: Overrunning array "mqprio->qm_min_rate" of 128 bytes by passing it to a function which accesses it at byte offset 1079 using argument "len * 8UL" (which evaluates to 1080). [Note: The source code implementation of the function has been overridden by a builtin model.] # 497| return -NLE_RANGE; # 498|··· # 499|-> memcpy(mqprio->qm_min_rate, min, len * sizeof(uint64_t)); # 500| mqprio->qm_mask |= SCH_MQPRIO_ATTR_MIN_RATE; # 501|··· Error: OVERRUN (CWE-119): libnl-3.6.0/lib/route/qdisc/mqprio.c:545: cond_at_most: Checking "len / 8UL > 16UL" implies that "len" may be up to 135 on the false branch. libnl-3.6.0/lib/route/qdisc/mqprio.c:548: overrun-buffer-arg: Overrunning array "mqprio->qm_max_rate" of 128 bytes by passing it to a function which accesses it at byte offset 1079 using argument "len * 8UL" (which evaluates to 1080). [Note: The source code implementation of the function has been overridden by a builtin model.] # 546| return -NLE_RANGE; # 547|··· # 548|-> memcpy(mqprio->qm_max_rate, max, len * sizeof(uint64_t)); # 549| mqprio->qm_mask |= SCH_MQPRIO_ATTR_MAX_RATE; # 550|··· Fixes: 25cf1d39eded ('route:qdisc: add MQPRIO Qdisc'
Diffstat (limited to 'lib/route')
-rw-r--r--lib/route/qdisc/mqprio.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/lib/route/qdisc/mqprio.c b/lib/route/qdisc/mqprio.c
index b07da78..c165404 100644
--- a/lib/route/qdisc/mqprio.c
+++ b/lib/route/qdisc/mqprio.c
@@ -265,14 +265,15 @@ int rtnl_qdisc_mqprio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[],
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC))
return -NLE_MISSING_ATTR;
- if ((len / sizeof(uint8_t)) > (TC_QOPT_BITMASK+1))
+ if (len > TC_QOPT_BITMASK + 1)
return -NLE_RANGE;
- for (i = 0; i <= TC_QOPT_BITMASK; i++) {
+ for (i = 0; i < len; i++) {
if (priomap[i] > mqprio->qm_num_tc)
return -NLE_RANGE;
}
+ memset(mqprio->qm_prio_map, 0, sizeof(mqprio->qm_prio_map));
memcpy(mqprio->qm_prio_map, priomap, len * sizeof(uint8_t));
mqprio->qm_mask |= SCH_MQPRIO_ATTR_PRIOMAP;
@@ -360,9 +361,11 @@ int rtnl_qdisc_mqprio_set_queue(struct rtnl_qdisc *qdisc, uint16_t count[],
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC))
return -NLE_MISSING_ATTR;
- if ((len / sizeof(uint16_t)) > TC_QOPT_MAX_QUEUE)
+ if (len < 0 || len > TC_QOPT_MAX_QUEUE)
return -NLE_RANGE;
+ memset(mqprio->qm_count, 0, sizeof(mqprio->qm_count));
+ memset(mqprio->qm_offset, 0, sizeof(mqprio->qm_offset));
memcpy(mqprio->qm_count, count, len * sizeof(uint16_t));
memcpy(mqprio->qm_offset, offset, len * sizeof(uint16_t));
mqprio->qm_mask |= SCH_MQPRIO_ATTR_QUEUE;
@@ -493,9 +496,10 @@ int rtnl_qdisc_mqprio_set_min_rate(struct rtnl_qdisc *qdisc, uint64_t min[], int
if (mqprio->qm_shaper != TC_MQPRIO_SHAPER_BW_RATE)
return -NLE_INVAL;
- if ((len / sizeof(uint64_t)) > TC_QOPT_MAX_QUEUE)
+ if (len < 0 || len > TC_QOPT_MAX_QUEUE)
return -NLE_RANGE;
+ memset(mqprio->qm_min_rate, 0, sizeof(mqprio->qm_min_rate));
memcpy(mqprio->qm_min_rate, min, len * sizeof(uint64_t));
mqprio->qm_mask |= SCH_MQPRIO_ATTR_MIN_RATE;
@@ -542,9 +546,10 @@ int rtnl_qdisc_mqprio_set_max_rate(struct rtnl_qdisc *qdisc, uint64_t max[], int
if (mqprio->qm_shaper != TC_MQPRIO_SHAPER_BW_RATE)
return -NLE_INVAL;
- if ((len / sizeof(uint64_t)) > TC_QOPT_MAX_QUEUE)
+ if (len < 0 || len > TC_QOPT_MAX_QUEUE)
return -NLE_RANGE;
+ memset(mqprio->qm_max_rate, 0, sizeof(mqprio->qm_max_rate));
memcpy(mqprio->qm_max_rate, max, len * sizeof(uint64_t));
mqprio->qm_mask |= SCH_MQPRIO_ATTR_MAX_RATE;