diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-06 19:15:03 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-06 19:15:03 -0500 |
commit | 51cb67c0b0fcb91581b15bd2e85f29af4d4b2df6 (patch) | |
tree | 2696e99342df5dedaa2226d7d72c4ff1668ee120 /net | |
parent | ee9a7d2cb0cf1a1498478bc923d911f3d9c910ac (diff) | |
parent | 8b8a321ff72c785ed5e8b4cf6eda20b35d427390 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
"As usual, there are a couple straggler bug fixes:
1) qlcnic_alloc_mbx_args() error returns are not checked in qlcnic
driver. Fix from Insu Yun.
2) SKB refcounting bug in connector, from Florian Westphal.
3) vrf_get_saddr() has to propagate fib_lookup() errors to it's
callers, from David Ahern.
4) Fix AF_UNIX splice/bind deadlock, from Rainer Weikusat.
5) qdisc_rcu_free() fails to free the per-cpu qstats. Fix from John
Fastabend.
6) vmxnet3 driver passes wrong page to dma_map_page(), fix from
Shrikrishna Khare.
7) Don't allow zero cwnd in tcp_cwnd_reduction(), from Yuchung Cheng"
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
tcp: fix zero cwnd in tcp_cwnd_reduction
Driver: Vmxnet3: Fix regression caused by 5738a09
net: qmi_wwan: Add WeTelecom-WPD600N
mkiss: fix scribble on freed memory
net: possible use after free in dst_release
net: sched: fix missing free per cpu on qstats
ARM: net: bpf: fix zero right shift
6pack: fix free memory scribbles
net: filter: make JITs zero A for SKF_AD_ALU_XOR_X
bridge: Only call /sbin/bridge-stp for the initial network namespace
af_unix: Fix splice-bind deadlock
net: Propagate lookup failure in l3mdev_get_saddr to caller
r8152: add reset_resume function
connector: bump skb->users before callback invocation
cxgb4: correctly handling failed allocation
qlcnic: correctly handle qlcnic_alloc_mbx_args
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_stp_if.c | 5 | ||||
-rw-r--r-- | net/core/dst.c | 3 | ||||
-rw-r--r-- | net/ipv4/raw.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 3 | ||||
-rw-r--r-- | net/ipv4/udp.c | 7 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 4 | ||||
-rw-r--r-- | net/unix/af_unix.c | 66 |
7 files changed, 62 insertions, 33 deletions
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 12045dea276c..8a7ada8bb947 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -142,7 +142,10 @@ static void br_stp_start(struct net_bridge *br) | |||
142 | char *envp[] = { NULL }; | 142 | char *envp[] = { NULL }; |
143 | struct net_bridge_port *p; | 143 | struct net_bridge_port *p; |
144 | 144 | ||
145 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | 145 | if (net_eq(dev_net(br->dev), &init_net)) |
146 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | ||
147 | else | ||
148 | r = -ENOENT; | ||
146 | 149 | ||
147 | spin_lock_bh(&br->lock); | 150 | spin_lock_bh(&br->lock); |
148 | 151 | ||
diff --git a/net/core/dst.c b/net/core/dst.c index e6dc77252fe9..a1656e3b8d72 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -301,12 +301,13 @@ void dst_release(struct dst_entry *dst) | |||
301 | { | 301 | { |
302 | if (dst) { | 302 | if (dst) { |
303 | int newrefcnt; | 303 | int newrefcnt; |
304 | unsigned short nocache = dst->flags & DST_NOCACHE; | ||
304 | 305 | ||
305 | newrefcnt = atomic_dec_return(&dst->__refcnt); | 306 | newrefcnt = atomic_dec_return(&dst->__refcnt); |
306 | if (unlikely(newrefcnt < 0)) | 307 | if (unlikely(newrefcnt < 0)) |
307 | net_warn_ratelimited("%s: dst:%p refcnt:%d\n", | 308 | net_warn_ratelimited("%s: dst:%p refcnt:%d\n", |
308 | __func__, dst, newrefcnt); | 309 | __func__, dst, newrefcnt); |
309 | if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE)) | 310 | if (!newrefcnt && unlikely(nocache)) |
310 | call_rcu(&dst->rcu_head, dst_destroy_rcu); | 311 | call_rcu(&dst->rcu_head, dst_destroy_rcu); |
311 | } | 312 | } |
312 | } | 313 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 63e5be0abd86..bc35f1842512 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -601,8 +601,11 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
601 | (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), | 601 | (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), |
602 | daddr, saddr, 0, 0); | 602 | daddr, saddr, 0, 0); |
603 | 603 | ||
604 | if (!saddr && ipc.oif) | 604 | if (!saddr && ipc.oif) { |
605 | l3mdev_get_saddr(net, ipc.oif, &fl4); | 605 | err = l3mdev_get_saddr(net, ipc.oif, &fl4); |
606 | if (err < 0) | ||
607 | goto done; | ||
608 | } | ||
606 | 609 | ||
607 | if (!inet->hdrincl) { | 610 | if (!inet->hdrincl) { |
608 | rfv.msg = msg; | 611 | rfv.msg = msg; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2d656eef7f8e..d4c51158470f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2478,6 +2478,9 @@ static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, | |||
2478 | int newly_acked_sacked = prior_unsacked - | 2478 | int newly_acked_sacked = prior_unsacked - |
2479 | (tp->packets_out - tp->sacked_out); | 2479 | (tp->packets_out - tp->sacked_out); |
2480 | 2480 | ||
2481 | if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) | ||
2482 | return; | ||
2483 | |||
2481 | tp->prr_delivered += newly_acked_sacked; | 2484 | tp->prr_delivered += newly_acked_sacked; |
2482 | if (delta < 0) { | 2485 | if (delta < 0) { |
2483 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + | 2486 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 0c7b0e61b917..c43890848641 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1025,8 +1025,11 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
1025 | flow_flags, | 1025 | flow_flags, |
1026 | faddr, saddr, dport, inet->inet_sport); | 1026 | faddr, saddr, dport, inet->inet_sport); |
1027 | 1027 | ||
1028 | if (!saddr && ipc.oif) | 1028 | if (!saddr && ipc.oif) { |
1029 | l3mdev_get_saddr(net, ipc.oif, fl4); | 1029 | err = l3mdev_get_saddr(net, ipc.oif, fl4); |
1030 | if (err < 0) | ||
1031 | goto out; | ||
1032 | } | ||
1030 | 1033 | ||
1031 | security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); | 1034 | security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); |
1032 | rt = ip_route_output_flow(net, fl4, sk); | 1035 | rt = ip_route_output_flow(net, fl4, sk); |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index e82a1ad80aa5..16bc83b2842a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -658,8 +658,10 @@ static void qdisc_rcu_free(struct rcu_head *head) | |||
658 | { | 658 | { |
659 | struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head); | 659 | struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head); |
660 | 660 | ||
661 | if (qdisc_is_percpu_stats(qdisc)) | 661 | if (qdisc_is_percpu_stats(qdisc)) { |
662 | free_percpu(qdisc->cpu_bstats); | 662 | free_percpu(qdisc->cpu_bstats); |
663 | free_percpu(qdisc->cpu_qstats); | ||
664 | } | ||
663 | 665 | ||
664 | kfree((char *) qdisc - qdisc->padded); | 666 | kfree((char *) qdisc - qdisc->padded); |
665 | } | 667 | } |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index a4631477cedf..ef05cd9403d4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -953,32 +953,20 @@ fail: | |||
953 | return NULL; | 953 | return NULL; |
954 | } | 954 | } |
955 | 955 | ||
956 | static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) | 956 | static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode, |
957 | struct path *res) | ||
957 | { | 958 | { |
958 | struct dentry *dentry; | 959 | int err; |
959 | struct path path; | ||
960 | int err = 0; | ||
961 | /* | ||
962 | * Get the parent directory, calculate the hash for last | ||
963 | * component. | ||
964 | */ | ||
965 | dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | ||
966 | err = PTR_ERR(dentry); | ||
967 | if (IS_ERR(dentry)) | ||
968 | return err; | ||
969 | 960 | ||
970 | /* | 961 | err = security_path_mknod(path, dentry, mode, 0); |
971 | * All right, let's create it. | ||
972 | */ | ||
973 | err = security_path_mknod(&path, dentry, mode, 0); | ||
974 | if (!err) { | 962 | if (!err) { |
975 | err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0); | 963 | err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0); |
976 | if (!err) { | 964 | if (!err) { |
977 | res->mnt = mntget(path.mnt); | 965 | res->mnt = mntget(path->mnt); |
978 | res->dentry = dget(dentry); | 966 | res->dentry = dget(dentry); |
979 | } | 967 | } |
980 | } | 968 | } |
981 | done_path_create(&path, dentry); | 969 | |
982 | return err; | 970 | return err; |
983 | } | 971 | } |
984 | 972 | ||
@@ -989,10 +977,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
989 | struct unix_sock *u = unix_sk(sk); | 977 | struct unix_sock *u = unix_sk(sk); |
990 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; | 978 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
991 | char *sun_path = sunaddr->sun_path; | 979 | char *sun_path = sunaddr->sun_path; |
992 | int err; | 980 | int err, name_err; |
993 | unsigned int hash; | 981 | unsigned int hash; |
994 | struct unix_address *addr; | 982 | struct unix_address *addr; |
995 | struct hlist_head *list; | 983 | struct hlist_head *list; |
984 | struct path path; | ||
985 | struct dentry *dentry; | ||
996 | 986 | ||
997 | err = -EINVAL; | 987 | err = -EINVAL; |
998 | if (sunaddr->sun_family != AF_UNIX) | 988 | if (sunaddr->sun_family != AF_UNIX) |
@@ -1008,14 +998,34 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1008 | goto out; | 998 | goto out; |
1009 | addr_len = err; | 999 | addr_len = err; |
1010 | 1000 | ||
1001 | name_err = 0; | ||
1002 | dentry = NULL; | ||
1003 | if (sun_path[0]) { | ||
1004 | /* Get the parent directory, calculate the hash for last | ||
1005 | * component. | ||
1006 | */ | ||
1007 | dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | ||
1008 | |||
1009 | if (IS_ERR(dentry)) { | ||
1010 | /* delay report until after 'already bound' check */ | ||
1011 | name_err = PTR_ERR(dentry); | ||
1012 | dentry = NULL; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1011 | err = mutex_lock_interruptible(&u->readlock); | 1016 | err = mutex_lock_interruptible(&u->readlock); |
1012 | if (err) | 1017 | if (err) |
1013 | goto out; | 1018 | goto out_path; |
1014 | 1019 | ||
1015 | err = -EINVAL; | 1020 | err = -EINVAL; |
1016 | if (u->addr) | 1021 | if (u->addr) |
1017 | goto out_up; | 1022 | goto out_up; |
1018 | 1023 | ||
1024 | if (name_err) { | ||
1025 | err = name_err == -EEXIST ? -EADDRINUSE : name_err; | ||
1026 | goto out_up; | ||
1027 | } | ||
1028 | |||
1019 | err = -ENOMEM; | 1029 | err = -ENOMEM; |
1020 | addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); | 1030 | addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); |
1021 | if (!addr) | 1031 | if (!addr) |
@@ -1026,11 +1036,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1026 | addr->hash = hash ^ sk->sk_type; | 1036 | addr->hash = hash ^ sk->sk_type; |
1027 | atomic_set(&addr->refcnt, 1); | 1037 | atomic_set(&addr->refcnt, 1); |
1028 | 1038 | ||
1029 | if (sun_path[0]) { | 1039 | if (dentry) { |
1030 | struct path path; | 1040 | struct path u_path; |
1031 | umode_t mode = S_IFSOCK | | 1041 | umode_t mode = S_IFSOCK | |
1032 | (SOCK_INODE(sock)->i_mode & ~current_umask()); | 1042 | (SOCK_INODE(sock)->i_mode & ~current_umask()); |
1033 | err = unix_mknod(sun_path, mode, &path); | 1043 | err = unix_mknod(dentry, &path, mode, &u_path); |
1034 | if (err) { | 1044 | if (err) { |
1035 | if (err == -EEXIST) | 1045 | if (err == -EEXIST) |
1036 | err = -EADDRINUSE; | 1046 | err = -EADDRINUSE; |
@@ -1038,9 +1048,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1038 | goto out_up; | 1048 | goto out_up; |
1039 | } | 1049 | } |
1040 | addr->hash = UNIX_HASH_SIZE; | 1050 | addr->hash = UNIX_HASH_SIZE; |
1041 | hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1); | 1051 | hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1); |
1042 | spin_lock(&unix_table_lock); | 1052 | spin_lock(&unix_table_lock); |
1043 | u->path = path; | 1053 | u->path = u_path; |
1044 | list = &unix_socket_table[hash]; | 1054 | list = &unix_socket_table[hash]; |
1045 | } else { | 1055 | } else { |
1046 | spin_lock(&unix_table_lock); | 1056 | spin_lock(&unix_table_lock); |
@@ -1063,6 +1073,10 @@ out_unlock: | |||
1063 | spin_unlock(&unix_table_lock); | 1073 | spin_unlock(&unix_table_lock); |
1064 | out_up: | 1074 | out_up: |
1065 | mutex_unlock(&u->readlock); | 1075 | mutex_unlock(&u->readlock); |
1076 | out_path: | ||
1077 | if (dentry) | ||
1078 | done_path_create(&path, dentry); | ||
1079 | |||
1066 | out: | 1080 | out: |
1067 | return err; | 1081 | return err; |
1068 | } | 1082 | } |