Skip to content

Commit 94a6d9f

Browse files
TaeheeYooJakub Kicinski
authored and
Jakub Kicinski
committed
gtp: fix wrong condition in gtp_genl_dump_pdp()
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: 459aa66 ("gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)") Signed-off-by: Taehee Yoo <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 6b01b1d commit 94a6d9f

File tree

1 file changed

+19
-17
lines changed

1 file changed

+19
-17
lines changed

drivers/net/gtp.c

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ struct pdp_ctx {
3838
struct hlist_node hlist_addr;
3939

4040
union {
41-
u64 tid;
4241
struct {
4342
u64 tid;
4443
u16 flow;
@@ -1244,43 +1243,46 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
12441243
struct netlink_callback *cb)
12451244
{
12461245
struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp;
1246+
int i, j, bucket = cb->args[0], skip = cb->args[1];
12471247
struct net *net = sock_net(skb->sk);
1248-
struct gtp_net *gn = net_generic(net, gtp_net_id);
1249-
unsigned long tid = cb->args[1];
1250-
int i, k = cb->args[0], ret;
12511248
struct pdp_ctx *pctx;
1249+
struct gtp_net *gn;
1250+
1251+
gn = net_generic(net, gtp_net_id);
12521252

12531253
if (cb->args[4])
12541254
return 0;
12551255

1256+
rcu_read_lock();
12561257
list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) {
12571258
if (last_gtp && last_gtp != gtp)
12581259
continue;
12591260
else
12601261
last_gtp = NULL;
12611262

1262-
for (i = k; i < gtp->hash_size; i++) {
1263-
hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid) {
1264-
if (tid && tid != pctx->u.tid)
1265-
continue;
1266-
else
1267-
tid = 0;
1268-
1269-
ret = gtp_genl_fill_info(skb,
1270-
NETLINK_CB(cb->skb).portid,
1271-
cb->nlh->nlmsg_seq,
1272-
cb->nlh->nlmsg_type, pctx);
1273-
if (ret < 0) {
1263+
for (i = bucket; i < gtp->hash_size; i++) {
1264+
j = 0;
1265+
hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i],
1266+
hlist_tid) {
1267+
if (j >= skip &&
1268+
gtp_genl_fill_info(skb,
1269+
NETLINK_CB(cb->skb).portid,
1270+
cb->nlh->nlmsg_seq,
1271+
cb->nlh->nlmsg_type, pctx)) {
12741272
cb->args[0] = i;
1275-
cb->args[1] = pctx->u.tid;
1273+
cb->args[1] = j;
12761274
cb->args[2] = (unsigned long)gtp;
12771275
goto out;
12781276
}
1277+
j++;
12791278
}
1279+
skip = 0;
12801280
}
1281+
bucket = 0;
12811282
}
12821283
cb->args[4] = 1;
12831284
out:
1285+
rcu_read_unlock();
12841286
return skb->len;
12851287
}
12861288

0 commit comments

Comments
 (0)