Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8da145e1 authored by Harout Hedeshian's avatar Harout Hedeshian Committed by Subash Abhinov Kasiviswanathan
Browse files

net: sched: gracefully handle qdisc which don't support change()



tc_qdisc_flow_control() incorrectly assumes that all queue disciplines
implement the change() callback in Qdisc_ops. If the flow control function
is called a queue that does not implement change(), we try to jump to a
null function pointer resulting in a panic. The flow control function
does require that the queue discipline support change() in order to
enable/disable the queue. Now we will check if the queue to do flow
control on supports the required funcionality and will WARN_ONCE and
return if the requirements are not met.

[<ffffffc000c5c028>] panic+0x28c
[<ffffffc0000889f4>] die+0x238
[<ffffffc000088a6c>] arm64_notify_die+0x4c
[<ffffffc000088d00>] bad_mode+0xa8
[<ffffffc000ab9ab8>] tc_qdisc_flow_control+0x98
[<ffffffc000c506e8>] rmnet_vnd_ioctl+0x230
[<ffffffc000aac6fc>] dev_ifsioc+0x2a0
[<ffffffc000aacde8>] dev_ioctl+0x644
[<ffffffc000a7db4c>] sock_ioctl+0x4c
[<ffffffc0001af548>] do_vfs_ioctl+0x4b4
[<ffffffc0001af684>] SyS_ioctl+0x60
[<ffffffc0000854b0>] el0_svc_naked+0x24

Change-Id: I85ca324e57814b6c0eac48d2e076e861ab32c260
Signed-off-by: default avatarHarout Hedeshian <harouth@codeaurora.org>
parent 319472d7
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -1184,10 +1184,17 @@ tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle, int enable_flow)
	q = qdisc_lookup(dev, tcm_handle);

	/* call registered change function */
	if (q) {
	if (likely(q && q->ops)) {
		if (likely(q->ops->change)) {
			qdisc_len = q->q.qlen;
		if (q->ops->change(q, &(req.attr)) != 0)
			pr_err("tc_qdisc_flow_control: qdisc change failed");
			if (q->ops->change(q, &req.attr) != 0)
				pr_err("%s(): qdisc change failed", __func__);
		} else {
			WARN_ONCE(1, "%s(): called on queue which does %s",
				  __func__, "not support change() operation");
		}
	} else {
		WARN_ONCE(1, "%s(): called on bad queue", __func__);
	}
	return qdisc_len;
}