diff options
author | Thomas Haller <thaller@redhat.com> | 2022-04-22 20:10:47 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-04-22 20:20:00 (GMT) |
commit | 1f61096c82c0b8f1eecef1d74f67985158a306e1 (patch) | |
tree | d28208f2d2896cd90235c48006f652577665bed8 /lib/route | |
parent | f918c3a427d3470cf3b7885537310e7a73c501bf (diff) | |
download | libnl-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.c | 15 |
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; |