]>
Commit | Line | Data |
---|---|---|
54545ec3 GKH |
1 | From 8f5c5fcf353302374b36232d6885c1a3b579e5ca Mon Sep 17 00:00:00 2001 |
2 | From: Cong Wang <xiyou.wangcong@gmail.com> | |
3 | Date: Tue, 4 Sep 2018 14:54:55 -0700 | |
4 | Subject: tipc: call start and done ops directly in __tipc_nl_compat_dumpit() | |
5 | ||
6 | From: Cong Wang <xiyou.wangcong@gmail.com> | |
7 | ||
8 | commit 8f5c5fcf353302374b36232d6885c1a3b579e5ca upstream. | |
9 | ||
10 | __tipc_nl_compat_dumpit() uses a netlink_callback on stack, | |
11 | so the only way to align it with other ->dumpit() call path | |
12 | is calling tipc_dump_start() and tipc_dump_done() directly | |
13 | inside it. Otherwise ->dumpit() would always get NULL from | |
14 | cb->args[]. | |
15 | ||
16 | But tipc_dump_start() uses sock_net(cb->skb->sk) to retrieve | |
17 | net pointer, the cb->skb here doesn't set skb->sk, the net pointer | |
18 | is saved in msg->net instead, so introduce a helper function | |
19 | __tipc_dump_start() to pass in msg->net. | |
20 | ||
21 | Ying pointed out cb->args[0...3] are already used by other | |
22 | callbacks on this call path, so we can't use cb->args[0] any | |
23 | more, use cb->args[4] instead. | |
24 | ||
25 | Fixes: 9a07efa9aea2 ("tipc: switch to rhashtable iterator") | |
26 | Reported-and-tested-by: syzbot+e93a2c41f91b8e2c7d9b@syzkaller.appspotmail.com | |
27 | Cc: Jon Maloy <jon.maloy@ericsson.com> | |
28 | Cc: Ying Xue <ying.xue@windriver.com> | |
29 | Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> | |
30 | Acked-by: Ying Xue <ying.xue@windriver.com> | |
31 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
32 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
33 | ||
34 | --- | |
35 | net/tipc/netlink_compat.c | 2 ++ | |
36 | net/tipc/socket.c | 17 +++++++++++------ | |
37 | net/tipc/socket.h | 1 + | |
38 | 3 files changed, 14 insertions(+), 6 deletions(-) | |
39 | ||
40 | --- a/net/tipc/netlink_compat.c | |
41 | +++ b/net/tipc/netlink_compat.c | |
42 | @@ -185,6 +185,7 @@ static int __tipc_nl_compat_dumpit(struc | |
43 | return -ENOMEM; | |
44 | ||
45 | buf->sk = msg->dst_sk; | |
46 | + __tipc_dump_start(&cb, msg->net); | |
47 | ||
48 | do { | |
49 | int rem; | |
50 | @@ -216,6 +217,7 @@ static int __tipc_nl_compat_dumpit(struc | |
51 | err = 0; | |
52 | ||
53 | err_out: | |
54 | + tipc_dump_done(&cb); | |
55 | kfree_skb(buf); | |
56 | ||
57 | if (err == -EMSGSIZE) { | |
58 | --- a/net/tipc/socket.c | |
59 | +++ b/net/tipc/socket.c | |
60 | @@ -3233,7 +3233,7 @@ int tipc_nl_sk_walk(struct sk_buff *skb, | |
61 | struct netlink_callback *cb, | |
62 | struct tipc_sock *tsk)) | |
63 | { | |
64 | - struct rhashtable_iter *iter = (void *)cb->args[0]; | |
65 | + struct rhashtable_iter *iter = (void *)cb->args[4]; | |
66 | struct tipc_sock *tsk; | |
67 | int err; | |
68 | ||
69 | @@ -3269,8 +3269,14 @@ EXPORT_SYMBOL(tipc_nl_sk_walk); | |
70 | ||
71 | int tipc_dump_start(struct netlink_callback *cb) | |
72 | { | |
73 | - struct rhashtable_iter *iter = (void *)cb->args[0]; | |
74 | - struct net *net = sock_net(cb->skb->sk); | |
75 | + return __tipc_dump_start(cb, sock_net(cb->skb->sk)); | |
76 | +} | |
77 | +EXPORT_SYMBOL(tipc_dump_start); | |
78 | + | |
79 | +int __tipc_dump_start(struct netlink_callback *cb, struct net *net) | |
80 | +{ | |
81 | + /* tipc_nl_name_table_dump() uses cb->args[0...3]. */ | |
82 | + struct rhashtable_iter *iter = (void *)cb->args[4]; | |
83 | struct tipc_net *tn = tipc_net(net); | |
84 | ||
85 | if (!iter) { | |
86 | @@ -3278,17 +3284,16 @@ int tipc_dump_start(struct netlink_callb | |
87 | if (!iter) | |
88 | return -ENOMEM; | |
89 | ||
90 | - cb->args[0] = (long)iter; | |
91 | + cb->args[4] = (long)iter; | |
92 | } | |
93 | ||
94 | rhashtable_walk_enter(&tn->sk_rht, iter); | |
95 | return 0; | |
96 | } | |
97 | -EXPORT_SYMBOL(tipc_dump_start); | |
98 | ||
99 | int tipc_dump_done(struct netlink_callback *cb) | |
100 | { | |
101 | - struct rhashtable_iter *hti = (void *)cb->args[0]; | |
102 | + struct rhashtable_iter *hti = (void *)cb->args[4]; | |
103 | ||
104 | rhashtable_walk_exit(hti); | |
105 | kfree(hti); | |
106 | --- a/net/tipc/socket.h | |
107 | +++ b/net/tipc/socket.h | |
108 | @@ -69,5 +69,6 @@ int tipc_nl_sk_walk(struct sk_buff *skb, | |
109 | struct netlink_callback *cb, | |
110 | struct tipc_sock *tsk)); | |
111 | int tipc_dump_start(struct netlink_callback *cb); | |
112 | +int __tipc_dump_start(struct netlink_callback *cb, struct net *net); | |
113 | int tipc_dump_done(struct netlink_callback *cb); | |
114 | #endif |