diff options
author | Cong Wang <xiyou.wangcong@gmail.com> | 2018-09-04 17:54:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-09-07 00:49:18 -0400 |
commit | 8f5c5fcf353302374b36232d6885c1a3b579e5ca (patch) | |
tree | 9dc9fc708ad4252bb2ecec4e9c250ea15ab897ee /net/tipc | |
parent | 6da410d97ffa486eb0379236d5444e5f4527c07a (diff) |
tipc: call start and done ops directly in __tipc_nl_compat_dumpit()
__tipc_nl_compat_dumpit() uses a netlink_callback on stack,
so the only way to align it with other ->dumpit() call path
is calling tipc_dump_start() and tipc_dump_done() directly
inside it. Otherwise ->dumpit() would always get NULL from
cb->args[].
But tipc_dump_start() uses sock_net(cb->skb->sk) to retrieve
net pointer, the cb->skb here doesn't set skb->sk, the net pointer
is saved in msg->net instead, so introduce a helper function
__tipc_dump_start() to pass in msg->net.
Ying pointed out cb->args[0...3] are already used by other
callbacks on this call path, so we can't use cb->args[0] any
more, use cb->args[4] instead.
Fixes: 9a07efa9aea2 ("tipc: switch to rhashtable iterator")
Reported-and-tested-by: syzbot+e93a2c41f91b8e2c7d9b@syzkaller.appspotmail.com
Cc: Jon Maloy <jon.maloy@ericsson.com>
Cc: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/netlink_compat.c | 2 | ||||
-rw-r--r-- | net/tipc/socket.c | 17 | ||||
-rw-r--r-- | net/tipc/socket.h | 1 |
3 files changed, 14 insertions, 6 deletions
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index a2f76743c73a..82f665728382 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
@@ -185,6 +185,7 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, | |||
185 | return -ENOMEM; | 185 | return -ENOMEM; |
186 | 186 | ||
187 | buf->sk = msg->dst_sk; | 187 | buf->sk = msg->dst_sk; |
188 | __tipc_dump_start(&cb, msg->net); | ||
188 | 189 | ||
189 | do { | 190 | do { |
190 | int rem; | 191 | int rem; |
@@ -216,6 +217,7 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, | |||
216 | err = 0; | 217 | err = 0; |
217 | 218 | ||
218 | err_out: | 219 | err_out: |
220 | tipc_dump_done(&cb); | ||
219 | kfree_skb(buf); | 221 | kfree_skb(buf); |
220 | 222 | ||
221 | if (err == -EMSGSIZE) { | 223 | if (err == -EMSGSIZE) { |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index a0ff8bffc96b..3f03ddd0e35b 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -3230,7 +3230,7 @@ int tipc_nl_sk_walk(struct sk_buff *skb, struct netlink_callback *cb, | |||
3230 | struct netlink_callback *cb, | 3230 | struct netlink_callback *cb, |
3231 | struct tipc_sock *tsk)) | 3231 | struct tipc_sock *tsk)) |
3232 | { | 3232 | { |
3233 | struct rhashtable_iter *iter = (void *)cb->args[0]; | 3233 | struct rhashtable_iter *iter = (void *)cb->args[4]; |
3234 | struct tipc_sock *tsk; | 3234 | struct tipc_sock *tsk; |
3235 | int err; | 3235 | int err; |
3236 | 3236 | ||
@@ -3266,8 +3266,14 @@ EXPORT_SYMBOL(tipc_nl_sk_walk); | |||
3266 | 3266 | ||
3267 | int tipc_dump_start(struct netlink_callback *cb) | 3267 | int tipc_dump_start(struct netlink_callback *cb) |
3268 | { | 3268 | { |
3269 | struct rhashtable_iter *iter = (void *)cb->args[0]; | 3269 | return __tipc_dump_start(cb, sock_net(cb->skb->sk)); |
3270 | struct net *net = sock_net(cb->skb->sk); | 3270 | } |
3271 | EXPORT_SYMBOL(tipc_dump_start); | ||
3272 | |||
3273 | int __tipc_dump_start(struct netlink_callback *cb, struct net *net) | ||
3274 | { | ||
3275 | /* tipc_nl_name_table_dump() uses cb->args[0...3]. */ | ||
3276 | struct rhashtable_iter *iter = (void *)cb->args[4]; | ||
3271 | struct tipc_net *tn = tipc_net(net); | 3277 | struct tipc_net *tn = tipc_net(net); |
3272 | 3278 | ||
3273 | if (!iter) { | 3279 | if (!iter) { |
@@ -3275,17 +3281,16 @@ int tipc_dump_start(struct netlink_callback *cb) | |||
3275 | if (!iter) | 3281 | if (!iter) |
3276 | return -ENOMEM; | 3282 | return -ENOMEM; |
3277 | 3283 | ||
3278 | cb->args[0] = (long)iter; | 3284 | cb->args[4] = (long)iter; |
3279 | } | 3285 | } |
3280 | 3286 | ||
3281 | rhashtable_walk_enter(&tn->sk_rht, iter); | 3287 | rhashtable_walk_enter(&tn->sk_rht, iter); |
3282 | return 0; | 3288 | return 0; |
3283 | } | 3289 | } |
3284 | EXPORT_SYMBOL(tipc_dump_start); | ||
3285 | 3290 | ||
3286 | int tipc_dump_done(struct netlink_callback *cb) | 3291 | int tipc_dump_done(struct netlink_callback *cb) |
3287 | { | 3292 | { |
3288 | struct rhashtable_iter *hti = (void *)cb->args[0]; | 3293 | struct rhashtable_iter *hti = (void *)cb->args[4]; |
3289 | 3294 | ||
3290 | rhashtable_walk_exit(hti); | 3295 | rhashtable_walk_exit(hti); |
3291 | kfree(hti); | 3296 | kfree(hti); |
diff --git a/net/tipc/socket.h b/net/tipc/socket.h index d43032e26532..5e575f205afe 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h | |||
@@ -69,5 +69,6 @@ int tipc_nl_sk_walk(struct sk_buff *skb, struct netlink_callback *cb, | |||
69 | struct netlink_callback *cb, | 69 | struct netlink_callback *cb, |
70 | struct tipc_sock *tsk)); | 70 | struct tipc_sock *tsk)); |
71 | int tipc_dump_start(struct netlink_callback *cb); | 71 | int tipc_dump_start(struct netlink_callback *cb); |
72 | int __tipc_dump_start(struct netlink_callback *cb, struct net *net); | ||
72 | int tipc_dump_done(struct netlink_callback *cb); | 73 | int tipc_dump_done(struct netlink_callback *cb); |
73 | #endif | 74 | #endif |