This is a note to let you know that I've just added the patch titled gtp: fix wrong condition in gtp_genl_dump_pdp() to the 4.19-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: gtp-fix-wrong-condition-in-gtp_genl_dump_pdp.patch and it can be found in the queue-4.19 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Wed 01 Jan 2020 10:36:29 PM CET From: Taehee Yoo <ap420073@xxxxxxxxx> Date: Wed, 11 Dec 2019 08:23:17 +0000 Subject: gtp: fix wrong condition in gtp_genl_dump_pdp() From: Taehee Yoo <ap420073@xxxxxxxxx> [ Upstream commit 94a6d9fb88df43f92d943c32b84ce398d50bf49f ] gtp_genl_dump_pdp() is ->dumpit() callback of GTP module and it is used to dump pdp contexts. it would be re-executed because of dump packet size. If dump packet size is too big, it saves current dump pointer (gtp interface pointer, bucket, TID value) then it restarts dump from last pointer. Current GTP code allows adding zero TID pdp context but dump code ignores zero TID value. So, last dump pointer will not be found. In addition, this patch adds missing rcu_read_lock() in gtp_genl_dump_pdp(). Fixes: 459aa660eb1d ("gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)") Signed-off-by: Taehee Yoo <ap420073@xxxxxxxxx> Signed-off-by: Jakub Kicinski <jakub.kicinski@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/net/gtp.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -42,7 +42,6 @@ struct pdp_ctx { struct hlist_node hlist_addr; union { - u64 tid; struct { u64 tid; u16 flow; @@ -1249,43 +1248,46 @@ static int gtp_genl_dump_pdp(struct sk_b struct netlink_callback *cb) { struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp; + int i, j, bucket = cb->args[0], skip = cb->args[1]; struct net *net = sock_net(skb->sk); - struct gtp_net *gn = net_generic(net, gtp_net_id); - unsigned long tid = cb->args[1]; - int i, k = cb->args[0], ret; struct pdp_ctx *pctx; + struct gtp_net *gn; + + gn = net_generic(net, gtp_net_id); if (cb->args[4]) return 0; + rcu_read_lock(); list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) { if (last_gtp && last_gtp != gtp) continue; else last_gtp = NULL; - for (i = k; i < gtp->hash_size; i++) { - hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid) { - if (tid && tid != pctx->u.tid) - continue; - else - tid = 0; - - ret = gtp_genl_fill_info(skb, - NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, - cb->nlh->nlmsg_type, pctx); - if (ret < 0) { + for (i = bucket; i < gtp->hash_size; i++) { + j = 0; + hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], + hlist_tid) { + if (j >= skip && + gtp_genl_fill_info(skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, + cb->nlh->nlmsg_type, pctx)) { cb->args[0] = i; - cb->args[1] = pctx->u.tid; + cb->args[1] = j; cb->args[2] = (unsigned long)gtp; goto out; } + j++; } + skip = 0; } + bucket = 0; } cb->args[4] = 1; out: + rcu_read_unlock(); return skb->len; } Patches currently in stable-queue which might be from ap420073@xxxxxxxxx are queue-4.19/gtp-avoid-zero-size-hashtable.patch queue-4.19/gtp-fix-wrong-condition-in-gtp_genl_dump_pdp.patch queue-4.19/gtp-fix-an-use-after-free-in-ipv4_pdp_find.patch queue-4.19/gtp-do-not-allow-adding-duplicate-tid-and-ms_addr-pdp-context.patch