diff options
author | Roman Kapl <code@rkapl.cz> | 2018-02-19 23:32:51 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-03-09 09:41:10 +0300 |
commit | 795f3deff199e944bebbf04d577033363c335c44 (patch) | |
tree | 4fcae0fbe3e7019238e3c60fafd6f550b61b9606 /net/sched | |
parent | 60b28d5ef3e3880a180bdbf69a3956fcb33d6e99 (diff) | |
download | linux-795f3deff199e944bebbf04d577033363c335c44.tar.xz |
net: sched: report if filter is too large to dump
[ Upstream commit 5ae437ad5a2ed573b1ebb04e0afa70b8869f88dd ]
So far, if the filter was too large to fit in the allocated skb, the
kernel did not return any error and stopped dumping. Modify the dumper
so that it returns -EMSGSIZE when a filter fails to dump and it is the
first filter in the skb. If we are not first, we will get a next chance
with more room.
I understand this is pretty near to being an API change, but the
original design (silent truncation) can be considered a bug.
Note: The error case can happen pretty easily if you create a filter
with 32 actions and have 4kb pages. Also recent versions of iproute try
to be clever with their buffer allocation size, which in turn leads to
Signed-off-by: Roman Kapl <code@rkapl.cz>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_api.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 934c239cf98d..c2fab4bcb8be 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -871,13 +871,18 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) if (tca[TCA_CHAIN] && nla_get_u32(tca[TCA_CHAIN]) != chain->index) continue; - if (!tcf_chain_dump(chain, skb, cb, index_start, &index)) + if (!tcf_chain_dump(chain, skb, cb, index_start, &index)) { + err = -EMSGSIZE; break; + } } cb->args[0] = index; out: + /* If we did no progress, the error (EMSGSIZE) is real */ + if (skb->len == 0 && err) + return err; return skb->len; } |