aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c61
-rw-r--r--net/ipv6/netfilter/ip6_queue.c2
-rw-r--r--net/ipv6/tcp_ipv6.c2
3 files changed, 42 insertions, 23 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a225d5ee3c2..c02280a4d12 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -502,29 +502,31 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
502 rcu_read_unlock(); 502 rcu_read_unlock();
503} 503}
504 504
505static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) 505static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
506{ 506{
507 struct net *net; 507 struct net *net;
508 int old;
509
510 if (!rtnl_trylock())
511 return restart_syscall();
508 512
509 net = (struct net *)table->extra2; 513 net = (struct net *)table->extra2;
510 if (p == &net->ipv6.devconf_dflt->forwarding) 514 old = *p;
511 return 0; 515 *p = newf;
512 516
513 if (!rtnl_trylock()) { 517 if (p == &net->ipv6.devconf_dflt->forwarding) {
514 /* Restore the original values before restarting */ 518 rtnl_unlock();
515 *p = old; 519 return 0;
516 return restart_syscall();
517 } 520 }
518 521
519 if (p == &net->ipv6.devconf_all->forwarding) { 522 if (p == &net->ipv6.devconf_all->forwarding) {
520 __s32 newf = net->ipv6.devconf_all->forwarding;
521 net->ipv6.devconf_dflt->forwarding = newf; 523 net->ipv6.devconf_dflt->forwarding = newf;
522 addrconf_forward_change(net, newf); 524 addrconf_forward_change(net, newf);
523 } else if ((!*p) ^ (!old)) 525 } else if ((!newf) ^ (!old))
524 dev_forward_change((struct inet6_dev *)table->extra1); 526 dev_forward_change((struct inet6_dev *)table->extra1);
525 rtnl_unlock(); 527 rtnl_unlock();
526 528
527 if (*p) 529 if (newf)
528 rt6_purge_dflt_routers(net); 530 rt6_purge_dflt_routers(net);
529 return 1; 531 return 1;
530} 532}
@@ -4260,9 +4262,17 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
4260 int *valp = ctl->data; 4262 int *valp = ctl->data;
4261 int val = *valp; 4263 int val = *valp;
4262 loff_t pos = *ppos; 4264 loff_t pos = *ppos;
4265 ctl_table lctl;
4263 int ret; 4266 int ret;
4264 4267
4265 ret = proc_dointvec(ctl, write, buffer, lenp, ppos); 4268 /*
4269 * ctl->data points to idev->cnf.forwarding, we should
4270 * not modify it until we get the rtnl lock.
4271 */
4272 lctl = *ctl;
4273 lctl.data = &val;
4274
4275 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
4266 4276
4267 if (write) 4277 if (write)
4268 ret = addrconf_fixup_forwarding(ctl, valp, val); 4278 ret = addrconf_fixup_forwarding(ctl, valp, val);
@@ -4300,26 +4310,27 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
4300 rcu_read_unlock(); 4310 rcu_read_unlock();
4301} 4311}
4302 4312
4303static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) 4313static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
4304{ 4314{
4305 struct net *net; 4315 struct net *net;
4316 int old;
4317
4318 if (!rtnl_trylock())
4319 return restart_syscall();
4306 4320
4307 net = (struct net *)table->extra2; 4321 net = (struct net *)table->extra2;
4322 old = *p;
4323 *p = newf;
4308 4324
4309 if (p == &net->ipv6.devconf_dflt->disable_ipv6) 4325 if (p == &net->ipv6.devconf_dflt->disable_ipv6) {
4326 rtnl_unlock();
4310 return 0; 4327 return 0;
4311
4312 if (!rtnl_trylock()) {
4313 /* Restore the original values before restarting */
4314 *p = old;
4315 return restart_syscall();
4316 } 4328 }
4317 4329
4318 if (p == &net->ipv6.devconf_all->disable_ipv6) { 4330 if (p == &net->ipv6.devconf_all->disable_ipv6) {
4319 __s32 newf = net->ipv6.devconf_all->disable_ipv6;
4320 net->ipv6.devconf_dflt->disable_ipv6 = newf; 4331 net->ipv6.devconf_dflt->disable_ipv6 = newf;
4321 addrconf_disable_change(net, newf); 4332 addrconf_disable_change(net, newf);
4322 } else if ((!*p) ^ (!old)) 4333 } else if ((!newf) ^ (!old))
4323 dev_disable_change((struct inet6_dev *)table->extra1); 4334 dev_disable_change((struct inet6_dev *)table->extra1);
4324 4335
4325 rtnl_unlock(); 4336 rtnl_unlock();
@@ -4333,9 +4344,17 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write,
4333 int *valp = ctl->data; 4344 int *valp = ctl->data;
4334 int val = *valp; 4345 int val = *valp;
4335 loff_t pos = *ppos; 4346 loff_t pos = *ppos;
4347 ctl_table lctl;
4336 int ret; 4348 int ret;
4337 4349
4338 ret = proc_dointvec(ctl, write, buffer, lenp, ppos); 4350 /*
4351 * ctl->data points to idev->cnf.disable_ipv6, we should
4352 * not modify it until we get the rtnl lock.
4353 */
4354 lctl = *ctl;
4355 lctl.data = &val;
4356
4357 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
4339 4358
4340 if (write) 4359 if (write)
4341 ret = addrconf_disable_ipv6(ctl, valp, val); 4360 ret = addrconf_disable_ipv6(ctl, valp, val);
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index fb80a23c664..a34c9e4c792 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -432,7 +432,7 @@ __ipq_rcv_skb(struct sk_buff *skb)
432 if (type <= IPQM_BASE) 432 if (type <= IPQM_BASE)
433 return; 433 return;
434 434
435 if (security_netlink_recv(skb, CAP_NET_ADMIN)) 435 if (!capable(CAP_NET_ADMIN))
436 RCV_SKB_FAIL(-EPERM); 436 RCV_SKB_FAIL(-EPERM);
437 437
438 spin_lock_bh(&queue_lock); 438 spin_lock_bh(&queue_lock);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 906c7ca4354..3edd05ae438 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1083,7 +1083,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
1083 1083
1084#ifdef CONFIG_TCP_MD5SIG 1084#ifdef CONFIG_TCP_MD5SIG
1085 if (sk) 1085 if (sk)
1086 key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); 1086 key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr);
1087#endif 1087#endif
1088 1088
1089 if (th->ack) 1089 if (th->ack)