diff options
Diffstat (limited to 'net')
31 files changed, 311 insertions, 157 deletions
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 95897183226e..e70301eb7a4a 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -64,7 +64,6 @@ static struct genl_family net_drop_monitor_family = { | |||
64 | .hdrsize = 0, | 64 | .hdrsize = 0, |
65 | .name = "NET_DM", | 65 | .name = "NET_DM", |
66 | .version = 2, | 66 | .version = 2, |
67 | .maxattr = NET_DM_CMD_MAX, | ||
68 | }; | 67 | }; |
69 | 68 | ||
70 | static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data); | 69 | static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data); |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index bf6f404c04aa..a666740051dc 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -1169,6 +1169,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
1169 | neigh->parms->reachable_time : | 1169 | neigh->parms->reachable_time : |
1170 | 0))); | 1170 | 0))); |
1171 | neigh->nud_state = new; | 1171 | neigh->nud_state = new; |
1172 | notify = 1; | ||
1172 | } | 1173 | } |
1173 | 1174 | ||
1174 | if (lladdr != neigh->ha) { | 1175 | if (lladdr != neigh->ha) { |
diff --git a/net/core/sock.c b/net/core/sock.c index ab20ed9b0f31..5393b4b719d7 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -882,7 +882,7 @@ set_rcvbuf: | |||
882 | 882 | ||
883 | case SO_PEEK_OFF: | 883 | case SO_PEEK_OFF: |
884 | if (sock->ops->set_peek_off) | 884 | if (sock->ops->set_peek_off) |
885 | sock->ops->set_peek_off(sk, val); | 885 | ret = sock->ops->set_peek_off(sk, val); |
886 | else | 886 | else |
887 | ret = -EOPNOTSUPP; | 887 | ret = -EOPNOTSUPP; |
888 | break; | 888 | break; |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 4ac71ff7c2e4..2b90a786e475 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -851,7 +851,6 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
851 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 851 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
852 | if (flowlabel == NULL) | 852 | if (flowlabel == NULL) |
853 | return -EINVAL; | 853 | return -EINVAL; |
854 | usin->sin6_addr = flowlabel->dst; | ||
855 | fl6_sock_release(flowlabel); | 854 | fl6_sock_release(flowlabel); |
856 | } | 855 | } |
857 | } | 856 | } |
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 523be38e37de..f2e15738534d 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -104,7 +104,10 @@ errout: | |||
104 | static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) | 104 | static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) |
105 | { | 105 | { |
106 | struct fib_result *result = (struct fib_result *) arg->result; | 106 | struct fib_result *result = (struct fib_result *) arg->result; |
107 | struct net_device *dev = result->fi->fib_dev; | 107 | struct net_device *dev = NULL; |
108 | |||
109 | if (result->fi) | ||
110 | dev = result->fi->fib_dev; | ||
108 | 111 | ||
109 | /* do not accept result if the route does | 112 | /* do not accept result if the route does |
110 | * not meet the required prefix length | 113 | * not meet the required prefix length |
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c index f13bd91d9a56..a313c3fbeb46 100644 --- a/net/ipv4/netfilter/ipt_SYNPROXY.c +++ b/net/ipv4/netfilter/ipt_SYNPROXY.c | |||
@@ -423,6 +423,7 @@ static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par) | |||
423 | static struct xt_target synproxy_tg4_reg __read_mostly = { | 423 | static struct xt_target synproxy_tg4_reg __read_mostly = { |
424 | .name = "SYNPROXY", | 424 | .name = "SYNPROXY", |
425 | .family = NFPROTO_IPV4, | 425 | .family = NFPROTO_IPV4, |
426 | .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD), | ||
426 | .target = synproxy_tg4, | 427 | .target = synproxy_tg4, |
427 | .targetsize = sizeof(struct xt_synproxy_info), | 428 | .targetsize = sizeof(struct xt_synproxy_info), |
428 | .checkentry = synproxy_tg4_check, | 429 | .checkentry = synproxy_tg4_check, |
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c index fff5ba1a33b7..4a5e94ac314a 100644 --- a/net/ipv4/netfilter/nft_reject_ipv4.c +++ b/net/ipv4/netfilter/nft_reject_ipv4.c | |||
@@ -72,7 +72,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
72 | { | 72 | { |
73 | const struct nft_reject *priv = nft_expr_priv(expr); | 73 | const struct nft_reject *priv = nft_expr_priv(expr); |
74 | 74 | ||
75 | if (nla_put_be32(skb, NFTA_REJECT_TYPE, priv->type)) | 75 | if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type))) |
76 | goto nla_put_failure; | 76 | goto nla_put_failure; |
77 | 77 | ||
78 | switch (priv->type) { | 78 | switch (priv->type) { |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 44f6a20fa29d..f140048334ce 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -560,15 +560,11 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb, | |||
560 | __be16 sport, __be16 dport, | 560 | __be16 sport, __be16 dport, |
561 | struct udp_table *udptable) | 561 | struct udp_table *udptable) |
562 | { | 562 | { |
563 | struct sock *sk; | ||
564 | const struct iphdr *iph = ip_hdr(skb); | 563 | const struct iphdr *iph = ip_hdr(skb); |
565 | 564 | ||
566 | if (unlikely(sk = skb_steal_sock(skb))) | 565 | return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport, |
567 | return sk; | 566 | iph->daddr, dport, inet_iif(skb), |
568 | else | 567 | udptable); |
569 | return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport, | ||
570 | iph->daddr, dport, inet_iif(skb), | ||
571 | udptable); | ||
572 | } | 568 | } |
573 | 569 | ||
574 | struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, | 570 | struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, |
@@ -1603,12 +1599,16 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
1603 | kfree_skb(skb1); | 1599 | kfree_skb(skb1); |
1604 | } | 1600 | } |
1605 | 1601 | ||
1606 | static void udp_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | 1602 | /* For TCP sockets, sk_rx_dst is protected by socket lock |
1603 | * For UDP, we use xchg() to guard against concurrent changes. | ||
1604 | */ | ||
1605 | static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) | ||
1607 | { | 1606 | { |
1608 | struct dst_entry *dst = skb_dst(skb); | 1607 | struct dst_entry *old; |
1609 | 1608 | ||
1610 | dst_hold(dst); | 1609 | dst_hold(dst); |
1611 | sk->sk_rx_dst = dst; | 1610 | old = xchg(&sk->sk_rx_dst, dst); |
1611 | dst_release(old); | ||
1612 | } | 1612 | } |
1613 | 1613 | ||
1614 | /* | 1614 | /* |
@@ -1739,15 +1739,16 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
1739 | if (udp4_csum_init(skb, uh, proto)) | 1739 | if (udp4_csum_init(skb, uh, proto)) |
1740 | goto csum_error; | 1740 | goto csum_error; |
1741 | 1741 | ||
1742 | if (skb->sk) { | 1742 | sk = skb_steal_sock(skb); |
1743 | if (sk) { | ||
1744 | struct dst_entry *dst = skb_dst(skb); | ||
1743 | int ret; | 1745 | int ret; |
1744 | sk = skb->sk; | ||
1745 | 1746 | ||
1746 | if (unlikely(sk->sk_rx_dst == NULL)) | 1747 | if (unlikely(sk->sk_rx_dst != dst)) |
1747 | udp_sk_rx_dst_set(sk, skb); | 1748 | udp_sk_rx_dst_set(sk, dst); |
1748 | 1749 | ||
1749 | ret = udp_queue_rcv_skb(sk, skb); | 1750 | ret = udp_queue_rcv_skb(sk, skb); |
1750 | 1751 | sock_put(sk); | |
1751 | /* a return value > 0 means to resubmit the input, but | 1752 | /* a return value > 0 means to resubmit the input, but |
1752 | * it wants the return to be -protocol, or 0 | 1753 | * it wants the return to be -protocol, or 0 |
1753 | */ | 1754 | */ |
@@ -1913,17 +1914,20 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net, | |||
1913 | 1914 | ||
1914 | void udp_v4_early_demux(struct sk_buff *skb) | 1915 | void udp_v4_early_demux(struct sk_buff *skb) |
1915 | { | 1916 | { |
1916 | const struct iphdr *iph = ip_hdr(skb); | 1917 | struct net *net = dev_net(skb->dev); |
1917 | const struct udphdr *uh = udp_hdr(skb); | 1918 | const struct iphdr *iph; |
1919 | const struct udphdr *uh; | ||
1918 | struct sock *sk; | 1920 | struct sock *sk; |
1919 | struct dst_entry *dst; | 1921 | struct dst_entry *dst; |
1920 | struct net *net = dev_net(skb->dev); | ||
1921 | int dif = skb->dev->ifindex; | 1922 | int dif = skb->dev->ifindex; |
1922 | 1923 | ||
1923 | /* validate the packet */ | 1924 | /* validate the packet */ |
1924 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) | 1925 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) |
1925 | return; | 1926 | return; |
1926 | 1927 | ||
1928 | iph = ip_hdr(skb); | ||
1929 | uh = udp_hdr(skb); | ||
1930 | |||
1927 | if (skb->pkt_type == PACKET_BROADCAST || | 1931 | if (skb->pkt_type == PACKET_BROADCAST || |
1928 | skb->pkt_type == PACKET_MULTICAST) | 1932 | skb->pkt_type == PACKET_MULTICAST) |
1929 | sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, | 1933 | sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 8dfe1f4d3c1a..93b1aa34c432 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -73,7 +73,6 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
73 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 73 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
74 | if (flowlabel == NULL) | 74 | if (flowlabel == NULL) |
75 | return -EINVAL; | 75 | return -EINVAL; |
76 | usin->sin6_addr = flowlabel->dst; | ||
77 | } | 76 | } |
78 | } | 77 | } |
79 | 78 | ||
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index e27591635f92..3fd0a578329e 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -122,7 +122,11 @@ out: | |||
122 | static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) | 122 | static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) |
123 | { | 123 | { |
124 | struct rt6_info *rt = (struct rt6_info *) arg->result; | 124 | struct rt6_info *rt = (struct rt6_info *) arg->result; |
125 | struct net_device *dev = rt->rt6i_idev->dev; | 125 | struct net_device *dev = NULL; |
126 | |||
127 | if (rt->rt6i_idev) | ||
128 | dev = rt->rt6i_idev->dev; | ||
129 | |||
126 | /* do not accept result if the route does | 130 | /* do not accept result if the route does |
127 | * not meet the required prefix length | 131 | * not meet the required prefix length |
128 | */ | 132 | */ |
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index f78f41aca8e9..a0d17270117c 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c | |||
@@ -446,6 +446,7 @@ static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par) | |||
446 | static struct xt_target synproxy_tg6_reg __read_mostly = { | 446 | static struct xt_target synproxy_tg6_reg __read_mostly = { |
447 | .name = "SYNPROXY", | 447 | .name = "SYNPROXY", |
448 | .family = NFPROTO_IPV6, | 448 | .family = NFPROTO_IPV6, |
449 | .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD), | ||
449 | .target = synproxy_tg6, | 450 | .target = synproxy_tg6, |
450 | .targetsize = sizeof(struct xt_synproxy_info), | 451 | .targetsize = sizeof(struct xt_synproxy_info), |
451 | .checkentry = synproxy_tg6_check, | 452 | .checkentry = synproxy_tg6_check, |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 7fb4e14c467f..b6bb87e55805 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -792,7 +792,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
792 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 792 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
793 | if (flowlabel == NULL) | 793 | if (flowlabel == NULL) |
794 | return -EINVAL; | 794 | return -EINVAL; |
795 | daddr = &flowlabel->dst; | ||
796 | } | 795 | } |
797 | } | 796 | } |
798 | 797 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a1a57523b158..89b2735cecf5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2170,12 +2170,10 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2170 | bool anycast) | 2170 | bool anycast) |
2171 | { | 2171 | { |
2172 | struct net *net = dev_net(idev->dev); | 2172 | struct net *net = dev_net(idev->dev); |
2173 | struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 0, NULL); | 2173 | struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, |
2174 | 2174 | DST_NOCOUNT, NULL); | |
2175 | if (!rt) { | 2175 | if (!rt) |
2176 | net_warn_ratelimited("Maximum number of routes reached, consider increasing route/max_size\n"); | ||
2177 | return ERR_PTR(-ENOMEM); | 2176 | return ERR_PTR(-ENOMEM); |
2178 | } | ||
2179 | 2177 | ||
2180 | in6_dev_hold(idev); | 2178 | in6_dev_hold(idev); |
2181 | 2179 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index bd91e7ff482b..da046a5d7ffb 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -156,7 +156,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
156 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 156 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
157 | if (flowlabel == NULL) | 157 | if (flowlabel == NULL) |
158 | return -EINVAL; | 158 | return -EINVAL; |
159 | usin->sin6_addr = flowlabel->dst; | ||
160 | fl6_sock_release(flowlabel); | 159 | fl6_sock_release(flowlabel); |
161 | } | 160 | } |
162 | } | 161 | } |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index bcd5699313c3..089c741a3992 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1140,7 +1140,6 @@ do_udp_sendmsg: | |||
1140 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 1140 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
1141 | if (flowlabel == NULL) | 1141 | if (flowlabel == NULL) |
1142 | return -EINVAL; | 1142 | return -EINVAL; |
1143 | daddr = &flowlabel->dst; | ||
1144 | } | 1143 | } |
1145 | } | 1144 | } |
1146 | 1145 | ||
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index d9b437e55007..bb6e206ea70b 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c | |||
@@ -528,7 +528,6 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
528 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 528 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
529 | if (flowlabel == NULL) | 529 | if (flowlabel == NULL) |
530 | return -EINVAL; | 530 | return -EINVAL; |
531 | daddr = &flowlabel->dst; | ||
532 | } | 531 | } |
533 | } | 532 | } |
534 | 533 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c index 2bc2dec20b00..6226803fc490 100644 --- a/net/netfilter/ipset/ip_set_hash_netnet.c +++ b/net/netfilter/ipset/ip_set_hash_netnet.c | |||
@@ -59,7 +59,7 @@ hash_netnet4_data_equal(const struct hash_netnet4_elem *ip1, | |||
59 | u32 *multi) | 59 | u32 *multi) |
60 | { | 60 | { |
61 | return ip1->ipcmp == ip2->ipcmp && | 61 | return ip1->ipcmp == ip2->ipcmp && |
62 | ip2->ccmp == ip2->ccmp; | 62 | ip1->ccmp == ip2->ccmp; |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline int | 65 | static inline int |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index dcddc49c0e08..f93b7d06f4be 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -1717,6 +1717,19 @@ nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule) | |||
1717 | return -ENOENT; | 1717 | return -ENOENT; |
1718 | } | 1718 | } |
1719 | 1719 | ||
1720 | static int nf_table_delrule_by_chain(struct nft_ctx *ctx) | ||
1721 | { | ||
1722 | struct nft_rule *rule; | ||
1723 | int err; | ||
1724 | |||
1725 | list_for_each_entry(rule, &ctx->chain->rules, list) { | ||
1726 | err = nf_tables_delrule_one(ctx, rule); | ||
1727 | if (err < 0) | ||
1728 | return err; | ||
1729 | } | ||
1730 | return 0; | ||
1731 | } | ||
1732 | |||
1720 | static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb, | 1733 | static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb, |
1721 | const struct nlmsghdr *nlh, | 1734 | const struct nlmsghdr *nlh, |
1722 | const struct nlattr * const nla[]) | 1735 | const struct nlattr * const nla[]) |
@@ -1725,8 +1738,8 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb, | |||
1725 | const struct nft_af_info *afi; | 1738 | const struct nft_af_info *afi; |
1726 | struct net *net = sock_net(skb->sk); | 1739 | struct net *net = sock_net(skb->sk); |
1727 | const struct nft_table *table; | 1740 | const struct nft_table *table; |
1728 | struct nft_chain *chain; | 1741 | struct nft_chain *chain = NULL; |
1729 | struct nft_rule *rule, *tmp; | 1742 | struct nft_rule *rule; |
1730 | int family = nfmsg->nfgen_family, err = 0; | 1743 | int family = nfmsg->nfgen_family, err = 0; |
1731 | struct nft_ctx ctx; | 1744 | struct nft_ctx ctx; |
1732 | 1745 | ||
@@ -1738,22 +1751,29 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb, | |||
1738 | if (IS_ERR(table)) | 1751 | if (IS_ERR(table)) |
1739 | return PTR_ERR(table); | 1752 | return PTR_ERR(table); |
1740 | 1753 | ||
1741 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]); | 1754 | if (nla[NFTA_RULE_CHAIN]) { |
1742 | if (IS_ERR(chain)) | 1755 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]); |
1743 | return PTR_ERR(chain); | 1756 | if (IS_ERR(chain)) |
1757 | return PTR_ERR(chain); | ||
1758 | } | ||
1744 | 1759 | ||
1745 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); | 1760 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); |
1746 | 1761 | ||
1747 | if (nla[NFTA_RULE_HANDLE]) { | 1762 | if (chain) { |
1748 | rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]); | 1763 | if (nla[NFTA_RULE_HANDLE]) { |
1749 | if (IS_ERR(rule)) | 1764 | rule = nf_tables_rule_lookup(chain, |
1750 | return PTR_ERR(rule); | 1765 | nla[NFTA_RULE_HANDLE]); |
1766 | if (IS_ERR(rule)) | ||
1767 | return PTR_ERR(rule); | ||
1751 | 1768 | ||
1752 | err = nf_tables_delrule_one(&ctx, rule); | ||
1753 | } else { | ||
1754 | /* Remove all rules in this chain */ | ||
1755 | list_for_each_entry_safe(rule, tmp, &chain->rules, list) { | ||
1756 | err = nf_tables_delrule_one(&ctx, rule); | 1769 | err = nf_tables_delrule_one(&ctx, rule); |
1770 | } else { | ||
1771 | err = nf_table_delrule_by_chain(&ctx); | ||
1772 | } | ||
1773 | } else { | ||
1774 | list_for_each_entry(chain, &table->chains, list) { | ||
1775 | ctx.chain = chain; | ||
1776 | err = nf_table_delrule_by_chain(&ctx); | ||
1757 | if (err < 0) | 1777 | if (err < 0) |
1758 | break; | 1778 | break; |
1759 | } | 1779 | } |
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 9ff035c71403..a3910fc2122b 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
@@ -325,21 +325,24 @@ static void htable_gc(unsigned long htlong) | |||
325 | add_timer(&ht->timer); | 325 | add_timer(&ht->timer); |
326 | } | 326 | } |
327 | 327 | ||
328 | static void htable_destroy(struct xt_hashlimit_htable *hinfo) | 328 | static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) |
329 | { | 329 | { |
330 | struct hashlimit_net *hashlimit_net = hashlimit_pernet(hinfo->net); | 330 | struct hashlimit_net *hashlimit_net = hashlimit_pernet(hinfo->net); |
331 | struct proc_dir_entry *parent; | 331 | struct proc_dir_entry *parent; |
332 | 332 | ||
333 | del_timer_sync(&hinfo->timer); | ||
334 | |||
335 | if (hinfo->family == NFPROTO_IPV4) | 333 | if (hinfo->family == NFPROTO_IPV4) |
336 | parent = hashlimit_net->ipt_hashlimit; | 334 | parent = hashlimit_net->ipt_hashlimit; |
337 | else | 335 | else |
338 | parent = hashlimit_net->ip6t_hashlimit; | 336 | parent = hashlimit_net->ip6t_hashlimit; |
339 | 337 | ||
340 | if(parent != NULL) | 338 | if (parent != NULL) |
341 | remove_proc_entry(hinfo->name, parent); | 339 | remove_proc_entry(hinfo->name, parent); |
340 | } | ||
342 | 341 | ||
342 | static void htable_destroy(struct xt_hashlimit_htable *hinfo) | ||
343 | { | ||
344 | del_timer_sync(&hinfo->timer); | ||
345 | htable_remove_proc_entry(hinfo); | ||
343 | htable_selective_cleanup(hinfo, select_all); | 346 | htable_selective_cleanup(hinfo, select_all); |
344 | kfree(hinfo->name); | 347 | kfree(hinfo->name); |
345 | vfree(hinfo); | 348 | vfree(hinfo); |
@@ -883,21 +886,15 @@ static int __net_init hashlimit_proc_net_init(struct net *net) | |||
883 | static void __net_exit hashlimit_proc_net_exit(struct net *net) | 886 | static void __net_exit hashlimit_proc_net_exit(struct net *net) |
884 | { | 887 | { |
885 | struct xt_hashlimit_htable *hinfo; | 888 | struct xt_hashlimit_htable *hinfo; |
886 | struct proc_dir_entry *pde; | ||
887 | struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); | 889 | struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); |
888 | 890 | ||
889 | /* recent_net_exit() is called before recent_mt_destroy(). Make sure | 891 | /* hashlimit_net_exit() is called before hashlimit_mt_destroy(). |
890 | * that the parent xt_recent proc entry is is empty before trying to | 892 | * Make sure that the parent ipt_hashlimit and ip6t_hashlimit proc |
891 | * remove it. | 893 | * entries is empty before trying to remove it. |
892 | */ | 894 | */ |
893 | mutex_lock(&hashlimit_mutex); | 895 | mutex_lock(&hashlimit_mutex); |
894 | pde = hashlimit_net->ipt_hashlimit; | ||
895 | if (pde == NULL) | ||
896 | pde = hashlimit_net->ip6t_hashlimit; | ||
897 | |||
898 | hlist_for_each_entry(hinfo, &hashlimit_net->htables, node) | 896 | hlist_for_each_entry(hinfo, &hashlimit_net->htables, node) |
899 | remove_proc_entry(hinfo->name, pde); | 897 | htable_remove_proc_entry(hinfo); |
900 | |||
901 | hashlimit_net->ipt_hashlimit = NULL; | 898 | hashlimit_net->ipt_hashlimit = NULL; |
902 | hashlimit_net->ip6t_hashlimit = NULL; | 899 | hashlimit_net->ip6t_hashlimit = NULL; |
903 | mutex_unlock(&hashlimit_mutex); | 900 | mutex_unlock(&hashlimit_mutex); |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 830c64f25539..6b0e854b0115 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -1471,11 +1471,22 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1471 | sch_tree_lock(sch); | 1471 | sch_tree_lock(sch); |
1472 | } | 1472 | } |
1473 | 1473 | ||
1474 | rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0; | ||
1475 | |||
1476 | ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0; | ||
1477 | |||
1478 | psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64); | ||
1479 | psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64); | ||
1480 | |||
1474 | /* it used to be a nasty bug here, we have to check that node | 1481 | /* it used to be a nasty bug here, we have to check that node |
1475 | * is really leaf before changing cl->un.leaf ! | 1482 | * is really leaf before changing cl->un.leaf ! |
1476 | */ | 1483 | */ |
1477 | if (!cl->level) { | 1484 | if (!cl->level) { |
1478 | cl->quantum = hopt->rate.rate / q->rate2quantum; | 1485 | u64 quantum = cl->rate.rate_bytes_ps; |
1486 | |||
1487 | do_div(quantum, q->rate2quantum); | ||
1488 | cl->quantum = min_t(u64, quantum, INT_MAX); | ||
1489 | |||
1479 | if (!hopt->quantum && cl->quantum < 1000) { | 1490 | if (!hopt->quantum && cl->quantum < 1000) { |
1480 | pr_warning( | 1491 | pr_warning( |
1481 | "HTB: quantum of class %X is small. Consider r2q change.\n", | 1492 | "HTB: quantum of class %X is small. Consider r2q change.\n", |
@@ -1494,13 +1505,6 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1494 | cl->prio = TC_HTB_NUMPRIO - 1; | 1505 | cl->prio = TC_HTB_NUMPRIO - 1; |
1495 | } | 1506 | } |
1496 | 1507 | ||
1497 | rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0; | ||
1498 | |||
1499 | ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0; | ||
1500 | |||
1501 | psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64); | ||
1502 | psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64); | ||
1503 | |||
1504 | cl->buffer = PSCHED_TICKS2NS(hopt->buffer); | 1508 | cl->buffer = PSCHED_TICKS2NS(hopt->buffer); |
1505 | cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer); | 1509 | cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer); |
1506 | 1510 | ||
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index a6090051c5db..887e672f9d7d 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -118,6 +118,32 @@ struct tbf_sched_data { | |||
118 | }; | 118 | }; |
119 | 119 | ||
120 | 120 | ||
121 | /* Time to Length, convert time in ns to length in bytes | ||
122 | * to determinate how many bytes can be sent in given time. | ||
123 | */ | ||
124 | static u64 psched_ns_t2l(const struct psched_ratecfg *r, | ||
125 | u64 time_in_ns) | ||
126 | { | ||
127 | /* The formula is : | ||
128 | * len = (time_in_ns * r->rate_bytes_ps) / NSEC_PER_SEC | ||
129 | */ | ||
130 | u64 len = time_in_ns * r->rate_bytes_ps; | ||
131 | |||
132 | do_div(len, NSEC_PER_SEC); | ||
133 | |||
134 | if (unlikely(r->linklayer == TC_LINKLAYER_ATM)) { | ||
135 | do_div(len, 53); | ||
136 | len = len * 48; | ||
137 | } | ||
138 | |||
139 | if (len > r->overhead) | ||
140 | len -= r->overhead; | ||
141 | else | ||
142 | len = 0; | ||
143 | |||
144 | return len; | ||
145 | } | ||
146 | |||
121 | /* | 147 | /* |
122 | * Return length of individual segments of a gso packet, | 148 | * Return length of individual segments of a gso packet, |
123 | * including all headers (MAC, IP, TCP/UDP) | 149 | * including all headers (MAC, IP, TCP/UDP) |
@@ -289,10 +315,11 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
289 | struct tbf_sched_data *q = qdisc_priv(sch); | 315 | struct tbf_sched_data *q = qdisc_priv(sch); |
290 | struct nlattr *tb[TCA_TBF_MAX + 1]; | 316 | struct nlattr *tb[TCA_TBF_MAX + 1]; |
291 | struct tc_tbf_qopt *qopt; | 317 | struct tc_tbf_qopt *qopt; |
292 | struct qdisc_rate_table *rtab = NULL; | ||
293 | struct qdisc_rate_table *ptab = NULL; | ||
294 | struct Qdisc *child = NULL; | 318 | struct Qdisc *child = NULL; |
295 | int max_size, n; | 319 | struct psched_ratecfg rate; |
320 | struct psched_ratecfg peak; | ||
321 | u64 max_size; | ||
322 | s64 buffer, mtu; | ||
296 | u64 rate64 = 0, prate64 = 0; | 323 | u64 rate64 = 0, prate64 = 0; |
297 | 324 | ||
298 | err = nla_parse_nested(tb, TCA_TBF_MAX, opt, tbf_policy); | 325 | err = nla_parse_nested(tb, TCA_TBF_MAX, opt, tbf_policy); |
@@ -304,38 +331,13 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
304 | goto done; | 331 | goto done; |
305 | 332 | ||
306 | qopt = nla_data(tb[TCA_TBF_PARMS]); | 333 | qopt = nla_data(tb[TCA_TBF_PARMS]); |
307 | rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB]); | 334 | if (qopt->rate.linklayer == TC_LINKLAYER_UNAWARE) |
308 | if (rtab == NULL) | 335 | qdisc_put_rtab(qdisc_get_rtab(&qopt->rate, |
309 | goto done; | 336 | tb[TCA_TBF_RTAB])); |
310 | |||
311 | if (qopt->peakrate.rate) { | ||
312 | if (qopt->peakrate.rate > qopt->rate.rate) | ||
313 | ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]); | ||
314 | if (ptab == NULL) | ||
315 | goto done; | ||
316 | } | ||
317 | |||
318 | for (n = 0; n < 256; n++) | ||
319 | if (rtab->data[n] > qopt->buffer) | ||
320 | break; | ||
321 | max_size = (n << qopt->rate.cell_log) - 1; | ||
322 | if (ptab) { | ||
323 | int size; | ||
324 | |||
325 | for (n = 0; n < 256; n++) | ||
326 | if (ptab->data[n] > qopt->mtu) | ||
327 | break; | ||
328 | size = (n << qopt->peakrate.cell_log) - 1; | ||
329 | if (size < max_size) | ||
330 | max_size = size; | ||
331 | } | ||
332 | if (max_size < 0) | ||
333 | goto done; | ||
334 | 337 | ||
335 | if (max_size < psched_mtu(qdisc_dev(sch))) | 338 | if (qopt->peakrate.linklayer == TC_LINKLAYER_UNAWARE) |
336 | pr_warn_ratelimited("sch_tbf: burst %u is lower than device %s mtu (%u) !\n", | 339 | qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate, |
337 | max_size, qdisc_dev(sch)->name, | 340 | tb[TCA_TBF_PTAB])); |
338 | psched_mtu(qdisc_dev(sch))); | ||
339 | 341 | ||
340 | if (q->qdisc != &noop_qdisc) { | 342 | if (q->qdisc != &noop_qdisc) { |
341 | err = fifo_set_limit(q->qdisc, qopt->limit); | 343 | err = fifo_set_limit(q->qdisc, qopt->limit); |
@@ -349,6 +351,39 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
349 | } | 351 | } |
350 | } | 352 | } |
351 | 353 | ||
354 | buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U); | ||
355 | mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U); | ||
356 | |||
357 | if (tb[TCA_TBF_RATE64]) | ||
358 | rate64 = nla_get_u64(tb[TCA_TBF_RATE64]); | ||
359 | psched_ratecfg_precompute(&rate, &qopt->rate, rate64); | ||
360 | |||
361 | max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U); | ||
362 | |||
363 | if (qopt->peakrate.rate) { | ||
364 | if (tb[TCA_TBF_PRATE64]) | ||
365 | prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]); | ||
366 | psched_ratecfg_precompute(&peak, &qopt->peakrate, prate64); | ||
367 | if (peak.rate_bytes_ps <= rate.rate_bytes_ps) { | ||
368 | pr_warn_ratelimited("sch_tbf: peakrate %llu is lower than or equals to rate %llu !\n", | ||
369 | peak.rate_bytes_ps, rate.rate_bytes_ps); | ||
370 | err = -EINVAL; | ||
371 | goto done; | ||
372 | } | ||
373 | |||
374 | max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu)); | ||
375 | } | ||
376 | |||
377 | if (max_size < psched_mtu(qdisc_dev(sch))) | ||
378 | pr_warn_ratelimited("sch_tbf: burst %llu is lower than device %s mtu (%u) !\n", | ||
379 | max_size, qdisc_dev(sch)->name, | ||
380 | psched_mtu(qdisc_dev(sch))); | ||
381 | |||
382 | if (!max_size) { | ||
383 | err = -EINVAL; | ||
384 | goto done; | ||
385 | } | ||
386 | |||
352 | sch_tree_lock(sch); | 387 | sch_tree_lock(sch); |
353 | if (child) { | 388 | if (child) { |
354 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); | 389 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); |
@@ -362,13 +397,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
362 | q->tokens = q->buffer; | 397 | q->tokens = q->buffer; |
363 | q->ptokens = q->mtu; | 398 | q->ptokens = q->mtu; |
364 | 399 | ||
365 | if (tb[TCA_TBF_RATE64]) | 400 | memcpy(&q->rate, &rate, sizeof(struct psched_ratecfg)); |
366 | rate64 = nla_get_u64(tb[TCA_TBF_RATE64]); | 401 | if (qopt->peakrate.rate) { |
367 | psched_ratecfg_precompute(&q->rate, &rtab->rate, rate64); | 402 | memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg)); |
368 | if (ptab) { | ||
369 | if (tb[TCA_TBF_PRATE64]) | ||
370 | prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]); | ||
371 | psched_ratecfg_precompute(&q->peak, &ptab->rate, prate64); | ||
372 | q->peak_present = true; | 403 | q->peak_present = true; |
373 | } else { | 404 | } else { |
374 | q->peak_present = false; | 405 | q->peak_present = false; |
@@ -377,10 +408,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
377 | sch_tree_unlock(sch); | 408 | sch_tree_unlock(sch); |
378 | err = 0; | 409 | err = 0; |
379 | done: | 410 | done: |
380 | if (rtab) | ||
381 | qdisc_put_rtab(rtab); | ||
382 | if (ptab) | ||
383 | qdisc_put_rtab(ptab); | ||
384 | return err; | 411 | return err; |
385 | } | 412 | } |
386 | 413 | ||
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 3d7c6bd46311..5ae609200674 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -145,8 +145,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
145 | = 5 * asoc->rto_max; | 145 | = 5 * asoc->rto_max; |
146 | 146 | ||
147 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; | 147 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; |
148 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = | 148 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ; |
149 | min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ; | ||
150 | 149 | ||
151 | /* Initializes the timers */ | 150 | /* Initializes the timers */ |
152 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) | 151 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) |
@@ -254,8 +253,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
254 | asoc->peer.ipv6_address = 1; | 253 | asoc->peer.ipv6_address = 1; |
255 | INIT_LIST_HEAD(&asoc->asocs); | 254 | INIT_LIST_HEAD(&asoc->asocs); |
256 | 255 | ||
257 | asoc->autoclose = sp->autoclose; | ||
258 | |||
259 | asoc->default_stream = sp->default_stream; | 256 | asoc->default_stream = sp->default_stream; |
260 | asoc->default_ppid = sp->default_ppid; | 257 | asoc->default_ppid = sp->default_ppid; |
261 | asoc->default_flags = sp->default_flags; | 258 | asoc->default_flags = sp->default_flags; |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 6371337e1fe7..3f55823279d9 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -580,7 +580,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
580 | unsigned long timeout; | 580 | unsigned long timeout; |
581 | 581 | ||
582 | /* Restart the AUTOCLOSE timer when sending data. */ | 582 | /* Restart the AUTOCLOSE timer when sending data. */ |
583 | if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) { | 583 | if (sctp_state(asoc, ESTABLISHED) && |
584 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { | ||
584 | timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; | 585 | timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; |
585 | timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; | 586 | timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; |
586 | 587 | ||
diff --git a/net/sctp/probe.c b/net/sctp/probe.c index 53c452efb40b..5e68b94ee640 100644 --- a/net/sctp/probe.c +++ b/net/sctp/probe.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <net/sctp/sctp.h> | 38 | #include <net/sctp/sctp.h> |
39 | #include <net/sctp/sm.h> | 39 | #include <net/sctp/sm.h> |
40 | 40 | ||
41 | MODULE_SOFTDEP("pre: sctp"); | ||
41 | MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>"); | 42 | MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>"); |
42 | MODULE_DESCRIPTION("SCTP snooper"); | 43 | MODULE_DESCRIPTION("SCTP snooper"); |
43 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
@@ -182,6 +183,20 @@ static struct jprobe sctp_recv_probe = { | |||
182 | .entry = jsctp_sf_eat_sack, | 183 | .entry = jsctp_sf_eat_sack, |
183 | }; | 184 | }; |
184 | 185 | ||
186 | static __init int sctp_setup_jprobe(void) | ||
187 | { | ||
188 | int ret = register_jprobe(&sctp_recv_probe); | ||
189 | |||
190 | if (ret) { | ||
191 | if (request_module("sctp")) | ||
192 | goto out; | ||
193 | ret = register_jprobe(&sctp_recv_probe); | ||
194 | } | ||
195 | |||
196 | out: | ||
197 | return ret; | ||
198 | } | ||
199 | |||
185 | static __init int sctpprobe_init(void) | 200 | static __init int sctpprobe_init(void) |
186 | { | 201 | { |
187 | int ret = -ENOMEM; | 202 | int ret = -ENOMEM; |
@@ -202,7 +217,7 @@ static __init int sctpprobe_init(void) | |||
202 | &sctpprobe_fops)) | 217 | &sctpprobe_fops)) |
203 | goto free_kfifo; | 218 | goto free_kfifo; |
204 | 219 | ||
205 | ret = register_jprobe(&sctp_recv_probe); | 220 | ret = sctp_setup_jprobe(); |
206 | if (ret) | 221 | if (ret) |
207 | goto remove_proc; | 222 | goto remove_proc; |
208 | 223 | ||
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index dd0eba919a8b..ee02771d8b9c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -819,7 +819,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, | |||
819 | SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); | 819 | SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); |
820 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 820 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
821 | 821 | ||
822 | if (new_asoc->autoclose) | 822 | if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
823 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 823 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
824 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 824 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
825 | 825 | ||
@@ -907,7 +907,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(struct net *net, | |||
907 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); | 907 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); |
908 | SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); | 908 | SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); |
909 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 909 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
910 | if (asoc->autoclose) | 910 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
911 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 911 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
912 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 912 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
913 | 913 | ||
@@ -2969,7 +2969,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net, | |||
2969 | if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) | 2969 | if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) |
2970 | force = SCTP_FORCE(); | 2970 | force = SCTP_FORCE(); |
2971 | 2971 | ||
2972 | if (asoc->autoclose) { | 2972 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { |
2973 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 2973 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
2974 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 2974 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
2975 | } | 2975 | } |
@@ -3877,7 +3877,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net, | |||
3877 | SCTP_CHUNK(chunk)); | 3877 | SCTP_CHUNK(chunk)); |
3878 | 3878 | ||
3879 | /* Count this as receiving DATA. */ | 3879 | /* Count this as receiving DATA. */ |
3880 | if (asoc->autoclose) { | 3880 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { |
3881 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 3881 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
3882 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 3882 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
3883 | } | 3883 | } |
@@ -5266,7 +5266,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( | |||
5266 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 5266 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
5267 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 5267 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
5268 | 5268 | ||
5269 | if (asoc->autoclose) | 5269 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
5270 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5270 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
5271 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 5271 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
5272 | 5272 | ||
@@ -5345,7 +5345,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack( | |||
5345 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 5345 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
5346 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); | 5346 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); |
5347 | 5347 | ||
5348 | if (asoc->autoclose) | 5348 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
5349 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5349 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
5350 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 5350 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
5351 | 5351 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 191cd9257806..d39fd0c2c4cf 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2195,6 +2195,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
2195 | unsigned int optlen) | 2195 | unsigned int optlen) |
2196 | { | 2196 | { |
2197 | struct sctp_sock *sp = sctp_sk(sk); | 2197 | struct sctp_sock *sp = sctp_sk(sk); |
2198 | struct net *net = sock_net(sk); | ||
2198 | 2199 | ||
2199 | /* Applicable to UDP-style socket only */ | 2200 | /* Applicable to UDP-style socket only */ |
2200 | if (sctp_style(sk, TCP)) | 2201 | if (sctp_style(sk, TCP)) |
@@ -2204,6 +2205,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
2204 | if (copy_from_user(&sp->autoclose, optval, optlen)) | 2205 | if (copy_from_user(&sp->autoclose, optval, optlen)) |
2205 | return -EFAULT; | 2206 | return -EFAULT; |
2206 | 2207 | ||
2208 | if (sp->autoclose > net->sctp.max_autoclose) | ||
2209 | sp->autoclose = net->sctp.max_autoclose; | ||
2210 | |||
2207 | return 0; | 2211 | return 0; |
2208 | } | 2212 | } |
2209 | 2213 | ||
@@ -2810,6 +2814,8 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne | |||
2810 | { | 2814 | { |
2811 | struct sctp_rtoinfo rtoinfo; | 2815 | struct sctp_rtoinfo rtoinfo; |
2812 | struct sctp_association *asoc; | 2816 | struct sctp_association *asoc; |
2817 | unsigned long rto_min, rto_max; | ||
2818 | struct sctp_sock *sp = sctp_sk(sk); | ||
2813 | 2819 | ||
2814 | if (optlen != sizeof (struct sctp_rtoinfo)) | 2820 | if (optlen != sizeof (struct sctp_rtoinfo)) |
2815 | return -EINVAL; | 2821 | return -EINVAL; |
@@ -2823,26 +2829,36 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne | |||
2823 | if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) | 2829 | if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) |
2824 | return -EINVAL; | 2830 | return -EINVAL; |
2825 | 2831 | ||
2832 | rto_max = rtoinfo.srto_max; | ||
2833 | rto_min = rtoinfo.srto_min; | ||
2834 | |||
2835 | if (rto_max) | ||
2836 | rto_max = asoc ? msecs_to_jiffies(rto_max) : rto_max; | ||
2837 | else | ||
2838 | rto_max = asoc ? asoc->rto_max : sp->rtoinfo.srto_max; | ||
2839 | |||
2840 | if (rto_min) | ||
2841 | rto_min = asoc ? msecs_to_jiffies(rto_min) : rto_min; | ||
2842 | else | ||
2843 | rto_min = asoc ? asoc->rto_min : sp->rtoinfo.srto_min; | ||
2844 | |||
2845 | if (rto_min > rto_max) | ||
2846 | return -EINVAL; | ||
2847 | |||
2826 | if (asoc) { | 2848 | if (asoc) { |
2827 | if (rtoinfo.srto_initial != 0) | 2849 | if (rtoinfo.srto_initial != 0) |
2828 | asoc->rto_initial = | 2850 | asoc->rto_initial = |
2829 | msecs_to_jiffies(rtoinfo.srto_initial); | 2851 | msecs_to_jiffies(rtoinfo.srto_initial); |
2830 | if (rtoinfo.srto_max != 0) | 2852 | asoc->rto_max = rto_max; |
2831 | asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max); | 2853 | asoc->rto_min = rto_min; |
2832 | if (rtoinfo.srto_min != 0) | ||
2833 | asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min); | ||
2834 | } else { | 2854 | } else { |
2835 | /* If there is no association or the association-id = 0 | 2855 | /* If there is no association or the association-id = 0 |
2836 | * set the values to the endpoint. | 2856 | * set the values to the endpoint. |
2837 | */ | 2857 | */ |
2838 | struct sctp_sock *sp = sctp_sk(sk); | ||
2839 | |||
2840 | if (rtoinfo.srto_initial != 0) | 2858 | if (rtoinfo.srto_initial != 0) |
2841 | sp->rtoinfo.srto_initial = rtoinfo.srto_initial; | 2859 | sp->rtoinfo.srto_initial = rtoinfo.srto_initial; |
2842 | if (rtoinfo.srto_max != 0) | 2860 | sp->rtoinfo.srto_max = rto_max; |
2843 | sp->rtoinfo.srto_max = rtoinfo.srto_max; | 2861 | sp->rtoinfo.srto_min = rto_min; |
2844 | if (rtoinfo.srto_min != 0) | ||
2845 | sp->rtoinfo.srto_min = rtoinfo.srto_min; | ||
2846 | } | 2862 | } |
2847 | 2863 | ||
2848 | return 0; | 2864 | return 0; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 80b17b5df6bb..9dd5ac084663 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -55,11 +55,16 @@ extern long sysctl_sctp_mem[3]; | |||
55 | extern int sysctl_sctp_rmem[3]; | 55 | extern int sysctl_sctp_rmem[3]; |
56 | extern int sysctl_sctp_wmem[3]; | 56 | extern int sysctl_sctp_wmem[3]; |
57 | 57 | ||
58 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | 58 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, |
59 | int write, | 59 | void __user *buffer, size_t *lenp, |
60 | loff_t *ppos); | ||
61 | static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, | ||
62 | void __user *buffer, size_t *lenp, | ||
63 | loff_t *ppos); | ||
64 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | ||
60 | void __user *buffer, size_t *lenp, | 65 | void __user *buffer, size_t *lenp, |
61 | |||
62 | loff_t *ppos); | 66 | loff_t *ppos); |
67 | |||
63 | static struct ctl_table sctp_table[] = { | 68 | static struct ctl_table sctp_table[] = { |
64 | { | 69 | { |
65 | .procname = "sctp_mem", | 70 | .procname = "sctp_mem", |
@@ -101,17 +106,17 @@ static struct ctl_table sctp_net_table[] = { | |||
101 | .data = &init_net.sctp.rto_min, | 106 | .data = &init_net.sctp.rto_min, |
102 | .maxlen = sizeof(unsigned int), | 107 | .maxlen = sizeof(unsigned int), |
103 | .mode = 0644, | 108 | .mode = 0644, |
104 | .proc_handler = proc_dointvec_minmax, | 109 | .proc_handler = proc_sctp_do_rto_min, |
105 | .extra1 = &one, | 110 | .extra1 = &one, |
106 | .extra2 = &timer_max | 111 | .extra2 = &init_net.sctp.rto_max |
107 | }, | 112 | }, |
108 | { | 113 | { |
109 | .procname = "rto_max", | 114 | .procname = "rto_max", |
110 | .data = &init_net.sctp.rto_max, | 115 | .data = &init_net.sctp.rto_max, |
111 | .maxlen = sizeof(unsigned int), | 116 | .maxlen = sizeof(unsigned int), |
112 | .mode = 0644, | 117 | .mode = 0644, |
113 | .proc_handler = proc_dointvec_minmax, | 118 | .proc_handler = proc_sctp_do_rto_max, |
114 | .extra1 = &one, | 119 | .extra1 = &init_net.sctp.rto_min, |
115 | .extra2 = &timer_max | 120 | .extra2 = &timer_max |
116 | }, | 121 | }, |
117 | { | 122 | { |
@@ -293,8 +298,7 @@ static struct ctl_table sctp_net_table[] = { | |||
293 | { /* sentinel */ } | 298 | { /* sentinel */ } |
294 | }; | 299 | }; |
295 | 300 | ||
296 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | 301 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, |
297 | int write, | ||
298 | void __user *buffer, size_t *lenp, | 302 | void __user *buffer, size_t *lenp, |
299 | loff_t *ppos) | 303 | loff_t *ppos) |
300 | { | 304 | { |
@@ -341,6 +345,60 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | |||
341 | return ret; | 345 | return ret; |
342 | } | 346 | } |
343 | 347 | ||
348 | static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, | ||
349 | void __user *buffer, size_t *lenp, | ||
350 | loff_t *ppos) | ||
351 | { | ||
352 | struct net *net = current->nsproxy->net_ns; | ||
353 | int new_value; | ||
354 | struct ctl_table tbl; | ||
355 | unsigned int min = *(unsigned int *) ctl->extra1; | ||
356 | unsigned int max = *(unsigned int *) ctl->extra2; | ||
357 | int ret; | ||
358 | |||
359 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
360 | tbl.maxlen = sizeof(unsigned int); | ||
361 | |||
362 | if (write) | ||
363 | tbl.data = &new_value; | ||
364 | else | ||
365 | tbl.data = &net->sctp.rto_min; | ||
366 | ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); | ||
367 | if (write) { | ||
368 | if (ret || new_value > max || new_value < min) | ||
369 | return -EINVAL; | ||
370 | net->sctp.rto_min = new_value; | ||
371 | } | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | ||
376 | void __user *buffer, size_t *lenp, | ||
377 | loff_t *ppos) | ||
378 | { | ||
379 | struct net *net = current->nsproxy->net_ns; | ||
380 | int new_value; | ||
381 | struct ctl_table tbl; | ||
382 | unsigned int min = *(unsigned int *) ctl->extra1; | ||
383 | unsigned int max = *(unsigned int *) ctl->extra2; | ||
384 | int ret; | ||
385 | |||
386 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
387 | tbl.maxlen = sizeof(unsigned int); | ||
388 | |||
389 | if (write) | ||
390 | tbl.data = &new_value; | ||
391 | else | ||
392 | tbl.data = &net->sctp.rto_max; | ||
393 | ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); | ||
394 | if (write) { | ||
395 | if (ret || new_value > max || new_value < min) | ||
396 | return -EINVAL; | ||
397 | net->sctp.rto_max = new_value; | ||
398 | } | ||
399 | return ret; | ||
400 | } | ||
401 | |||
344 | int sctp_sysctl_net_register(struct net *net) | 402 | int sctp_sysctl_net_register(struct net *net) |
345 | { | 403 | { |
346 | struct ctl_table *table; | 404 | struct ctl_table *table; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 97912b40c254..42fdfc634e56 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1517,7 +1517,7 @@ out: | |||
1517 | static int | 1517 | static int |
1518 | gss_refresh_null(struct rpc_task *task) | 1518 | gss_refresh_null(struct rpc_task *task) |
1519 | { | 1519 | { |
1520 | return -EACCES; | 1520 | return 0; |
1521 | } | 1521 | } |
1522 | 1522 | ||
1523 | static __be32 * | 1523 | static __be32 * |
diff --git a/net/tipc/core.c b/net/tipc/core.c index 68977c423022..f9e88d8b04ca 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -109,7 +109,6 @@ err: | |||
109 | static void tipc_core_stop(void) | 109 | static void tipc_core_stop(void) |
110 | { | 110 | { |
111 | tipc_netlink_stop(); | 111 | tipc_netlink_stop(); |
112 | tipc_handler_stop(); | ||
113 | tipc_cfg_stop(); | 112 | tipc_cfg_stop(); |
114 | tipc_subscr_stop(); | 113 | tipc_subscr_stop(); |
115 | tipc_nametbl_stop(); | 114 | tipc_nametbl_stop(); |
@@ -142,9 +141,10 @@ static int tipc_core_start(void) | |||
142 | res = tipc_subscr_start(); | 141 | res = tipc_subscr_start(); |
143 | if (!res) | 142 | if (!res) |
144 | res = tipc_cfg_init(); | 143 | res = tipc_cfg_init(); |
145 | if (res) | 144 | if (res) { |
145 | tipc_handler_stop(); | ||
146 | tipc_core_stop(); | 146 | tipc_core_stop(); |
147 | 147 | } | |
148 | return res; | 148 | return res; |
149 | } | 149 | } |
150 | 150 | ||
@@ -174,6 +174,7 @@ static int __init tipc_init(void) | |||
174 | 174 | ||
175 | static void __exit tipc_exit(void) | 175 | static void __exit tipc_exit(void) |
176 | { | 176 | { |
177 | tipc_handler_stop(); | ||
177 | tipc_core_stop_net(); | 178 | tipc_core_stop_net(); |
178 | tipc_core_stop(); | 179 | tipc_core_stop(); |
179 | pr_info("Deactivated\n"); | 180 | pr_info("Deactivated\n"); |
diff --git a/net/tipc/handler.c b/net/tipc/handler.c index b36f0fcd9bdf..e4bc8a296744 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c | |||
@@ -56,12 +56,13 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument) | |||
56 | { | 56 | { |
57 | struct queue_item *item; | 57 | struct queue_item *item; |
58 | 58 | ||
59 | spin_lock_bh(&qitem_lock); | ||
59 | if (!handler_enabled) { | 60 | if (!handler_enabled) { |
60 | pr_err("Signal request ignored by handler\n"); | 61 | pr_err("Signal request ignored by handler\n"); |
62 | spin_unlock_bh(&qitem_lock); | ||
61 | return -ENOPROTOOPT; | 63 | return -ENOPROTOOPT; |
62 | } | 64 | } |
63 | 65 | ||
64 | spin_lock_bh(&qitem_lock); | ||
65 | item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC); | 66 | item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC); |
66 | if (!item) { | 67 | if (!item) { |
67 | pr_err("Signal queue out of memory\n"); | 68 | pr_err("Signal queue out of memory\n"); |
@@ -112,10 +113,14 @@ void tipc_handler_stop(void) | |||
112 | struct list_head *l, *n; | 113 | struct list_head *l, *n; |
113 | struct queue_item *item; | 114 | struct queue_item *item; |
114 | 115 | ||
115 | if (!handler_enabled) | 116 | spin_lock_bh(&qitem_lock); |
117 | if (!handler_enabled) { | ||
118 | spin_unlock_bh(&qitem_lock); | ||
116 | return; | 119 | return; |
117 | 120 | } | |
118 | handler_enabled = 0; | 121 | handler_enabled = 0; |
122 | spin_unlock_bh(&qitem_lock); | ||
123 | |||
119 | tasklet_kill(&tipc_tasklet); | 124 | tasklet_kill(&tipc_tasklet); |
120 | 125 | ||
121 | spin_lock_bh(&qitem_lock); | 126 | spin_lock_bh(&qitem_lock); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 813622296317..800ca61758ff 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -532,13 +532,17 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, | |||
532 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, | 532 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, |
533 | struct msghdr *, size_t, int); | 533 | struct msghdr *, size_t, int); |
534 | 534 | ||
535 | static void unix_set_peek_off(struct sock *sk, int val) | 535 | static int unix_set_peek_off(struct sock *sk, int val) |
536 | { | 536 | { |
537 | struct unix_sock *u = unix_sk(sk); | 537 | struct unix_sock *u = unix_sk(sk); |
538 | 538 | ||
539 | mutex_lock(&u->readlock); | 539 | if (mutex_lock_interruptible(&u->readlock)) |
540 | return -EINTR; | ||
541 | |||
540 | sk->sk_peek_off = val; | 542 | sk->sk_peek_off = val; |
541 | mutex_unlock(&u->readlock); | 543 | mutex_unlock(&u->readlock); |
544 | |||
545 | return 0; | ||
542 | } | 546 | } |
543 | 547 | ||
544 | 548 | ||
@@ -716,7 +720,9 @@ static int unix_autobind(struct socket *sock) | |||
716 | int err; | 720 | int err; |
717 | unsigned int retries = 0; | 721 | unsigned int retries = 0; |
718 | 722 | ||
719 | mutex_lock(&u->readlock); | 723 | err = mutex_lock_interruptible(&u->readlock); |
724 | if (err) | ||
725 | return err; | ||
720 | 726 | ||
721 | err = 0; | 727 | err = 0; |
722 | if (u->addr) | 728 | if (u->addr) |
@@ -875,7 +881,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
875 | goto out; | 881 | goto out; |
876 | addr_len = err; | 882 | addr_len = err; |
877 | 883 | ||
878 | mutex_lock(&u->readlock); | 884 | err = mutex_lock_interruptible(&u->readlock); |
885 | if (err) | ||
886 | goto out; | ||
879 | 887 | ||
880 | err = -EINVAL; | 888 | err = -EINVAL; |
881 | if (u->addr) | 889 | if (u->addr) |