Skip to contentSkip to conversation

3.10.23-stable review

PATCH In review Greg Kroah-Hartman 3 participants 62 messages Dec 6, 2013 – Dec 7, 2013

Subsystems (2)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 3.10.23-stable review

This is the start of the stable review cycle for the 3.10.23 release. There are 58 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Sun Dec 8 21:47:53 UTC 2013. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v3.0/stable-review/patch-3.10.23-rc1.gz

and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>

    Linux 3.10.23-rc1

Pierre Ossman <[email protected]>
drm/radeon/audio: correct ACR table

Pierre Ossman <[email protected]>
drm/radeon/audio: improve ACR calculation

Miroslav Lichvar <[email protected]>
ntp: Make periodic RTC update more reliable

Tomoki Sekiyama <[email protected]>

    elevator: acquire q->sysfs_lock in elevator_change()

Tomoki Sekiyama <[email protected]>
elevator: Fix a race in elevator switching and md device initialization

Neil Horman <[email protected]>
iommu: Remove stack trace from broken irq remapping warning

Julian Stecklina <[email protected]>
iommu/vt-d: Fixed interaction of VFIO_IOMMU_MAP_DMA with IOMMU address limits

Simon Wood <[email protected]>
HID: lg: fix Report Descriptor for Logitech MOMO Force (Black)

Sasha Levin <[email protected]>
video: kyro: fix incorrect sizes when copying to userspace

Mel Gorman <[email protected]>
mm: numa: return the number of base pages altered by protection changes

Stephen Boyd <[email protected]>
clockevents: Prefer CPU local devices over global devices

Thomas Gleixner <[email protected]>
clockevents: Split out selection logic

Thomas Gleixner <[email protected]>
clockevents: Add module refcount

Thomas Gleixner <[email protected]>
clockevents: Get rid of the notifier chain

Mateusz Guzik <[email protected]>
aio: restore locking of ioctx list on removal

KOBAYASHI Yoshitake <[email protected]>
mmc: block: fix a bug of error handling in MMC driver

Dwight Engen <[email protected]>
xfs: add capability check to free eofblocks ioctl

Eric Dumazet <[email protected]>
tcp: gso: fix truesize tracking

fan.du <[email protected]>
{pktgen, xfrm} Update IPv4 header total len and checksum after tranformation

Hannes Frederic Sowa <[email protected]>
ipv6: fix possible seqlock deadlock in ip6_finish_output2

Eric Dumazet <[email protected]>
inet: fix possible seqlock deadlocks

Jiri Pirko <[email protected]>
team: fix master carrier set when user linkup is enabled

Shawn Landden <[email protected]>
net: update consumers of MSG_MORE to recognize MSG_SENDPAGE_NOTLAST

Yang Yingliang <[email protected]>
net: 8139cp: fix a BUG_ON triggered by wrong bytes_compl

David Chang <[email protected]>
r8169: check ALDPS bit and disable it if enabled for the 8168g

Veaceslav Falico <[email protected]>
af_packet: block BH in prb_shutdown_retire_blk_timer()

Daniel Borkmann <[email protected]>
packet: fix use after free race in send path when dev is released

Ding Tianhong <[email protected]>
bridge: flush br's address entry in fdb when remove the bridge dev

Vlad Yasevich <[email protected]>
net: core: Always propagate flag changes to interfaces

Alexei Starovoitov <[email protected]>
ipv4: fix race in concurrent ip_route_input_slow()

Andrey Vagin <[email protected]>
tcp: don't update snd_nxt, when a socket is switched from repair mode

Ying Xue <[email protected]>
atm: idt77252: fix dev refcnt leak

fan.du <[email protected]>
xfrm: Release dst if this dst is improper for vti tunnel

Jiri Pirko <[email protected]>
netfilter: push reasm skb through instead of original frag skbs

Jiri Pirko <[email protected]>
ip6_output: fragment outgoing reassembled skb properly

Hannes Frederic Sowa <[email protected]>
ipv6: fix leaking uninitialized port number of offender sockaddr

Dan Carpenter <[email protected]>

    net: clamp ->msg_namelen instead of returning an error

Hannes Frederic Sowa <[email protected]>

    inet: fix addr_len/msg->msg_namelen assignment in recv_error and rxpmtu functions

Hannes Frederic Sowa <[email protected]>
net: add BUG_ON if kernel advertises msg_namelen > sizeof(struct sockaddr_storage)

Hannes Frederic Sowa <[email protected]>
net: rework recvmsg handler msg_name and msg_namelen logic

Hannes Frederic Sowa <[email protected]>
inet: prevent leakage of uninitialized memory to user in recv syscalls

Eric Dumazet <[email protected]>
ipv4: fix possible seqlock deadlock

Chris Metcalf <[email protected]>
connector: improved unaligned access error fix

Dan Carpenter <[email protected]>
isdnloop: use strlcpy() instead of strcpy()

Eric Dumazet <[email protected]>
net-tcp: fix panic in tcp_fastopen_cache_set()

Nikolay Aleksandrov <[email protected]>
bonding: fix two race conditions in bond_store_updelay/downdelay

Eric Dumazet <[email protected]>
tcp: tsq: restore minimal amount of queueing

Jason Wang <[email protected]>
macvtap: limit head length of skb allocated

Jason Wang <[email protected]>
tuntap: limit head length of skb allocated

Jukka Rissanen <[email protected]>
6lowpan: Uncompression of traffic class field was incorrect

Felix Fietkau <[email protected]>
usbnet: fix status interrupt urb handling

Veaceslav Falico <[email protected]>
bonding: don't permit to use ARP monitoring in 802.3ad mode

Daniel Borkmann <[email protected]>
random32: fix off-by-one in seeding requirement

Hannes Frederic Sowa <[email protected]>
ipv6: protect for_each_sk_fl_rcu in mem_check with rcu_read_lock_bh

Duan Jiong <[email protected]>
ipv6: use rt6_get_dflt_router to get default router in rt6_route_rcv

Andreas Henriksson <[email protected]>
net: Fix "ip rule delete table 256"

Amir Vadai <[email protected]>
net/mlx4_en: Fixed crash when port type is changed

Hannes Frederic Sowa <[email protected]>
ipv6: fix headroom calculation in udp6_ufo_fragment

-------------

Diffstat:

 Documentation/networking/ip-sysctl.txt         |   3 -
 Makefile                                       |   4 +-
 block/blk-core.c                               |  10 ++-
 block/elevator.c                               |  22 ++++-
 crypto/algif_hash.c                            |   5 +-
 crypto/algif_skcipher.c                        |   4 +-
 drivers/atm/idt77252.c                         |   2 +-
 drivers/connector/cn_proc.c                    |  72 ++++++++++-------
 drivers/gpu/drm/radeon/r600_hdmi.c             |  74 +++++++++++------
 drivers/hid/hid-lg.c                           |  58 ++++++++++++++
 drivers/iommu/intel-iommu.c                    |   6 +-
 drivers/iommu/intel_irq_remapping.c            |  13 +--
 drivers/isdn/isdnloop/isdnloop.c               |   8 +-
 drivers/isdn/mISDN/socket.c                    |  13 +--
 drivers/mmc/card/block.c                       |  45 ++++++++++-
 drivers/net/bonding/bond_sysfs.c               |  11 ++-
 drivers/net/ethernet/mellanox/mlx4/en_main.c   |   8 +-
 drivers/net/ethernet/realtek/8139cp.c          |   5 +-
 drivers/net/ethernet/realtek/r8169.c           |   5 ++
 drivers/net/macvtap.c                          |   8 +-
 drivers/net/ppp/pppoe.c                        |   2 -
 drivers/net/team/team.c                        |   4 +
 drivers/net/tun.c                              |  10 ++-
 drivers/net/usb/usbnet.c                       |   3 -
 drivers/video/kyro/fbdev.c                     |   6 +-
 fs/aio.c                                       |  10 ++-
 fs/xfs/xfs_ioctl.c                             |   6 ++
 include/linux/clockchips.h                     |   4 +-
 include/linux/net.h                            |   8 ++
 include/linux/random.h                         |   6 +-
 include/linux/skbuff.h                         |  32 --------
 include/linux/vm_event_item.h                  |   1 +
 include/net/ip.h                               |   2 +-
 include/net/ip_vs.h                            |  32 +-------
 include/net/ipv6.h                             |   6 +-
 include/net/netfilter/ipv6/nf_defrag_ipv6.h    |   5 +-
 kernel/time/clockevents.c                      |  36 +--------
 kernel/time/ntp.c                              |   3 +-
 kernel/time/tick-broadcast.c                   |  33 ++++++--
 kernel/time/tick-common.c                      | 106 ++++++++++++-------------
 kernel/time/tick-internal.h                    |   7 +-
 lib/random32.c                                 |  14 ++--
 mm/mprotect.c                                  |   7 +-
 mm/vmstat.c                                    |   1 +
 net/appletalk/ddp.c                            |  16 ++--
 net/atm/common.c                               |   2 -
 net/ax25/af_ax25.c                             |   4 +-
 net/bluetooth/af_bluetooth.c                   |   4 -
 net/bluetooth/hci_sock.c                       |   2 -
 net/bluetooth/rfcomm/sock.c                    |   1 -
 net/bluetooth/sco.c                            |   1 -
 net/bridge/br_if.c                             |   2 +
 net/caif/caif_socket.c                         |   4 -
 net/compat.c                                   |   5 +-
 net/core/dev.c                                 |   2 +-
 net/core/fib_rules.c                           |   3 +-
 net/core/iovec.c                               |   3 +-
 net/core/pktgen.c                              |   7 ++
 net/core/skbuff.c                              |   3 -
 net/ieee802154/6lowpan.c                       |   4 +-
 net/ieee802154/dgram.c                         |   3 +-
 net/ipv4/datagram.c                            |   2 +-
 net/ipv4/ip_sockglue.c                         |   3 +-
 net/ipv4/ip_vti.c                              |   1 +
 net/ipv4/ping.c                                |  13 ++-
 net/ipv4/raw.c                                 |   6 +-
 net/ipv4/route.c                               |   8 +-
 net/ipv4/tcp.c                                 |  19 ++---
 net/ipv4/tcp_ipv4.c                            |   2 +-
 net/ipv4/tcp_metrics.c                         |   5 +-
 net/ipv4/tcp_output.c                          |   7 +-
 net/ipv4/udp.c                                 |  14 ++--
 net/ipv6/datagram.c                            |   8 +-
 net/ipv6/ip6_flowlabel.c                       |   2 +
 net/ipv6/ip6_output.c                          |   7 +-
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |  54 +------------
 net/ipv6/netfilter/nf_conntrack_reasm.c        |  19 +----
 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c      |   7 +-
 net/ipv6/raw.c                                 |   8 +-
 net/ipv6/route.c                               |   7 +-
 net/ipv6/udp.c                                 |   9 +--
 net/ipv6/udp_offload.c                         |   2 +-
 net/ipx/af_ipx.c                               |   3 +-
 net/irda/af_irda.c                             |   4 -
 net/iucv/af_iucv.c                             |   2 -
 net/key/af_key.c                               |   1 -
 net/l2tp/l2tp_ip.c                             |   4 +-
 net/l2tp/l2tp_ip6.c                            |   2 +-
 net/l2tp/l2tp_ppp.c                            |   2 -
 net/llc/af_llc.c                               |   2 -
 net/netfilter/ipvs/ip_vs_core.c                |  55 +------------
 net/netfilter/ipvs/ip_vs_pe_sip.c              |   8 +-
 net/netlink/af_netlink.c                       |   2 -
 net/netrom/af_netrom.c                         |   3 +-
 net/nfc/llcp_sock.c                            |   2 -
 net/nfc/rawsock.c                              |   2 -
 net/packet/af_packet.c                         |  95 ++++++++++++----------
 net/packet/internal.h                          |   1 +
 net/phonet/datagram.c                          |   9 +--
 net/rds/recv.c                                 |   2 -
 net/rose/af_rose.c                             |   8 +-
 net/rxrpc/ar-recvmsg.c                         |   9 ++-
 net/socket.c                                   |  24 +++---
 net/tipc/socket.c                              |   6 --
 net/unix/af_unix.c                             |   5 --
 net/vmw_vsock/af_vsock.c                       |   2 -
 net/vmw_vsock/vmci_transport.c                 |   2 -
 net/x25/af_x25.c                               |   3 +-
 108 files changed, 616 insertions(+), 631 deletions(-)
author maintainer
#1 lore raw

PATCH 1/58 ipv6: fix headroom calculation in udp6_ufo_fragment

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hannes Frederic Sowa <[email protected]>

[ Upstream commit 0e033e04c2678dbbe74a46b23fffb7bb918c288e ]

Commit 1e2bd517c108816220f262d7954b697af03b5f9c ("udp6: Fix udp fragmentation for tunnel traffic.") changed the calculation if there is enough space to include a fragment header in the skb from a skb->mac_header dervived one to skb_headroom. Because we already peeled off the skb to transport_header this is wrong. Change this back to check if we have enough room before the mac_header.

This fixes a panic Saran Neti reported. He used the tbf scheduler which skb_gso_segments the skb. The offsets get negative and we panic in memcpy because the skb was erroneously not expanded at the head.

---
 net/ipv6/udp_offload.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/udp_offload.c +1 -1
@@ -85,7 +85,7 @@ static struct sk_buff *udp6_ufo_fragment
 
 	/* Check if there is enough headroom to insert fragment header. */
 	tnl_hlen = skb_tnl_header_len(skb);
-	if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) {
+	if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) {
 		if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz))
 			goto out;
 	}
author maintainer
#2 lore raw

PATCH 2/58 net/mlx4_en: Fixed crash when port type is changed

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Amir Vadai <[email protected]>

[ Upstream commit 1ec4864b10171b0691ee196d7006ae56d2c153f2 ]

timecounter_init() was was called only after first potential timecounter_read().
Moved mlx4_en_init_timestamp() before mlx4_en_init_netdev()

---
 drivers/net/ethernet/mellanox/mlx4/en_main.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/mellanox/mlx4/en_main.c +4 -4
@@ -264,6 +264,10 @@ static void *mlx4_en_add(struct mlx4_dev
 	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
 		mdev->port_cnt++;
 
+	/* Initialize time stamp mechanism */
+	if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
+		mlx4_en_init_timestamp(mdev);
+
 	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
 		if (!dev->caps.comp_pool) {
 			mdev->profile.prof[i].rx_ring_num =
@@ -301,10 +305,6 @@ static void *mlx4_en_add(struct mlx4_dev
 			mdev->pndev[i] = NULL;
 	}
 
-	/* Initialize time stamp mechanism */
-	if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
-		mlx4_en_init_timestamp(mdev);
-
 	return mdev;
 
 err_mr:
author maintainer
#3 lore raw

PATCH 3/58 net: Fix "ip rule delete table 256"

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andreas Henriksson <[email protected]>

[ Upstream commit 13eb2ab2d33c57ebddc57437a7d341995fc9138c ]

When trying to delete a table >= 256 using iproute2 the local table will be deleted.
The table id is specified as a netlink attribute when it needs more then 8 bits and iproute2 then sets the table field to RT_TABLE_UNSPEC (0). Preconditions to matching the table id in the rule delete code doesn't seem to take the "table id in netlink attribute" into condition so the frh_get_table helper function never gets to do its job when matching against current rule.
Use the helper function twice instead of peaking at the table value directly.

Originally reported at: http://bugs.debian.org/724783

---
 net/core/fib_rules.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/core/fib_rules.c +2 -1
@@ -445,7 +445,8 @@ static int fib_nl_delrule(struct sk_buff
 		if (frh->action && (frh->action != rule->action))
 			continue;
 
-		if (frh->table && (frh_get_table(frh, tb) != rule->table))
+		if (frh_get_table(frh, tb) &&
+		    (frh_get_table(frh, tb) != rule->table))
 			continue;
 
 		if (tb[FRA_PRIORITY] &&
author maintainer
#4 lore raw

PATCH 4/58 ipv6: use rt6_get_dflt_router to get default router in rt6_route_rcv

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Duan Jiong <[email protected]>

[ Upstream commit f104a567e673f382b09542a8dc3500aa689957b4 ]

As the rfc 4191 said, the Router Preference and Lifetime values in a ::/0 Route Information Option should override the preference and lifetime values in the Router Advertisement header. But when the kernel deals with a ::/0 Route Information Option, the rt6_get_route_info() always return NULL, that means that overriding will not happen, because those default routers were added without flag RTF_ROUTEINFO in rt6_add_dflt_router().

In order to deal with that condition, we should call rt6_get_dflt_router when the prefix length is 0.

---
 net/ipv6/route.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
net/ipv6/route.c +5 -2
@@ -728,8 +728,11 @@ int rt6_route_rcv(struct net_device *dev
 		prefix = &prefix_buf;
 	}
 
-	rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr,
-				dev->ifindex);
+	if (rinfo->prefix_len == 0)
+		rt = rt6_get_dflt_router(gwaddr, dev);
+	else
+		rt = rt6_get_route_info(net, prefix, rinfo->prefix_len,
+					gwaddr, dev->ifindex);
 
 	if (rt && !lifetime) {
 		ip6_del_rt(rt);
author maintainer
#5 lore raw

PATCH 5/58 ipv6: protect for_each_sk_fl_rcu in mem_check with rcu_read_lock_bh

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hannes Frederic Sowa <[email protected]>

[ Upstream commit f8c31c8f80dd882f7eb49276989a4078d33d67a7 ]

Fixes a suspicious rcu derference warning.

---
 net/ipv6/ip6_flowlabel.c |    2 ++
 1 file changed, 2 insertions(+)
net/ipv6/ip6_flowlabel.c +2 -0
@@ -453,8 +453,10 @@ static int mem_check(struct sock *sk)
 	if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK)
 		return 0;
 
+	rcu_read_lock_bh();
 	for_each_sk_fl_rcu(np, sfl)
 		count++;
+	rcu_read_unlock_bh();
 
 	if (room <= 0 ||
 	    ((count >= FL_MAX_PER_SOCK ||
author maintainer
#6 lore raw

PATCH 6/58 random32: fix off-by-one in seeding requirement

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel Borkmann <[email protected]>

[ Upstream commit 51c37a70aaa3f95773af560e6db3073520513912 ]

For properly initialising the Tausworthe generator [1], we have a strict seeding requirement, that is, s1 > 1, s2 > 7, s3 > 15.

Commit 697f8d0348 ("random32: seeding improvement") introduced a __seed() function that imposes boundary checks proposed by the errata paper [2] to properly ensure above conditions.

However, we're off by one, as the function is implemented as:
"return (x < m) ? x + m : x;", and called with __seed(X, 1), __seed(X, 7), __seed(X, 15). Thus, an unwanted seed of 1, 7, 15 would be possible, whereas the lower boundary should actually be of at least 2, 8, 16, just as GSL does. Fix this, as otherwise an initialization with an unwanted seed could have the effect that Tausworthe's PRNG properties cannot not be ensured.

Note that this PRNG is *not* used for cryptography in the kernel.

[1] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
[2] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps

Joint work with Hannes Frederic Sowa.

Fixes 697f8d0348a6 ("random32: seeding improvement")
Cc Stephen Hemminger <[email protected]>
Cc Florian Weimer <[email protected]>
Cc Theodore Ts'o <[email protected]>
---
 include/linux/random.h |    6 +++---
 lib/random32.c         |   14 +++++++-------
 2 files changed, 10 insertions(+), 10 deletions(-)
include/linux/random.h +3 -3
@@ -50,9 +50,9 @@ static inline void prandom_seed_state(st
 {
 	u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
 
-	state->s1 = __seed(i, 1);
-	state->s2 = __seed(i, 7);
-	state->s3 = __seed(i, 15);
+	state->s1 = __seed(i, 2);
+	state->s2 = __seed(i, 8);
+	state->s3 = __seed(i, 16);
 }
 
 #ifdef CONFIG_ARCH_RANDOM
lib/random32.c +7 -7
@@ -141,7 +141,7 @@ void prandom_seed(u32 entropy)
 	 */
 	for_each_possible_cpu (i) {
 		struct rnd_state *state = &per_cpu(net_rand_state, i);
-		state->s1 = __seed(state->s1 ^ entropy, 1);
+		state->s1 = __seed(state->s1 ^ entropy, 2);
 	}
 }
 EXPORT_SYMBOL(prandom_seed);
@@ -158,9 +158,9 @@ static int __init prandom_init(void)
 		struct rnd_state *state = &per_cpu(net_rand_state,i);
 
 #define LCG(x)	((x) * 69069)	/* super-duper LCG */
-		state->s1 = __seed(LCG(i + jiffies), 1);
-		state->s2 = __seed(LCG(state->s1), 7);
-		state->s3 = __seed(LCG(state->s2), 15);
+		state->s1 = __seed(LCG(i + jiffies), 2);
+		state->s2 = __seed(LCG(state->s1), 8);
+		state->s3 = __seed(LCG(state->s2), 16);
 
 		/* "warm it up" */
 		prandom_u32_state(state);
@@ -187,9 +187,9 @@ static int __init prandom_reseed(void)
 		u32 seeds[3];
 
 		get_random_bytes(&seeds, sizeof(seeds));
-		state->s1 = __seed(seeds[0], 1);
-		state->s2 = __seed(seeds[1], 7);
-		state->s3 = __seed(seeds[2], 15);
+		state->s1 = __seed(seeds[0], 2);
+		state->s2 = __seed(seeds[1], 8);
+		state->s3 = __seed(seeds[2], 16);
 
 		/* mix it in */
 		prandom_u32_state(state);
author maintainer
#7 lore raw

PATCH 7/58 bonding: dont permit to use ARP monitoring in 802.3ad mode

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Veaceslav Falico <[email protected]>

[ Upstream commit ec9f1d15db8185f63a2c3143dc1e90ba18541b08 ]

Currently the ARP monitoring is not supported with 802.3ad, and it's prohibited to use it via the module params.

However we still can set it afterwards via sysfs, cause we only check for *LB modes there.

To fix this - add a check for 802.3ad mode in bonding_store_arp_interval.

---
 drivers/net/bonding/bond_sysfs.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/bonding/bond_sysfs.c +3 -2
@@ -537,8 +537,9 @@ static ssize_t bonding_store_arp_interva
 		goto out;
 	}
 	if (bond->params.mode == BOND_MODE_ALB ||
-	    bond->params.mode == BOND_MODE_TLB) {
-		pr_info("%s: ARP monitoring cannot be used with ALB/TLB. Only MII monitoring is supported on %s.\n",
+	    bond->params.mode == BOND_MODE_TLB ||
+	    bond->params.mode == BOND_MODE_8023AD) {
+		pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n",
 			bond->dev->name, bond->dev->name);
 		ret = -EINVAL;
 		goto out;
author maintainer
#8 lore raw

PATCH 8/58 usbnet: fix status interrupt urb handling

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Felix Fietkau <[email protected]>

[ Upstream commit 52f48d0d9aaa621ffa5e08d79da99a3f8c93b848 ]

Since commit 7b0c5f21f348a66de495868b8df0284e8dfd6bbf "sierra_net: keep status interrupt URB active", sierra_net triggers status interrupt polling before the net_device is opened (in order to properly receive the sync message response).

To be able to receive further interrupts, the interrupt urb needs to be re-submitted, so this patch removes the bogus check for netif_running().

---
 drivers/net/usb/usbnet.c |    3 ---
 1 file changed, 3 deletions(-)
drivers/net/usb/usbnet.c +0 -3
@@ -206,9 +206,6 @@ static void intr_complete (struct urb *u
 		break;
 	}
 
-	if (!netif_running (dev->net))
-		return;
-
 	status = usb_submit_urb (urb, GFP_ATOMIC);
 	if (status != 0)
 		netif_err(dev, timer, dev->net,
author maintainer
#9 lore raw

PATCH 9/58 6lowpan: Uncompression of traffic class field was incorrect

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jukka Rissanen <[email protected]>

[ Upstream commit 1188f05497e7bd2f2614b99c54adfbe7413d5749 ]

If priority/traffic class field in IPv6 header is set (seen when using ssh), the uncompression sets the TC and Flow fields incorrectly.

Example:

This is IPv6 header of a sent packet. Note the priority/TC (=1) in the first byte.

00000000: 61 00 00 00 00 2c 06 40 fe 80 00 00 00 00 00 00 00000010: 02 02 72 ff fe c6 42 10 fe 80 00 00 00 00 00 00 00000020: 02 1e ab ff fe 4c 52 57

This gets compressed like this in the sending side

00000000: 72 31 04 06 02 1e ab ff fe 4c 52 57 ec c2 00 16 00000010: aa 2d fe 92 86 4e be c6 ....

In the receiving end, the packet gets uncompressed to this IPv6 header

00000000: 60 06 06 02 00 2a 1e 40 fe 80 00 00 00 00 00 00 00000010: 02 02 72 ff fe c6 42 10 fe 80 00 00 00 00 00 00 00000020: ab ff fe 4c 52 57 ec c2

First four bytes are set incorrectly and we have also lost two bytes from destination address.

The fix is to switch the case values in switch statement when checking the TC field.

---
 net/ieee802154/6lowpan.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/ieee802154/6lowpan.c +2 -2
@@ -862,7 +862,7 @@ lowpan_process_data(struct sk_buff *skb)
 	 * Traffic class carried in-line
 	 * ECN + DSCP (1 byte), Flow Label is elided
 	 */
-	case 1: /* 10b */
+	case 2: /* 10b */
 		if (lowpan_fetch_skb_u8(skb, &tmp))
 			goto drop;
 
@@ -875,7 +875,7 @@ lowpan_process_data(struct sk_buff *skb)
 	 * Flow Label carried in-line
 	 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
 	 */
-	case 2: /* 01b */
+	case 1: /* 01b */
 		if (lowpan_fetch_skb_u8(skb, &tmp))
 			goto drop;
 
author maintainer
#10 lore raw

PATCH 10/58 tuntap: limit head length of skb allocated

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jason Wang <[email protected]>

[ Upstream commit 96f8d9ecf227638c89f98ccdcdd50b569891976c ]

We currently use hdr_len as a hint of head length which is advertised by guest. But when guest advertise a very big value, it can lead to an 64K+ allocating of kmalloc() which has a very high possibility of failure when host memory is fragmented or under heavy stress. The huge hdr_len also reduce the effect of zerocopy or even disable if a gso skb is linearized in guest.

To solves those issues, this patch introduces an upper limit (PAGE_SIZE) of the head, which guarantees an order 0 allocation each time.

---
 drivers/net/tun.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/net/tun.c +9 -1
@@ -1069,6 +1069,7 @@ static ssize_t tun_get_user(struct tun_s
 	struct sk_buff *skb;
 	size_t len = total_len, align = NET_SKB_PAD, linear;
 	struct virtio_net_hdr gso = { 0 };
+	int good_linear;
 	int offset = 0;
 	int copylen;
 	bool zerocopy = false;
@@ -1109,12 +1110,16 @@ static ssize_t tun_get_user(struct tun_s
 			return -EINVAL;
 	}
 
+	good_linear = SKB_MAX_HEAD(align);
+
 	if (msg_control) {
 		/* There are 256 bytes to be copied in skb, so there is
 		 * enough room for skb expand head in case it is used.
 		 * The rest of the buffer is mapped from userspace.
 		 */
 		copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN;
+		if (copylen > good_linear)
+			copylen = good_linear;
 		linear = copylen;
 		if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS)
 			zerocopy = true;
@@ -1122,7 +1127,10 @@ static ssize_t tun_get_user(struct tun_s
 
 	if (!zerocopy) {
 		copylen = len;
-		linear = gso.hdr_len;
+		if (gso.hdr_len > good_linear)
+			linear = good_linear;
+		else
+			linear = gso.hdr_len;
 	}
 
 	skb = tun_alloc_skb(tfile, align, copylen, linear, noblock);
author maintainer
#11 lore raw

PATCH 11/58 macvtap: limit head length of skb allocated

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jason Wang <[email protected]>

[ Upstream commit 16a3fa28630331e28208872fa5341ce210b901c7 ]

We currently use hdr_len as a hint of head length which is advertised by guest. But when guest advertise a very big value, it can lead to an 64K+ allocating of kmalloc() which has a very high possibility of failure when host memory is fragmented or under heavy stress. The huge hdr_len also reduce the effect of zerocopy or even disable if a gso skb is linearized in guest.

To solves those issues, this patch introduces an upper limit (PAGE_SIZE) of the head, which guarantees an order 0 allocation each time.

---
 drivers/net/macvtap.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/net/macvtap.c +7 -1
@@ -661,6 +661,7 @@ static ssize_t macvtap_get_user(struct m
 				const struct iovec *iv, unsigned long total_len,
 				size_t count, int noblock)
 {
+	int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN);
 	struct sk_buff *skb;
 	struct macvlan_dev *vlan;
 	unsigned long len = total_len;
@@ -703,6 +704,8 @@ static ssize_t macvtap_get_user(struct m
 
 	if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) {
 		copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN;
+		if (copylen > good_linear)
+			copylen = good_linear;
 		linear = copylen;
 		if (iov_pages(iv, vnet_hdr_len + copylen, count)
 		    <= MAX_SKB_FRAGS)
@@ -711,7 +714,10 @@ static ssize_t macvtap_get_user(struct m
 
 	if (!zerocopy) {
 		copylen = len;
-		linear = vnet_hdr.hdr_len;
+		if (vnet_hdr.hdr_len > good_linear)
+			linear = good_linear;
+		else
+			linear = vnet_hdr.hdr_len;
 	}
 
 	skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
author maintainer
#12 lore raw

PATCH 12/58 tcp: tsq: restore minimal amount of queueing

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 98e09386c0ef4dfd48af7ba60ff908f0d525cdee ]

After commit c9eeec26e32e ("tcp: TSQ can use a dynamic limit"), several users reported throughput regressions, notably on mvneta and wifi adapters.

802.11 AMPDU requires a fair amount of queueing to be effective.

This patch partially reverts the change done in tcp_write_xmit() so that the minimal amount is sysctl_tcp_limit_output_bytes.

It also remove the use of this sysctl while building skb stored in write queue, as TSO autosizing does the right thing anyway.

Users with well behaving NICS and correct qdisc (like sch_fq), can then lower the default sysctl_tcp_limit_output_bytes value from 128KB to 8KB.

This new usage of sysctl_tcp_limit_output_bytes permits each driver authors to check how their driver performs when/if the value is set to a minimum of 4KB.

Normally, line rate for a single TCP flow should be possible, but some drivers rely on timers to perform TX completion and too long TX completion delays prevent reaching full throughput.

---
 Documentation/networking/ip-sysctl.txt |    3 ---
 net/ipv4/tcp.c                         |    6 ------
 net/ipv4/tcp_output.c                  |    6 +++++-
 3 files changed, 5 insertions(+), 10 deletions(-)
Documentation/networking/ip-sysctl.txt +0 -3
@@ -571,9 +571,6 @@ tcp_limit_output_bytes - INTEGER
 	typical pfifo_fast qdiscs.
 	tcp_limit_output_bytes limits the number of bytes on qdisc
 	or device to reduce artificial RTT/cwnd and reduce bufferbloat.
-	Note: For GSO/TSO enabled flows, we try to have at least two
-	packets in flight. Reducing tcp_limit_output_bytes might also
-	reduce the size of individual GSO packet (64KB being the max)
 	Default: 131072
 
 tcp_challenge_ack_limit - INTEGER
net/ipv4/tcp.c +0 -6
@@ -807,12 +807,6 @@ static unsigned int tcp_xmit_size_goal(s
 		xmit_size_goal = min_t(u32, gso_size,
 				       sk->sk_gso_max_size - 1 - hlen);
 
-		/* TSQ : try to have at least two segments in flight
-		 * (one in NIC TX ring, another in Qdisc)
-		 */
-		xmit_size_goal = min_t(u32, xmit_size_goal,
-				       sysctl_tcp_limit_output_bytes >> 1);
-
 		xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal);
 
 		/* We try hard to avoid divides here */
net/ipv4/tcp_output.c +5 -1
@@ -1866,8 +1866,12 @@ static bool tcp_write_xmit(struct sock *
 		 *  - better RTT estimation and ACK scheduling
 		 *  - faster recovery
 		 *  - high rates
+		 * Alas, some drivers / subsystems require a fair amount
+		 * of queued bytes to ensure line rate.
+		 * One example is wifi aggregation (802.11 AMPDU)
 		 */
-		limit = max(skb->truesize, sk->sk_pacing_rate >> 10);
+		limit = max_t(unsigned int, sysctl_tcp_limit_output_bytes,
+			      sk->sk_pacing_rate >> 10);
 
 		if (atomic_read(&sk->sk_wmem_alloc) > limit) {
 			set_bit(TSQ_THROTTLED, &tp->tsq_flags);
author maintainer
#13 lore raw

PATCH 13/58 bonding: fix two race conditions in bond_store_updelay/downdelay

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Nikolay Aleksandrov <[email protected]>

[ Upstream commit b869ccfab1e324507fa3596e3e1308444fb68227 ]

This patch fixes two race conditions between bond_store_updelay/downdelay and bond_store_miimon which could lead to division by zero as miimon can be set to 0 while either updelay/downdelay are being set and thus miss the zero check in the beginning, the zero div happens because updelay/downdelay are stored as new_value / bond->params.miimon. Use rtnl to synchronize with miimon setting.

---
 drivers/net/bonding/bond_sysfs.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/net/bonding/bond_sysfs.c +6 -0
@@ -697,6 +697,8 @@ static ssize_t bonding_store_downdelay(s
 	int new_value, ret = count;
 	struct bonding *bond = to_bond(d);
 
+	if (!rtnl_trylock())
+		return restart_syscall();
 	if (!(bond->params.miimon)) {
 		pr_err("%s: Unable to set down delay as MII monitoring is disabled\n",
 		       bond->dev->name);
@@ -730,6 +732,7 @@ static ssize_t bonding_store_downdelay(s
 	}
 
 out:
+	rtnl_unlock();
 	return ret;
 }
 static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR,
@@ -752,6 +755,8 @@ static ssize_t bonding_store_updelay(str
 	int new_value, ret = count;
 	struct bonding *bond = to_bond(d);
 
+	if (!rtnl_trylock())
+		return restart_syscall();
 	if (!(bond->params.miimon)) {
 		pr_err("%s: Unable to set up delay as MII monitoring is disabled\n",
 		       bond->dev->name);
@@ -785,6 +790,7 @@ static ssize_t bonding_store_updelay(str
 	}
 
 out:
+	rtnl_unlock();
 	return ret;
 }
 static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR,
author maintainer
#14 lore raw

PATCH 14/58 net-tcp: fix panic in tcp_fastopen_cache_set()

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit dccf76ca6b626c0c4a4e09bb221adee3270ab0ef ]

We had some reports of crashes using TCP fastopen, and Dave Jones gave a nice stack trace pointing to the error.

Issue is that tcp_get_metrics() should not be called with a NULL dst

Fixes 1fe4c481ba637 ("net-tcp: Fast Open client - cookie cache")
Cc Yuchung Cheng <[email protected]>
---
 net/ipv4/tcp_metrics.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
net/ipv4/tcp_metrics.c +4 -1
@@ -665,10 +665,13 @@ void tcp_fastopen_cache_get(struct sock
 void tcp_fastopen_cache_set(struct sock *sk, u16 mss,
 			    struct tcp_fastopen_cookie *cookie, bool syn_lost)
 {
+	struct dst_entry *dst = __sk_dst_get(sk);
 	struct tcp_metrics_block *tm;
 
+	if (!dst)
+		return;
 	rcu_read_lock();
-	tm = tcp_get_metrics(sk, __sk_dst_get(sk), true);
+	tm = tcp_get_metrics(sk, dst, true);
 	if (tm) {
 		struct tcp_fastopen_metrics *tfom = &tm->tcpm_fastopen;
 
author maintainer
#15 lore raw

PATCH 15/58 isdnloop: use strlcpy() instead of strcpy()

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <[email protected]>

[ Upstream commit f9a23c84486ed350cce7bb1b2828abd1f6658796 ]

These strings come from a copy_from_user() and there is no way to be sure they are NUL terminated.

---
 drivers/isdn/isdnloop/isdnloop.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/isdn/isdnloop/isdnloop.c +5 -3
@@ -1083,8 +1083,10 @@ isdnloop_start(isdnloop_card *card, isdn
 			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 			return -ENOMEM;
 		}
-		for (i = 0; i < 3; i++)
-			strcpy(card->s0num[i], sdef.num[i]);
+		for (i = 0; i < 3; i++) {
+			strlcpy(card->s0num[i], sdef.num[i],
+				sizeof(card->s0num[0]));
+		}
 		break;
 	case ISDN_PTYPE_1TR6:
 		if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95",
@@ -1097,7 +1099,7 @@ isdnloop_start(isdnloop_card *card, isdn
 			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 			return -ENOMEM;
 		}
-		strcpy(card->s0num[0], sdef.num[0]);
+		strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0]));
 		card->s0num[1][0] = '\0';
 		card->s0num[2][0] = '\0';
 		break;
author maintainer
#16 lore raw

PATCH 16/58 connector: improved unaligned access error fix

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chris Metcalf <[email protected]>

[ Upstream commit 1ca1a4cf59ea343a1a70084fe7cc96f37f3cf5b1 ]

In af3e095a1fb4, Erik Jacobsen fixed one type of unaligned access bug for ia64 by converting a 64-bit write to use put_unaligned(). Unfortunately, since gcc will convert a short memset() to a series of appropriately-aligned stores, the problem is now visible again on tilegx, where the memset that zeros out proc_event is converted to three 64-bit stores, causing an unaligned access panic.

A better fix for the original problem is to ensure that proc_event is aligned to 8 bytes here. We can do that relatively easily by arranging to start the struct cn_msg aligned to 8 bytes and then offset by 4 bytes. Doing so means that the immediately following proc_event structure is then correctly aligned to 8 bytes.

The result is that the memset() stores are now aligned, and as an added benefit, we can remove the put_unaligned() calls in the code.

---
 drivers/connector/cn_proc.c |   72 +++++++++++++++++++++++++-------------------
 1 file changed, 42 insertions(+), 30 deletions(-)
drivers/connector/cn_proc.c +42 -30
@@ -32,11 +32,23 @@
 #include <linux/atomic.h>
 #include <linux/pid_namespace.h>
 
-#include <asm/unaligned.h>
-
 #include <linux/cn_proc.h>
 
-#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event))
+/*
+ * Size of a cn_msg followed by a proc_event structure.  Since the
+ * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we
+ * add one 4-byte word to the size here, and then start the actual
+ * cn_msg structure 4 bytes into the stack buffer.  The result is that
+ * the immediately following proc_event structure is aligned to 8 bytes.
+ */
+#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4)
+
+/* See comment above; we test our assumption about sizeof struct cn_msg here. */
+static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer)
+{
+	BUILD_BUG_ON(sizeof(struct cn_msg) != 20);
+	return (struct cn_msg *)(buffer + 4);
+}
 
 static atomic_t proc_event_num_listeners = ATOMIC_INIT(0);
 static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC };
@@ -56,19 +68,19 @@ void proc_fork_connector(struct task_str
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 	struct timespec ts;
 	struct task_struct *parent;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_FORK;
 	rcu_read_lock();
 	parent = rcu_dereference(task->real_parent);
@@ -91,17 +103,17 @@ void proc_exec_connector(struct task_str
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	struct timespec ts;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_EXEC;
 	ev->event_data.exec.process_pid = task->pid;
 	ev->event_data.exec.process_tgid = task->tgid;
@@ -117,14 +129,14 @@ void proc_id_connector(struct task_struc
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 	struct timespec ts;
 	const struct cred *cred;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	ev->what = which_id;
@@ -145,7 +157,7 @@ void proc_id_connector(struct task_struc
 	rcu_read_unlock();
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
@@ -159,17 +171,17 @@ void proc_sid_connector(struct task_stru
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	struct timespec ts;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_SID;
 	ev->event_data.sid.process_pid = task->pid;
 	ev->event_data.sid.process_tgid = task->tgid;
@@ -186,17 +198,17 @@ void proc_ptrace_connector(struct task_s
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	struct timespec ts;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_PTRACE;
 	ev->event_data.ptrace.process_pid  = task->pid;
 	ev->event_data.ptrace.process_tgid = task->tgid;
@@ -221,17 +233,17 @@ void proc_comm_connector(struct task_str
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	struct timespec ts;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_COMM;
 	ev->event_data.comm.process_pid  = task->pid;
 	ev->event_data.comm.process_tgid = task->tgid;
@@ -248,18 +260,18 @@ void proc_coredump_connector(struct task
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_COREDUMP;
 	ev->event_data.coredump.process_pid = task->pid;
 	ev->event_data.coredump.process_tgid = task->tgid;
@@ -275,18 +287,18 @@ void proc_exit_connector(struct task_str
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_EXIT;
 	ev->event_data.exit.process_pid = task->pid;
 	ev->event_data.exit.process_tgid = task->tgid;
@@ -312,18 +324,18 @@ static void cn_proc_ack(int err, int rcv
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	__u8 buffer[CN_PROC_MSG_SIZE];
+	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 
-	msg = (struct cn_msg *)buffer;
+	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	msg->seq = rcvd_seq;
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->cpu = -1;
 	ev->what = PROC_EVENT_NONE;
 	ev->event_data.ack.err = err;
author maintainer
#17 lore raw

PATCH 17/58 ipv4: fix possible seqlock deadlock

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit c9e9042994d37cbc1ee538c500e9da1bb9d1bcdf ]

ip4_datagram_connect() being called from process context, it should use IP_INC_STATS() instead of IP_INC_STATS_BH() otherwise we can deadlock on 32bit arches, or get corruptions of SNMP counters.

Fixes 584bdf8cbdf6 ("[IPV4]: Fix "ipOutNoRoutes" counter error for TCP and UDP")
---
 net/ipv4/datagram.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/datagram.c +1 -1
@@ -57,7 +57,7 @@ int ip4_datagram_connect(struct sock *sk
 	if (IS_ERR(rt)) {
 		err = PTR_ERR(rt);
 		if (err == -ENETUNREACH)
-			IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+			IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
 		goto out;
 	}
 
author maintainer
#18 lore raw

PATCH 18/58 inet: prevent leakage of uninitialized memory to user in recv syscalls

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hannes Frederic Sowa <[email protected]>

[ Upstream commit bceaa90240b6019ed73b49965eac7d167610be69 ]

Only update *addr_len when we actually fill in sockaddr, otherwise we can return uninitialized memory from the stack to the caller in the recvfrom, recvmmsg and recvmsg syscalls. Drop the the (addr_len == NULL) checks because we only get called with a valid addr_len pointer either from sock_common_recvmsg or inet_recvmsg.

If a blocking read waits on a socket which is concurrently shut down we now return zero and set msg_msgnamelen to 0.

---
 net/ieee802154/dgram.c |    3 +--
 net/ipv4/ping.c        |    9 ++++-----
 net/ipv4/raw.c         |    4 +---
 net/ipv4/udp.c         |    7 +------
 net/ipv6/raw.c         |    4 +---
 net/ipv6/udp.c         |    5 +----
 net/l2tp/l2tp_ip.c     |    4 +---
 net/phonet/datagram.c  |    9 ++++-----
 8 files changed, 14 insertions(+), 31 deletions(-)
net/ieee802154/dgram.c +1 -2
@@ -315,9 +315,8 @@ static int dgram_recvmsg(struct kiocb *i
 	if (saddr) {
 		saddr->family = AF_IEEE802154;
 		saddr->addr = mac_cb(skb)->sa;
-	}
-	if (addr_len)
 		*addr_len = sizeof(*saddr);
+	}
 
 	if (flags & MSG_TRUNC)
 		copied = skb->len;
net/ipv4/ping.c +4 -5
@@ -626,7 +626,6 @@ static int ping_recvmsg(struct kiocb *io
 			size_t len, int noblock, int flags, int *addr_len)
 {
 	struct inet_sock *isk = inet_sk(sk);
-	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
 	struct sk_buff *skb;
 	int copied, err;
 
@@ -636,9 +635,6 @@ static int ping_recvmsg(struct kiocb *io
 	if (flags & MSG_OOB)
 		goto out;
 
-	if (addr_len)
-		*addr_len = sizeof(*sin);
-
 	if (flags & MSG_ERRQUEUE)
 		return ip_recv_error(sk, msg, len);
 
@@ -660,11 +656,14 @@ static int ping_recvmsg(struct kiocb *io
 	sock_recv_timestamp(msg, sk, skb);
 
 	/* Copy the address. */
-	if (sin) {
+	if (msg->msg_name) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
+
 		sin->sin_family = AF_INET;
 		sin->sin_port = 0 /* skb->h.uh->source */;
 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+		*addr_len = sizeof(*sin);
 	}
 	if (isk->cmsg_flags)
 		ip_cmsg_recv(msg, skb);
net/ipv4/raw.c +1 -3
@@ -692,9 +692,6 @@ static int raw_recvmsg(struct kiocb *ioc
 	if (flags & MSG_OOB)
 		goto out;
 
-	if (addr_len)
-		*addr_len = sizeof(*sin);
-
 	if (flags & MSG_ERRQUEUE) {
 		err = ip_recv_error(sk, msg, len);
 		goto out;
@@ -722,6 +719,7 @@ static int raw_recvmsg(struct kiocb *ioc
 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
 		sin->sin_port = 0;
 		memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
+		*addr_len = sizeof(*sin);
 	}
 	if (inet->cmsg_flags)
 		ip_cmsg_recv(msg, skb);
net/ipv4/udp.c +1 -6
@@ -1207,12 +1207,6 @@ int udp_recvmsg(struct kiocb *iocb, stru
 	int is_udplite = IS_UDPLITE(sk);
 	bool slow;
 
-	/*
-	 *	Check any passed addresses
-	 */
-	if (addr_len)
-		*addr_len = sizeof(*sin);
-
 	if (flags & MSG_ERRQUEUE)
 		return ip_recv_error(sk, msg, len);
 
@@ -1274,6 +1268,7 @@ try_again:
 		sin->sin_port = udp_hdr(skb)->source;
 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+		*addr_len = sizeof(*sin);
 	}
 	if (inet->cmsg_flags)
 		ip_cmsg_recv(msg, skb);
net/ipv6/raw.c +1 -3
@@ -459,9 +459,6 @@ static int rawv6_recvmsg(struct kiocb *i
 	if (flags & MSG_OOB)
 		return -EOPNOTSUPP;
 
-	if (addr_len)
-		*addr_len=sizeof(*sin6);
-
 	if (flags & MSG_ERRQUEUE)
 		return ipv6_recv_error(sk, msg, len);
 
@@ -500,6 +497,7 @@ static int rawv6_recvmsg(struct kiocb *i
 		sin6->sin6_flowinfo = 0;
 		sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,
 							  IP6CB(skb)->iif);
+		*addr_len = sizeof(*sin6);
 	}
 
 	sock_recv_ts_and_drops(msg, sk, skb);
net/ipv6/udp.c +1 -4
@@ -373,9 +373,6 @@ int udpv6_recvmsg(struct kiocb *iocb, st
 	int is_udp4;
 	bool slow;
 
-	if (addr_len)
-		*addr_len = sizeof(struct sockaddr_in6);
-
 	if (flags & MSG_ERRQUEUE)
 		return ipv6_recv_error(sk, msg, len);
 
@@ -461,7 +458,7 @@ try_again:
 				ipv6_iface_scope_id(&sin6->sin6_addr,
 						    IP6CB(skb)->iif);
 		}
-
+		*addr_len = sizeof(*sin6);
 	}
 	if (is_udp4) {
 		if (inet->cmsg_flags)
net/l2tp/l2tp_ip.c +1 -3
@@ -518,9 +518,6 @@ static int l2tp_ip_recvmsg(struct kiocb
 	if (flags & MSG_OOB)
 		goto out;
 
-	if (addr_len)
-		*addr_len = sizeof(*sin);
-
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
@@ -543,6 +540,7 @@ static int l2tp_ip_recvmsg(struct kiocb
 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
 		sin->sin_port = 0;
 		memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
+		*addr_len = sizeof(*sin);
 	}
 	if (inet->cmsg_flags)
 		ip_cmsg_recv(msg, skb);
net/phonet/datagram.c +4 -5
@@ -139,9 +139,6 @@ static int pn_recvmsg(struct kiocb *iocb
 			MSG_CMSG_COMPAT))
 		goto out_nofree;
 
-	if (addr_len)
-		*addr_len = sizeof(sa);
-
 	skb = skb_recv_datagram(sk, flags, noblock, &rval);
 	if (skb == NULL)
 		goto out_nofree;
@@ -162,8 +159,10 @@ static int pn_recvmsg(struct kiocb *iocb
 
 	rval = (flags & MSG_TRUNC) ? skb->len : copylen;
 
-	if (msg->msg_name != NULL)
-		memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn));
+	if (msg->msg_name != NULL) {
+		memcpy(msg->msg_name, &sa, sizeof(sa));
+		*addr_len = sizeof(sa);
+	}
 
 out:
 	skb_free_datagram(sk, skb);
author maintainer
#19 lore raw

PATCH 19/58 net: rework recvmsg handler msg_name and msg_namelen logic

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hannes Frederic Sowa <[email protected]>

[ Upstream commit f3d3342602f8bcbf37d7c46641cb9bca7618eb1c ]

This patch now always passes msg->msg_namelen as 0. recvmsg handlers must set msg_namelen to the proper size <= sizeof(struct sockaddr_storage) to return msg_name to the user.

This prevents numerous uninitialized memory leaks we had in the recvmsg handlers and makes it harder for new code to accidentally leak uninitialized memory.

Optimize for the case recvfrom is called with NULL as address. We don't need to copy the address at all, so set it to NULL before invoking the recvmsg handler. We can do so, because all the recvmsg handlers must cope with the case a plain read() is called on them. read() also sets msg_name to NULL.

Also document these changes in include/linux/net.h as suggested by David Miller.

Changes since RFC:

Set msg->msg_name = NULL if user specified a NULL in msg_name but had a non-null msg_namelen in verify_iovec/verify_compat_iovec. This doesn't affect sendto as it would bail out earlier while trying to copy-in the address. It also more naturally reflects the logic by the callers of verify_iovec.

With this change in place I could remove "
if (!uaddr || msg_sys->msg_namelen == 0)

	msg->msg_name = NULL

".

This change does not alter the user visible error logic as we ignore msg_namelen as long as msg_name is NULL.

Also remove two unnecessary curly brackets in ___sys_recvmsg and change comments to netdev style.

---
 crypto/algif_hash.c            |    2 --
 crypto/algif_skcipher.c        |    1 -
 drivers/isdn/mISDN/socket.c    |   13 ++++---------
 drivers/net/ppp/pppoe.c        |    2 --
 include/linux/net.h            |    8 ++++++++
 net/appletalk/ddp.c            |   16 +++++++---------
 net/atm/common.c               |    2 --
 net/ax25/af_ax25.c             |    4 ++--
 net/bluetooth/af_bluetooth.c   |    4 ----
 net/bluetooth/hci_sock.c       |    2 --
 net/bluetooth/rfcomm/sock.c    |    1 -
 net/bluetooth/sco.c            |    1 -
 net/caif/caif_socket.c         |    4 ----
 net/compat.c                   |    3 ++-
 net/core/iovec.c               |    3 ++-
 net/ipx/af_ipx.c               |    3 +--
 net/irda/af_irda.c             |    4 ----
 net/iucv/af_iucv.c             |    2 --
 net/key/af_key.c               |    1 -
 net/l2tp/l2tp_ppp.c            |    2 --
 net/llc/af_llc.c               |    2 --
 net/netlink/af_netlink.c       |    2 --
 net/netrom/af_netrom.c         |    3 +--
 net/nfc/llcp_sock.c            |    2 --
 net/nfc/rawsock.c              |    2 --
 net/packet/af_packet.c         |   32 +++++++++++++++-----------------
 net/rds/recv.c                 |    2 --
 net/rose/af_rose.c             |    8 +++++---
 net/rxrpc/ar-recvmsg.c         |    9 ++++++---
 net/socket.c                   |   19 +++++++++++--------
 net/tipc/socket.c              |    6 ------
 net/unix/af_unix.c             |    5 -----
 net/vmw_vsock/af_vsock.c       |    2 --
 net/vmw_vsock/vmci_transport.c |    2 --
 net/x25/af_x25.c               |    3 +--
 35 files changed, 65 insertions(+), 112 deletions(-)
crypto/algif_hash.c +0 -2
@@ -161,8 +161,6 @@ static int hash_recvmsg(struct kiocb *un
 	else if (len < ds)
 		msg->msg_flags |= MSG_TRUNC;
 
-	msg->msg_namelen = 0;
-
 	lock_sock(sk);
 	if (ctx->more) {
 		ctx->more = 0;
crypto/algif_skcipher.c +0 -1
@@ -432,7 +432,6 @@ static int skcipher_recvmsg(struct kiocb
 	long copied = 0;
 
 	lock_sock(sk);
-	msg->msg_namelen = 0;
 	for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
 	     iovlen--, iov++) {
 		unsigned long seglen = iov->iov_len;
drivers/isdn/mISDN/socket.c +4 -9
@@ -117,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, s
 {
 	struct sk_buff		*skb;
 	struct sock		*sk = sock->sk;
-	struct sockaddr_mISDN	*maddr;
 
 	int		copied, err;
 
@@ -135,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, s
 	if (!skb)
 		return err;
 
-	if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
-		msg->msg_namelen = sizeof(struct sockaddr_mISDN);
-		maddr = (struct sockaddr_mISDN *)msg->msg_name;
+	if (msg->msg_name) {
+		struct sockaddr_mISDN *maddr = msg->msg_name;
+
 		maddr->family = AF_ISDN;
 		maddr->dev = _pms(sk)->dev->id;
 		if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
@@ -150,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, s
 			maddr->sapi = _pms(sk)->ch.addr & 0xFF;
 			maddr->tei =  (_pms(sk)->ch.addr >> 8) & 0xFF;
 		}
-	} else {
-		if (msg->msg_namelen)
-			printk(KERN_WARNING "%s: too small namelen %d\n",
-			       __func__, msg->msg_namelen);
-		msg->msg_namelen = 0;
+		msg->msg_namelen = sizeof(*maddr);
 	}
 
 	copied = skb->len + MISDN_HEADER_LEN;
drivers/net/ppp/pppoe.c +0 -2
@@ -979,8 +979,6 @@ static int pppoe_recvmsg(struct kiocb *i
 	if (error < 0)
 		goto end;
 
-	m->msg_namelen = 0;
-
 	if (skb) {
 		total_len = min_t(size_t, total_len, skb->len);
 		error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
include/linux/net.h +8 -0
@@ -163,6 +163,14 @@ struct proto_ops {
 #endif
 	int		(*sendmsg)   (struct kiocb *iocb, struct socket *sock,
 				      struct msghdr *m, size_t total_len);
+	/* Notes for implementing recvmsg:
+	 * ===============================
+	 * msg->msg_namelen should get updated by the recvmsg handlers
+	 * iff msg_name != NULL. It is by default 0 to prevent
+	 * returning uninitialized memory to user space.  The recvfrom
+	 * handlers can assume that msg.msg_name is either NULL or has
+	 * a minimum size of sizeof(struct sockaddr_storage).
+	 */
 	int		(*recvmsg)   (struct kiocb *iocb, struct socket *sock,
 				      struct msghdr *m, size_t total_len,
 				      int flags);
net/appletalk/ddp.c +7 -9
@@ -1735,7 +1735,6 @@ static int atalk_recvmsg(struct kiocb *i
 			 size_t size, int flags)
 {
 	struct sock *sk = sock->sk;
-	struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
 	struct ddpehdr *ddp;
 	int copied = 0;
 	int offset = 0;
@@ -1764,14 +1763,13 @@ static int atalk_recvmsg(struct kiocb *i
 	}
 	err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
 
-	if (!err) {
-		if (sat) {
-			sat->sat_family      = AF_APPLETALK;
-			sat->sat_port        = ddp->deh_sport;
-			sat->sat_addr.s_node = ddp->deh_snode;
-			sat->sat_addr.s_net  = ddp->deh_snet;
-		}
-		msg->msg_namelen = sizeof(*sat);
+	if (!err && msg->msg_name) {
+		struct sockaddr_at *sat = msg->msg_name;
+		sat->sat_family      = AF_APPLETALK;
+		sat->sat_port        = ddp->deh_sport;
+		sat->sat_addr.s_node = ddp->deh_snode;
+		sat->sat_addr.s_net  = ddp->deh_snet;
+		msg->msg_namelen     = sizeof(*sat);
 	}
 
 	skb_free_datagram(sk, skb);	/* Free the datagram. */
net/atm/common.c +0 -2
@@ -531,8 +531,6 @@ int vcc_recvmsg(struct kiocb *iocb, stru
 	struct sk_buff *skb;
 	int copied, error = -EINVAL;
 
-	msg->msg_namelen = 0;
-
 	if (sock->state != SS_CONNECTED)
 		return -ENOTCONN;
 
net/ax25/af_ax25.c +2 -2
@@ -1636,11 +1636,11 @@ static int ax25_recvmsg(struct kiocb *io
 
 	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
-	if (msg->msg_namelen != 0) {
-		struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
+	if (msg->msg_name) {
 		ax25_digi digi;
 		ax25_address src;
 		const unsigned char *mac = skb_mac_header(skb);
+		struct sockaddr_ax25 *sax = msg->msg_name;
 
 		memset(sax, 0, sizeof(struct full_sockaddr_ax25));
 		ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
net/bluetooth/af_bluetooth.c +0 -4
@@ -221,8 +221,6 @@ int bt_sock_recvmsg(struct kiocb *iocb,
 	if (flags & (MSG_OOB))
 		return -EOPNOTSUPP;
 
-	msg->msg_namelen = 0;
-
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb) {
 		if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -287,8 +285,6 @@ int bt_sock_stream_recvmsg(struct kiocb
 	if (flags & MSG_OOB)
 		return -EOPNOTSUPP;
 
-	msg->msg_namelen = 0;
-
 	BT_DBG("sk %p size %zu", sk, size);
 
 	lock_sock(sk);
net/bluetooth/hci_sock.c +0 -2
@@ -752,8 +752,6 @@ static int hci_sock_recvmsg(struct kiocb
 	if (!skb)
 		return err;
 
-	msg->msg_namelen = 0;
-
 	copied = skb->len;
 	if (len < copied) {
 		msg->msg_flags |= MSG_TRUNC;
net/bluetooth/rfcomm/sock.c +0 -1
@@ -608,7 +608,6 @@ static int rfcomm_sock_recvmsg(struct ki
 
 	if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
 		rfcomm_dlc_accept(d);
-		msg->msg_namelen = 0;
 		return 0;
 	}
 
net/bluetooth/sco.c +0 -1
@@ -700,7 +700,6 @@ static int sco_sock_recvmsg(struct kiocb
 	    test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
 		sco_conn_defer_accept(pi->conn->hcon, 0);
 		sk->sk_state = BT_CONFIG;
-		msg->msg_namelen = 0;
 
 		release_sock(sk);
 		return 0;
net/caif/caif_socket.c +0 -4
@@ -286,8 +286,6 @@ static int caif_seqpkt_recvmsg(struct ki
 	if (m->msg_flags&MSG_OOB)
 		goto read_error;
 
-	m->msg_namelen = 0;
-
 	skb = skb_recv_datagram(sk, flags, 0 , &ret);
 	if (!skb)
 		goto read_error;
@@ -361,8 +359,6 @@ static int caif_stream_recvmsg(struct ki
 	if (flags&MSG_OOB)
 		goto out;
 
-	msg->msg_namelen = 0;
-
 	/*
 	 * Lock the socket to prevent queue disordering
 	 * while sleeps in memcpy_tomsg
net/compat.c +2 -1
@@ -93,7 +93,8 @@ int verify_compat_iovec(struct msghdr *k
 			if (err < 0)
 				return err;
 		}
-		kern_msg->msg_name = kern_address;
+		if (kern_msg->msg_name)
+			kern_msg->msg_name = kern_address;
 	} else
 		kern_msg->msg_name = NULL;
 
net/core/iovec.c +2 -1
@@ -48,7 +48,8 @@ int verify_iovec(struct msghdr *m, struc
 			if (err < 0)
 				return err;
 		}
-		m->msg_name = address;
+		if (m->msg_name)
+			m->msg_name = address;
 	} else {
 		m->msg_name = NULL;
 	}
net/ipx/af_ipx.c +1 -2
@@ -1823,8 +1823,6 @@ static int ipx_recvmsg(struct kiocb *ioc
 	if (skb->tstamp.tv64)
 		sk->sk_stamp = skb->tstamp;
 
-	msg->msg_namelen = sizeof(*sipx);
-
 	if (sipx) {
 		sipx->sipx_family	= AF_IPX;
 		sipx->sipx_port		= ipx->ipx_source.sock;
@@ -1832,6 +1830,7 @@ static int ipx_recvmsg(struct kiocb *ioc
 		sipx->sipx_network	= IPX_SKB_CB(skb)->ipx_source_net;
 		sipx->sipx_type 	= ipx->ipx_type;
 		sipx->sipx_zero		= 0;
+		msg->msg_namelen	= sizeof(*sipx);
 	}
 	rc = copied;
 
net/irda/af_irda.c +0 -4
@@ -1385,8 +1385,6 @@ static int irda_recvmsg_dgram(struct kio
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
-	msg->msg_namelen = 0;
-
 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 				flags & MSG_DONTWAIT, &err);
 	if (!skb)
@@ -1451,8 +1449,6 @@ static int irda_recvmsg_stream(struct ki
 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
 	timeo = sock_rcvtimeo(sk, noblock);
 
-	msg->msg_namelen = 0;
-
 	do {
 		int chunk;
 		struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue);
net/iucv/af_iucv.c +0 -2
@@ -1324,8 +1324,6 @@ static int iucv_sock_recvmsg(struct kioc
 	int err = 0;
 	u32 offset;
 
-	msg->msg_namelen = 0;
-
 	if ((sk->sk_state == IUCV_DISCONN) &&
 	    skb_queue_empty(&iucv->backlog_skb_q) &&
 	    skb_queue_empty(&sk->sk_receive_queue) &&
net/key/af_key.c +0 -1
@@ -3623,7 +3623,6 @@ static int pfkey_recvmsg(struct kiocb *k
 	if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
 		goto out;
 
-	msg->msg_namelen = 0;
 	skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
 	if (skb == NULL)
 		goto out;
net/l2tp/l2tp_ppp.c +0 -2
@@ -197,8 +197,6 @@ static int pppol2tp_recvmsg(struct kiocb
 	if (sk->sk_state & PPPOX_BOUND)
 		goto end;
 
-	msg->msg_namelen = 0;
-
 	err = 0;
 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 				flags & MSG_DONTWAIT, &err);
net/llc/af_llc.c +0 -2
@@ -720,8 +720,6 @@ static int llc_ui_recvmsg(struct kiocb *
 	int target;	/* Read at least this many bytes */
 	long timeo;
 
-	msg->msg_namelen = 0;
-
 	lock_sock(sk);
 	copied = -ENOTCONN;
 	if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
net/netlink/af_netlink.c +0 -2
@@ -2168,8 +2168,6 @@ static int netlink_recvmsg(struct kiocb
 	}
 #endif
 
-	msg->msg_namelen = 0;
-
 	copied = data_skb->len;
 	if (len < copied) {
 		msg->msg_flags |= MSG_TRUNC;
net/netrom/af_netrom.c +1 -2
@@ -1179,10 +1179,9 @@ static int nr_recvmsg(struct kiocb *iocb
 		sax->sax25_family = AF_NETROM;
 		skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
 			      AX25_ADDR_LEN);
+		msg->msg_namelen = sizeof(*sax);
 	}
 
-	msg->msg_namelen = sizeof(*sax);
-
 	skb_free_datagram(sk, skb);
 
 	release_sock(sk);
net/nfc/llcp_sock.c +0 -2
@@ -800,8 +800,6 @@ static int llcp_sock_recvmsg(struct kioc
 
 	pr_debug("%p %zu\n", sk, len);
 
-	msg->msg_namelen = 0;
-
 	lock_sock(sk);
 
 	if (sk->sk_state == LLCP_CLOSED &&
net/nfc/rawsock.c +0 -2
@@ -241,8 +241,6 @@ static int rawsock_recvmsg(struct kiocb
 	if (!skb)
 		return rc;
 
-	msg->msg_namelen = 0;
-
 	copied = skb->len;
 	if (len < copied) {
 		msg->msg_flags |= MSG_TRUNC;
net/packet/af_packet.c +15 -17
@@ -2694,7 +2694,6 @@ static int packet_recvmsg(struct kiocb *
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
 	int copied, err;
-	struct sockaddr_ll *sll;
 	int vnet_hdr_len = 0;
 
 	err = -EINVAL;
@@ -2777,22 +2776,10 @@ static int packet_recvmsg(struct kiocb *
 			goto out_free;
 	}
 
-	/*
-	 *	If the address length field is there to be filled in, we fill
-	 *	it in now.
+	/* You lose any data beyond the buffer you gave. If it worries
+	 * a user program they can ask the device for its MTU
+	 * anyway.
 	 */
-
-	sll = &PACKET_SKB_CB(skb)->sa.ll;
-	if (sock->type == SOCK_PACKET)
-		msg->msg_namelen = sizeof(struct sockaddr_pkt);
-	else
-		msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr);
-
-	/*
-	 *	You lose any data beyond the buffer you gave. If it worries a
-	 *	user program they can ask the device for its MTU anyway.
-	 */
-
 	copied = skb->len;
 	if (copied > len) {
 		copied = len;
@@ -2805,9 +2792,20 @@ static int packet_recvmsg(struct kiocb *
 
 	sock_recv_ts_and_drops(msg, sk, skb);
 
-	if (msg->msg_name)
+	if (msg->msg_name) {
+		/* If the address length field is there to be filled
+		 * in, we fill it in now.
+		 */
+		if (sock->type == SOCK_PACKET) {
+			msg->msg_namelen = sizeof(struct sockaddr_pkt);
+		} else {
+			struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
+			msg->msg_namelen = sll->sll_halen +
+				offsetof(struct sockaddr_ll, sll_addr);
+		}
 		memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa,
 		       msg->msg_namelen);
+	}
 
 	if (pkt_sk(sk)->auxdata) {
 		struct tpacket_auxdata aux;
net/rds/recv.c +0 -2
@@ -410,8 +410,6 @@ int rds_recvmsg(struct kiocb *iocb, stru
 
 	rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo);
 
-	msg->msg_namelen = 0;
-
 	if (msg_flags & MSG_OOB)
 		goto out;
 
net/rose/af_rose.c +5 -3
@@ -1216,7 +1216,6 @@ static int rose_recvmsg(struct kiocb *io
 {
 	struct sock *sk = sock->sk;
 	struct rose_sock *rose = rose_sk(sk);
-	struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name;
 	size_t copied;
 	unsigned char *asmptr;
 	struct sk_buff *skb;
@@ -1252,8 +1251,11 @@ static int rose_recvmsg(struct kiocb *io
 
 	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
-	if (srose != NULL) {
-		memset(srose, 0, msg->msg_namelen);
+	if (msg->msg_name) {
+		struct sockaddr_rose *srose;
+
+		memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
+		srose = msg->msg_name;
 		srose->srose_family = AF_ROSE;
 		srose->srose_addr   = rose->dest_addr;
 		srose->srose_call   = rose->dest_call;
net/rxrpc/ar-recvmsg.c +6 -3
@@ -143,10 +143,13 @@ int rxrpc_recvmsg(struct kiocb *iocb, st
 
 		/* copy the peer address and timestamp */
 		if (!continue_call) {
-			if (msg->msg_name && msg->msg_namelen > 0)
+			if (msg->msg_name) {
+				size_t len =
+					sizeof(call->conn->trans->peer->srx);
 				memcpy(msg->msg_name,
-				       &call->conn->trans->peer->srx,
-				       sizeof(call->conn->trans->peer->srx));
+				       &call->conn->trans->peer->srx, len);
+				msg->msg_namelen = len;
+			}
 			sock_recv_ts_and_drops(msg, &rx->sk, skb);
 		}
 
net/socket.c +11 -8
@@ -1832,8 +1832,10 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void
 	msg.msg_iov = &iov;
 	iov.iov_len = size;
 	iov.iov_base = ubuf;
-	msg.msg_name = (struct sockaddr *)&address;
-	msg.msg_namelen = sizeof(address);
+	/* Save some cycles and don't copy the address if not needed */
+	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
+	/* We assume all kernel code knows the size of sockaddr_storage */
+	msg.msg_namelen = 0;
 	if (sock->file->f_flags & O_NONBLOCK)
 		flags |= MSG_DONTWAIT;
 	err = sock_recvmsg(sock, &msg, size, flags);
@@ -2213,16 +2215,14 @@ static int ___sys_recvmsg(struct socket
 			goto out;
 	}
 
-	/*
-	 *      Save the user-mode address (verify_iovec will change the
-	 *      kernel msghdr to use the kernel address space)
+	/* Save the user-mode address (verify_iovec will change the
+	 * kernel msghdr to use the kernel address space)
 	 */
-
 	uaddr = (__force void __user *)msg_sys->msg_name;
 	uaddr_len = COMPAT_NAMELEN(msg);
-	if (MSG_CMSG_COMPAT & flags) {
+	if (MSG_CMSG_COMPAT & flags)
 		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
-	} else
+	else
 		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
 	if (err < 0)
 		goto out_freeiov;
@@ -2231,6 +2231,9 @@ static int ___sys_recvmsg(struct socket
 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
 
+	/* We assume all kernel code knows the size of sockaddr_storage */
+	msg_sys->msg_namelen = 0;
+
 	if (sock->file->f_flags & O_NONBLOCK)
 		flags |= MSG_DONTWAIT;
 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
net/tipc/socket.c +0 -6
@@ -905,9 +905,6 @@ static int recv_msg(struct kiocb *iocb,
 		goto exit;
 	}
 
-	/* will be updated in set_orig_addr() if needed */
-	m->msg_namelen = 0;
-
 	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 restart:
 
@@ -1017,9 +1014,6 @@ static int recv_stream(struct kiocb *ioc
 		goto exit;
 	}
 
-	/* will be updated in set_orig_addr() if needed */
-	m->msg_namelen = 0;
-
 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
 	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 
net/unix/af_unix.c +0 -5
@@ -1761,7 +1761,6 @@ static void unix_copy_addr(struct msghdr
 {
 	struct unix_sock *u = unix_sk(sk);
 
-	msg->msg_namelen = 0;
 	if (u->addr) {
 		msg->msg_namelen = u->addr->len;
 		memcpy(msg->msg_name, u->addr->name, u->addr->len);
@@ -1785,8 +1784,6 @@ static int unix_dgram_recvmsg(struct kio
 	if (flags&MSG_OOB)
 		goto out;
 
-	msg->msg_namelen = 0;
-
 	err = mutex_lock_interruptible(&u->readlock);
 	if (err) {
 		err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
@@ -1926,8 +1923,6 @@ static int unix_stream_recvmsg(struct ki
 	target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
 	timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
 
-	msg->msg_namelen = 0;
-
 	/* Lock the socket to prevent queue disordering
 	 * while sleeps in memcpy_tomsg
 	 */
net/vmw_vsock/af_vsock.c +0 -2
@@ -1670,8 +1670,6 @@ vsock_stream_recvmsg(struct kiocb *kiocb
 	vsk = vsock_sk(sk);
 	err = 0;
 
-	msg->msg_namelen = 0;
-
 	lock_sock(sk);
 
 	if (sk->sk_state != SS_CONNECTED) {
net/vmw_vsock/vmci_transport.c +0 -2
@@ -1746,8 +1746,6 @@ static int vmci_transport_dgram_dequeue(
 	if (flags & MSG_OOB || flags & MSG_ERRQUEUE)
 		return -EOPNOTSUPP;
 
-	msg->msg_namelen = 0;
-
 	/* Retrieve the head sk_buff from the socket's receive queue. */
 	err = 0;
 	skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err);
net/x25/af_x25.c +1 -2
@@ -1340,10 +1340,9 @@ static int x25_recvmsg(struct kiocb *ioc
 	if (sx25) {
 		sx25->sx25_family = AF_X25;
 		sx25->sx25_addr   = x25->dest_addr;
+		msg->msg_namelen = sizeof(*sx25);
 	}
 
-	msg->msg_namelen = sizeof(struct sockaddr_x25);
-
 	x25_check_rbuf(sk);
 	rc = copied;
 out_free_dgram:
author maintainer
#20 lore raw

PATCH 20/58 net: add BUG_ON if kernel advertises msg_namelen > sizeof(struct sockaddr_storage)

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hannes Frederic Sowa <[email protected]>

[ Upstream commit 68c6beb373955da0886d8f4f5995b3922ceda4be ]

In that case it is probable that kernel code overwrote part of the stack. So we should bail out loudly here.

The BUG_ON may be removed in future if we are sure all protocols are conformant.

---
 net/socket.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/socket.c +2 -1
@@ -215,12 +215,13 @@ static int move_addr_to_user(struct sock
 	int err;
 	int len;
 
+	BUG_ON(klen > sizeof(struct sockaddr_storage));
 	err = get_user(len, ulen);
 	if (err)
 		return err;
 	if (len > klen)
 		len = klen;
-	if (len < 0 || len > sizeof(struct sockaddr_storage))
+	if (len < 0)
 		return -EINVAL;
 	if (len) {
 		if (audit_sockaddr(klen, kaddr))
author maintainer
#21 lore raw

PATCH 21/58 inet: fix addr_len/msg->msg_namelen assignment in recv_error and rxpmtu functions

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hannes Frederic Sowa <[email protected]>

[ Upstream commit 85fbaa75037d0b6b786ff18658ddf0b4014ce2a4 ]

Commit bceaa90240b6019ed73b49965eac7d167610be69 ("inet: prevent leakage of uninitialized memory to user in recv syscalls") conditionally updated addr_len if the msg_name is written to. The recv_error and rxpmtu functions relied on the recvmsg functions to set up addr_len before.

As this does not happen any more we have to pass addr_len to those functions as well and set it to the size of the corresponding sockaddr length.

This broke traceroute and such.

Fixes bceaa90240b6 ("inet: prevent leakage of uninitialized memory to user in recv syscalls")
Reported-by Tom Labanowski
Cc David S. Miller <[email protected]>
Cc Eric Dumazet <[email protected]>
---
 include/net/ip.h       |    2 +-
 include/net/ipv6.h     |    6 ++++--
 net/ipv4/ip_sockglue.c |    3 ++-
 net/ipv4/ping.c        |    2 +-
 net/ipv4/raw.c         |    2 +-
 net/ipv4/udp.c         |    2 +-
 net/ipv6/datagram.c    |    7 +++++--
 net/ipv6/raw.c         |    4 ++--
 net/ipv6/udp.c         |    4 ++--
 net/l2tp/l2tp_ip6.c    |    2 +-
 10 files changed, 20 insertions(+), 14 deletions(-)
include/net/ip.h +1 -1
@@ -454,7 +454,7 @@ extern int	compat_ip_getsockopt(struct s
 			int optname, char __user *optval, int __user *optlen);
 extern int	ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
 
-extern int 	ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
+extern int 	ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
 extern void	ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
 			      __be16 port, u32 info, u8 *payload);
 extern void	ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
include/net/ipv6.h +4 -2
@@ -793,8 +793,10 @@ extern int			compat_ipv6_getsockopt(stru
 extern int			ip6_datagram_connect(struct sock *sk, 
 						     struct sockaddr *addr, int addr_len);
 
-extern int 			ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
-extern int 			ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
+extern int 			ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
+						int *addr_len);
+extern int 			ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
+						 int *addr_len);
 extern void			ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
 						u32 info, u8 *payload);
 extern void			ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
net/ipv4/ip_sockglue.c +2 -1
@@ -368,7 +368,7 @@ void ip_local_error(struct sock *sk, int
 /*
  *	Handle MSG_ERRQUEUE
  */
-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
 	struct sock_exterr_skb *serr;
 	struct sk_buff *skb, *skb2;
@@ -405,6 +405,7 @@ int ip_recv_error(struct sock *sk, struc
 						   serr->addr_offset);
 		sin->sin_port = serr->port;
 		memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
+		*addr_len = sizeof(*sin);
 	}
 
 	memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
net/ipv4/ping.c +1 -1
@@ -636,7 +636,7 @@ static int ping_recvmsg(struct kiocb *io
 		goto out;
 
 	if (flags & MSG_ERRQUEUE)
-		return ip_recv_error(sk, msg, len);
+		return ip_recv_error(sk, msg, len, addr_len);
 
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
net/ipv4/raw.c +1 -1
@@ -693,7 +693,7 @@ static int raw_recvmsg(struct kiocb *ioc
 		goto out;
 
 	if (flags & MSG_ERRQUEUE) {
-		err = ip_recv_error(sk, msg, len);
+		err = ip_recv_error(sk, msg, len, addr_len);
 		goto out;
 	}
 
net/ipv4/udp.c +1 -1
@@ -1208,7 +1208,7 @@ int udp_recvmsg(struct kiocb *iocb, stru
 	bool slow;
 
 	if (flags & MSG_ERRQUEUE)
-		return ip_recv_error(sk, msg, len);
+		return ip_recv_error(sk, msg, len, addr_len);
 
 try_again:
 	skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
net/ipv6/datagram.c +5 -2
@@ -318,7 +318,7 @@ void ipv6_local_rxpmtu(struct sock *sk,
 /*
  *	Handle MSG_ERRQUEUE
  */
-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sock_exterr_skb *serr;
@@ -369,6 +369,7 @@ int ipv6_recv_error(struct sock *sk, str
 					       &sin->sin6_addr);
 			sin->sin6_scope_id = 0;
 		}
+		*addr_len = sizeof(*sin);
 	}
 
 	memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
@@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error);
 /*
  *	Handle IPV6_RECVPATHMTU
  */
-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
+		     int *addr_len)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sk_buff *skb;
@@ -457,6 +459,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, st
 		sin->sin6_port = 0;
 		sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id;
 		sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr;
+		*addr_len = sizeof(*sin);
 	}
 
 	put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info);
net/ipv6/raw.c +2 -2
@@ -460,10 +460,10 @@ static int rawv6_recvmsg(struct kiocb *i
 		return -EOPNOTSUPP;
 
 	if (flags & MSG_ERRQUEUE)
-		return ipv6_recv_error(sk, msg, len);
+		return ipv6_recv_error(sk, msg, len, addr_len);
 
 	if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-		return ipv6_recv_rxpmtu(sk, msg, len);
+		return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
net/ipv6/udp.c +2 -2
@@ -374,10 +374,10 @@ int udpv6_recvmsg(struct kiocb *iocb, st
 	bool slow;
 
 	if (flags & MSG_ERRQUEUE)
-		return ipv6_recv_error(sk, msg, len);
+		return ipv6_recv_error(sk, msg, len, addr_len);
 
 	if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-		return ipv6_recv_rxpmtu(sk, msg, len);
+		return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
 try_again:
 	skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
net/l2tp/l2tp_ip6.c +1 -1
@@ -665,7 +665,7 @@ static int l2tp_ip6_recvmsg(struct kiocb
 		*addr_len = sizeof(*lsa);
 
 	if (flags & MSG_ERRQUEUE)
-		return ipv6_recv_error(sk, msg, len);
+		return ipv6_recv_error(sk, msg, len, addr_len);
 
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
author maintainer
#22 lore raw

PATCH 22/58 net: clamp ->msg_namelen instead of returning an error

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <[email protected]>

[ Upstream commit db31c55a6fb245fdbb752a2ca4aefec89afabb06 ]

If kmsg->msg_namelen > sizeof(struct sockaddr_storage) then in the original code that would lead to memory corruption in the kernel if you had audit configured. If you didn't have audit configured it was harmless.

There are some programs such as beta versions of Ruby which use too large of a buffer and returning an error code breaks them. We should clamp the ->msg_namelen value instead.

Fixes 1661bf364ae9 ("net: heap overflow in __audit_sockaddr()")
---
 net/compat.c |    2 +-
 net/socket.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
net/compat.c +1 -1
@@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kms
 	    __get_user(kmsg->msg_flags, &umsg->msg_flags))
 		return -EFAULT;
 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
-		return -EINVAL;
+		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
 	kmsg->msg_name = compat_ptr(tmp1);
 	kmsg->msg_iov = compat_ptr(tmp2);
 	kmsg->msg_control = compat_ptr(tmp3);
net/socket.c +1 -1
@@ -1965,7 +1965,7 @@ static int copy_msghdr_from_user(struct
 	if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
 		return -EFAULT;
 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
-		return -EINVAL;
+		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
 	return 0;
 }
 
author maintainer
#23 lore raw

PATCH 23/58 ipv6: fix leaking uninitialized port number of offender sockaddr

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hannes Frederic Sowa <[email protected]>

[ Upstream commit 1fa4c710b6fe7b0aac9907240291b6fe6aafc3b8 ]

Offenders don't have port numbers, so set it to 0.

---
 net/ipv6/datagram.c |    1 +
 1 file changed, 1 insertion(+)
net/ipv6/datagram.c +1 -0
@@ -378,6 +378,7 @@ int ipv6_recv_error(struct sock *sk, str
 	if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
 		sin->sin6_family = AF_INET6;
 		sin->sin6_flowinfo = 0;
+		sin->sin6_port = 0;
 		if (skb->protocol == htons(ETH_P_IPV6)) {
 			sin->sin6_addr = ipv6_hdr(skb)->saddr;
 			if (np->rxopt.all)
author maintainer
#24 lore raw

PATCH 24/58 ip6_output: fragment outgoing reassembled skb properly

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jiri Pirko <[email protected]>

[ Upstream commit 9037c3579a277f3a23ba476664629fda8c35f7c4 ]

If reassembled packet would fit into outdev MTU, it is not fragmented according the original frag size and it is send as single big packet.

The second case is if skb is gso. In that case fragmentation does not happen according to the original frag size.

This patch fixes these.

---
 net/ipv6/ip6_output.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv6/ip6_output.c +2 -1
@@ -150,7 +150,8 @@ static int ip6_finish_output2(struct sk_
 static int ip6_finish_output(struct sk_buff *skb)
 {
 	if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
-	    dst_allfrag(skb_dst(skb)))
+	    dst_allfrag(skb_dst(skb)) ||
+	    (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size))
 		return ip6_fragment(skb, ip6_finish_output2);
 	else
 		return ip6_finish_output2(skb);
author maintainer
#25 lore raw

PATCH 25/58 netfilter: push reasm skb through instead of original frag skbs

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jiri Pirko <[email protected]>

[ Upstream commit 6aafeef03b9d9ecf255f3a80ed85ee070260e1ae ]

Pushing original fragments through causes several problems. For example for matching, frags may not be matched correctly. Take following example:

<example>
On HOSTA do:
ip6tables -I INPUT -p icmpv6 -j DROP
ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT

and on HOSTB you do:
ping6 HOSTA -s2000 (MTU is 1500)

Incoming echo requests will be filtered out on HOSTA. This issue does not occur with smaller packets than MTU (where fragmentation does not happen) </example>

As was discussed previously, the only correct solution seems to be to use reassembled skb instead of separete frags. Doing this has positive side effects in reducing sk_buff by one pointer (nfct_reasm) and also the reams dances in ipvs and conntrack can be removed.

Future plan is to remove net/ipv6/netfilter/nf_conntrack_reasm.c entirely and use code in net/ipv6/reassembly.c instead.

---
 include/linux/skbuff.h                         |   32 --------------
 include/net/ip_vs.h                            |   32 --------------
 include/net/netfilter/ipv6/nf_defrag_ipv6.h    |    5 --
 net/core/skbuff.c                              |    3 -
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   54 ------------------------
 net/ipv6/netfilter/nf_conntrack_reasm.c        |   19 --------
 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c      |    7 ++-
 net/netfilter/ipvs/ip_vs_core.c                |   55 -------------------------
 net/netfilter/ipvs/ip_vs_pe_sip.c              |    8 ---
 9 files changed, 13 insertions(+), 202 deletions(-)
include/linux/skbuff.h +0 -32
@@ -331,11 +331,6 @@ typedef unsigned int sk_buff_data_t;
 typedef unsigned char *sk_buff_data_t;
 #endif
 
-#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \
-    defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
-#define NET_SKBUFF_NF_DEFRAG_NEEDED 1
-#endif
-
 /** 
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
@@ -368,7 +363,6 @@ typedef unsigned char *sk_buff_data_t;
  *	@protocol: Packet protocol from driver
  *	@destructor: Destruct function
  *	@nfct: Associated connection, if any
- *	@nfct_reasm: netfilter conntrack re-assembly pointer
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *	@skb_iif: ifindex of device we arrived on
  *	@tc_index: Traffic control index
@@ -455,9 +449,6 @@ struct sk_buff {
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 	struct nf_conntrack	*nfct;
 #endif
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
-	struct sk_buff		*nfct_reasm;
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	struct nf_bridge_info	*nf_bridge;
 #endif
@@ -2700,18 +2691,6 @@ static inline void nf_conntrack_get(stru
 		atomic_inc(&nfct->use);
 }
 #endif
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
-static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
-{
-	if (skb)
-		atomic_inc(&skb->users);
-}
-static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
-{
-	if (skb)
-		kfree_skb(skb);
-}
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
 {
@@ -2730,10 +2709,6 @@ static inline void nf_reset(struct sk_bu
 	nf_conntrack_put(skb->nfct);
 	skb->nfct = NULL;
 #endif
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
-	nf_conntrack_put_reasm(skb->nfct_reasm);
-	skb->nfct_reasm = NULL;
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(skb->nf_bridge);
 	skb->nf_bridge = NULL;
@@ -2755,10 +2730,6 @@ static inline void __nf_copy(struct sk_b
 	nf_conntrack_get(src->nfct);
 	dst->nfctinfo = src->nfctinfo;
 #endif
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
-	dst->nfct_reasm = src->nfct_reasm;
-	nf_conntrack_get_reasm(src->nfct_reasm);
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	dst->nf_bridge  = src->nf_bridge;
 	nf_bridge_get(src->nf_bridge);
@@ -2770,9 +2741,6 @@ static inline void nf_copy(struct sk_buf
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 	nf_conntrack_put(dst->nfct);
 #endif
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
-	nf_conntrack_put_reasm(dst->nfct_reasm);
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(dst->nf_bridge);
 #endif
include/net/ip_vs.h +1 -31
@@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size;
 struct ip_vs_iphdr {
 	__u32 len;	/* IPv4 simply where L4 starts
 			   IPv6 where L4 Transport Header starts */
-	__u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
 	__u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
 	__s16 protocol;
 	__s32 flags;
@@ -117,34 +116,12 @@ struct ip_vs_iphdr {
 	union nf_inet_addr daddr;
 };
 
-/* Dependency to module: nf_defrag_ipv6 */
-#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
-{
-	return skb->nfct_reasm;
-}
 static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
 				      int len, void *buffer,
 				      const struct ip_vs_iphdr *ipvsh)
 {
-	if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
-		return skb_header_pointer(skb_nfct_reasm(skb),
-					  ipvsh->thoff_reasm, len, buffer);
-
 	return skb_header_pointer(skb, offset, len, buffer);
 }
-#else
-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
-{
-	return NULL;
-}
-static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
-				      int len, void *buffer,
-				      const struct ip_vs_iphdr *ipvsh)
-{
-	return skb_header_pointer(skb, offset, len, buffer);
-}
-#endif
 
 static inline void
 ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
@@ -171,19 +148,12 @@ ip_vs_fill_iph_skb(int af, const struct
 			(struct ipv6hdr *)skb_network_header(skb);
 		iphdr->saddr.in6 = iph->saddr;
 		iphdr->daddr.in6 = iph->daddr;
-		/* ipv6_find_hdr() updates len, flags, thoff_reasm */
-		iphdr->thoff_reasm = 0;
+		/* ipv6_find_hdr() updates len, flags */
 		iphdr->len	 = 0;
 		iphdr->flags	 = 0;
 		iphdr->protocol  = ipv6_find_hdr(skb, &iphdr->len, -1,
 						 &iphdr->fragoffs,
 						 &iphdr->flags);
-		/* get proto from re-assembled packet and it's offset */
-		if (skb_nfct_reasm(skb))
-			iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
-							&iphdr->thoff_reasm,
-							-1, NULL, NULL);
-
 	} else
 #endif
 	{
include/net/netfilter/ipv6/nf_defrag_ipv6.h +1 -4
@@ -6,10 +6,7 @@ extern void nf_defrag_ipv6_enable(void);
 extern int nf_ct_frag6_init(void);
 extern void nf_ct_frag6_cleanup(void);
 extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
-			       struct net_device *in,
-			       struct net_device *out,
-			       int (*okfn)(struct sk_buff *));
+extern void nf_ct_frag6_consume_orig(struct sk_buff *skb);
 
 struct inet_frags_ctl;
 
net/core/skbuff.c +0 -3
@@ -585,9 +585,6 @@ static void skb_release_head_state(struc
 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
 	nf_conntrack_put(skb->nfct);
 #endif
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
-	nf_conntrack_put_reasm(skb->nfct_reasm);
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(skb->nf_bridge);
 #endif
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +2 -52

72 lines not on this page · raw message

net/ipv6/netfilter/nf_conntrack_reasm.c +2 -17
@@ -621,31 +621,16 @@ ret_orig:
 	return skb;
 }
 
-void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
-			struct net_device *in, struct net_device *out,
-			int (*okfn)(struct sk_buff *))
+void nf_ct_frag6_consume_orig(struct sk_buff *skb)
 {
 	struct sk_buff *s, *s2;
-	unsigned int ret = 0;
 
 	for (s = NFCT_FRAG6_CB(skb)->orig; s;) {
-		nf_conntrack_put_reasm(s->nfct_reasm);
-		nf_conntrack_get_reasm(skb);
-		s->nfct_reasm = skb;
-
 		s2 = s->next;
 		s->next = NULL;
-
-		if (ret != -ECANCELED)
-			ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s,
-					     in, out, okfn,
-					     NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
-		else
-			kfree_skb(s);
-
+		consume_skb(s);
 		s = s2;
 	}
-	nf_conntrack_put_reasm(skb);
 }
 
 static int nf_ct_net_init(struct net *net)
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +5 -2
@@ -75,8 +75,11 @@ static unsigned int ipv6_defrag(unsigned
 	if (reasm == skb)
 		return NF_ACCEPT;
 
-	nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
-			   (struct net_device *)out, okfn);
+	nf_ct_frag6_consume_orig(reasm);
+
+	NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm,
+		       (struct net_device *) in, (struct net_device *) out,
+		       okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
 
 	return NF_STOLEN;
 }
net/netfilter/ipvs/ip_vs_core.c +1 -54

86 lines not on this page · raw message

net/netfilter/ipvs/ip_vs_pe_sip.c +1 -7
@@ -65,7 +65,6 @@ static int get_callid(const char *dptr,
 static int
 ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
 {
-	struct sk_buff *reasm = skb_nfct_reasm(skb);
 	struct ip_vs_iphdr iph;
 	unsigned int dataoff, datalen, matchoff, matchlen;
 	const char *dptr;
@@ -79,15 +78,10 @@ ip_vs_sip_fill_param(struct ip_vs_conn_p
 	/* todo: IPv6 fragments:
 	 *       I think this only should be done for the first fragment. /HS
 	 */
-	if (reasm) {
-		skb = reasm;
-		dataoff = iph.thoff_reasm + sizeof(struct udphdr);
-	} else
-		dataoff = iph.len + sizeof(struct udphdr);
+	dataoff = iph.len + sizeof(struct udphdr);
 
 	if (dataoff >= skb->len)
 		return -EINVAL;
-	/* todo: Check if this will mess-up the reasm skb !!! /HS */
 	retc = skb_linearize(skb);
 	if (retc < 0)
 		return retc;
author maintainer
#26 lore raw

PATCH 26/58 xfrm: Release dst if this dst is improper for vti tunnel

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: "fan.du" <[email protected]>

[ Upstream commit 236c9f84868534c718b6889aa624de64763281f9 ]

After searching rt by the vti tunnel dst/src parameter, if this rt has neither attached to any transformation nor the transformation is not tunnel oriented, this rt should be released back to ip layer.

otherwise causing dst memory leakage.

---
 net/ipv4/ip_vti.c |    1 +
 1 file changed, 1 insertion(+)
net/ipv4/ip_vti.c +1 -0
@@ -350,6 +350,7 @@ static netdev_tx_t vti_tunnel_xmit(struc
 	if (!rt->dst.xfrm ||
 	    rt->dst.xfrm->props.mode != XFRM_MODE_TUNNEL) {
 		dev->stats.tx_carrier_errors++;
+		ip_rt_put(rt);
 		goto tx_error_icmp;
 	}
 	tdev = rt->dst.dev;
author maintainer
#27 lore raw

PATCH 27/58 atm: idt77252: fix dev refcnt leak

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ying Xue <[email protected]>

[ Upstream commit b5de4a22f157ca345cdb3575207bf46402414bc1 ]

init_card() calls dev_get_by_name() to get a network deceive. But it doesn't decrease network device reference count after the device is used.

---
 drivers/atm/idt77252.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/atm/idt77252.c +1 -1
@@ -3511,7 +3511,7 @@ static int init_card(struct atm_dev *dev
 	tmp = dev_get_by_name(&init_net, tname);	/* jhs: was "tmp = dev_get(tname);" */
 	if (tmp) {
 		memcpy(card->atmdev->esi, tmp->dev_addr, 6);
-
+		dev_put(tmp);
 		printk("%s: ESI %pM\n", card->name, card->atmdev->esi);
 	}
 	/*
author maintainer
#28 lore raw

PATCH 28/58 tcp: dont update snd_nxt, when a socket is switched from repair mode

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andrey Vagin <[email protected]>

[ Upstream commit dbde497966804e63a38fdedc1e3815e77097efc2 ]

snd_nxt must be updated synchronously with sk_send_head. Otherwise tp->packets_out may be updated incorrectly, what may bring a kernel panic.

Here is a kernel panic from my host.

[  103.043194] BUG: unable to handle kernel NULL pointer dereference at 0000000000000048
[  103.044025] IP: [<ffffffff815aaaaf>] tcp_rearm_rto+0xcf/0x150
...
[  146.301158] Call Trace:
[  146.301158]  [<ffffffff815ab7f0>] tcp_ack+0xcc0/0x12c0

Before this panic a tcp socket was restored. This socket had sent and unsent data in the write queue. Sent data was restored in repair mode, then the socket was switched from reapair mode and unsent data was restored. After that the socket was switched back into repair mode.

In that moment we had a socket where write queue looks like this:
snd_una snd_nxt write_seq

   |_________|________|
             |

sk_send_head

After a second switching from repair mode the state of socket was changed:

snd_una snd_nxt, write_seq

   |_________ ________|
             |

sk_send_head

This state is inconsistent, because snd_nxt and sk_send_head are not synchronized.

Bellow you can find a call trace, how packets_out can be incremented twice for one skb, if snd_nxt and sk_send_head are not synchronized. In this case packets_out will be always positive, even when sk_write_queue is empty.

tcp_write_wakeup

	skb = tcp_send_head(sk);
	tcp_fragment
		if (!before(tp->snd_nxt, TCP_SKB_CB(buff)->end_seq))
			tcp_adjust_pcount(sk, skb, diff);
	tcp_event_new_data_sent
		tp->packets_out += tcp_skb_pcount(skb);

I think update of snd_nxt isn't required, when a socket is switched from repair mode. Because it's initialized in tcp_connect_init. Then when a write queue is restored, snd_nxt is incremented in tcp_event_new_data_sent, so it's always is in consistent state.

I have checked, that the bug is not reproduced with this patch and all tests about restoring tcp connections work fine.

Cc Pavel Emelyanov <[email protected]>
Cc Eric Dumazet <[email protected]>
Cc "David S. Miller" <[email protected]>
Cc Alexey Kuznetsov <[email protected]>
Cc James Morris <[email protected]>
Cc Hideaki YOSHIFUJI <[email protected]>
Cc Patrick McHardy <[email protected]>
---
 net/ipv4/tcp_output.c |    1 -
 1 file changed, 1 deletion(-)
net/ipv4/tcp_output.c +0 -1
@@ -3102,7 +3102,6 @@ void tcp_send_window_probe(struct sock *
 {
 	if (sk->sk_state == TCP_ESTABLISHED) {
 		tcp_sk(sk)->snd_wl1 = tcp_sk(sk)->rcv_nxt - 1;
-		tcp_sk(sk)->snd_nxt = tcp_sk(sk)->write_seq;
 		tcp_xmit_probe_skb(sk, 0);
 	}
 }
author maintainer
#29 lore raw

PATCH 29/58 ipv4: fix race in concurrent ip_route_input_slow()

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexei Starovoitov <[email protected]>

[ Upstream commit dcdfdf56b4a6c9437fc37dbc9cee94a788f9b0c4 ]

CPUs can ask for local route via ip_route_input_noref() concurrently. if nh_rth_input is not cached yet, CPUs will proceed to allocate equivalent DSTs on 'lo' and then will try to cache them in nh_rth_input via rt_cache_route()
Most of the time they succeed, but on occasion the following two lines:

	orig = *p;
	prev = cmpxchg(p, orig, rt);

in rt_cache_route() do race and one of the cpus fails to complete cmpxchg. But ip_route_input_slow() doesn't check the return code of rt_cache_route(), so dst is leaking. dst_destroy() is never called and 'lo' device refcnt doesn't go to zero, which can be seen in the logs as:
unregister_netdevice: waiting for lo to become free. Usage count = 1
Adding mdelay() between above two lines makes it easily reproducible. Fix it similar to nh_pcpu_rth_output case.

Fixes d2d68ba9fe8b ("ipv4: Cache input routes in fib_info nexthops.")
---
 net/ipv4/route.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
net/ipv4/route.c +6 -2
@@ -1720,8 +1720,12 @@ local_input:
 		rth->dst.error= -err;
 		rth->rt_flags 	&= ~RTCF_LOCAL;
 	}
-	if (do_cache)
-		rt_cache_route(&FIB_RES_NH(res), rth);
+	if (do_cache) {
+		if (unlikely(!rt_cache_route(&FIB_RES_NH(res), rth))) {
+			rth->dst.flags |= DST_NOCACHE;
+			rt_add_uncached_list(rth);
+		}
+	}
 	skb_dst_set(skb, &rth->dst);
 	err = 0;
 	goto out;
author maintainer
#30 lore raw

PATCH 30/58 net: core: Always propagate flag changes to interfaces

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vlad Yasevich <[email protected]>

[ Upstream commit d2615bf450694c1302d86b9cc8a8958edfe4c3a4 ]

The following commit:

    b6c40d68ff6498b7f63ddf97cf0aa818d748dee7
    net: only invoke dev->change_rx_flags when device is UP

tried to fix a problem with VLAN devices and promiscuouse flag setting. The issue was that VLAN device was setting a flag on an interface that was down, thus resulting in bad promiscuity count.
This commit blocked flag propagation to any device that is currently down.

A later commit:
deede2fabe24e00bd7e246eb81cd5767dc6fcfc7
vlan: Don't propagate flag changes on down interfaces

fixed VLAN code to only propagate flags when the VLAN interface is up, thus fixing the same issue as above, only localized to VLAN.

The problem we have now is that if we have create a complex stack involving multiple software devices like bridges, bonds, and vlans, then it is possible that the flags would not propagate properly to the physical devices. A simple examle of the scenario is the following:

eth0----> bond0 ----> bridge0 ---> vlan50

If bond0 or eth0 happen to be down at the time bond0 is added to the bridge, then eth0 will never have promisc mode set which is currently required for operation as part of the bridge. As a result, packets with vlan50 will be dropped by the interface.

The only 2 devices that implement the special flag handling are VLAN and DSA and they both have required code to prevent incorrect flag propagation. As a result we can remove the generic solution introduced in b6c40d68ff6498b7f63ddf97cf0aa818d748dee7 and leave it to the individual devices to decide whether they will block flag propagation or not.

---
 net/core/dev.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/dev.c +1 -1
@@ -4478,7 +4478,7 @@ static void dev_change_rx_flags(struct n
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
 
-	if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags)
+	if (ops->ndo_change_rx_flags)
 		ops->ndo_change_rx_flags(dev, flags);
 }
 
author maintainer
#31 lore raw

PATCH 31/58 bridge: flush brs address entry in fdb when remove the bridge dev

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ding Tianhong <[email protected]>

[ Upstream commit f873042093c0b418d2351fe142222b625c740149 ]

When the following commands are executed:

brctl addbr br0
ifconfig br0 hw ether <addr>
rmmod bridge

The calltrace will occur:

[  563.312114] device eth1 left promiscuous mode
[  563.312188] br0: port 1(eth1) entered disabled state
[  563.468190] kmem_cache_destroy bridge_fdb_cache: Slab cache still has objects
[  563.468197] CPU: 6 PID: 6982 Comm: rmmod Tainted: G           O 3.12.0-0.7-default+ #9
[  563.468199] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
[  563.468200]  0000000000000880 ffff88010f111e98 ffffffff814d1c92 ffff88010f111eb8
[  563.468204]  ffffffff81148efd ffff88010f111eb8 0000000000000000 ffff88010f111ec8
[  563.468206]  ffffffffa062a270 ffff88010f111ed8 ffffffffa063ac76 ffff88010f111f78
[  563.468209] Call Trace:
[  563.468218]  [<ffffffff814d1c92>] dump_stack+0x6a/0x78
[  563.468234]  [<ffffffff81148efd>] kmem_cache_destroy+0xfd/0x100
[  563.468242]  [<ffffffffa062a270>] br_fdb_fini+0x10/0x20 [bridge]
[  563.468247]  [<ffffffffa063ac76>] br_deinit+0x4e/0x50 [bridge]
[  563.468254]  [<ffffffff810c7dc9>] SyS_delete_module+0x199/0x2b0
[  563.468259]  [<ffffffff814e0922>] system_call_fastpath+0x16/0x1b
[  570.377958] Bridge firewalling registered

--------------------------- cut here -------------------------------

The reason is that when the bridge dev's address is changed, the br_fdb_change_mac_address() will add new address in fdb, but when the bridge was removed, the address entry in the fdb did not free, the bridge_fdb_cache still has objects when destroy the cache, Fix this by flushing the bridge address entry when removing the bridge.

v2: according to the Toshiaki Makita and Vlad's suggestion, I only
delete the vlan0 entry, it still have a leak here if the vlan id is other number, so I need to call fdb_delete_by_port(br, NULL, 1) to flush all entries whose dst is NULL for the bridge.

---
 net/bridge/br_if.c |    2 ++
 1 file changed, 2 insertions(+)
net/bridge/br_if.c +2 -0
@@ -172,6 +172,8 @@ void br_dev_delete(struct net_device *de
 		del_nbp(p);
 	}
 
+	br_fdb_delete_by_port(br, NULL, 1);
+
 	del_timer_sync(&br->gc_timer);
 
 	br_sysfs_delbr(br->dev);
author maintainer
#32 lore raw

PATCH 32/58 packet: fix use after free race in send path when dev is released

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel Borkmann <[email protected]>

[ Upstream commit e40526cb20b5ee53419452e1f03d97092f144418 ]

Salam reported a use after free bug in PF_PACKET that occurs when we're sending out frames on a socket bound device and suddenly the net device is being unregistered. It appears that commit 827d9780 introduced a possible race condition between {t,}packet_snd() and packet_notifier(). In the case of a bound socket, packet_notifier() can drop the last reference to the net_device and {t,}packet_snd() might end up suddenly sending a packet over a freed net_device.

To avoid reverting 827d9780 and thus introducing a performance regression compared to the current state of things, we decided to hold a cached RCU protected pointer to the net device and maintain it on write side via bind spin_lock protected register_prot_hook() and __unregister_prot_hook() calls.

In {t,}packet_snd() path, we access this pointer under rcu_read_lock through packet_cached_dev_get() that holds reference to the device to prevent it from being freed through packet_notifier() while we're in send path. This is okay to do as dev_put()/dev_hold() are per-cpu counters, so this should not be a performance issue. Also, the code simplifies a bit as we don't need need_rls_dev anymore.

Fixes 827d978037d7 ("af-packet: Use existing netdev reference for bound sockets.")
Cc Ben Greear <[email protected]>
Cc Eric Dumazet <[email protected]>
---
 net/packet/af_packet.c |   59 +++++++++++++++++++++++++++++--------------------
 net/packet/internal.h  |    1 
 2 files changed, 37 insertions(+), 23 deletions(-)
net/packet/af_packet.c +36 -23
@@ -244,11 +244,15 @@ static void __fanout_link(struct sock *s
 static void register_prot_hook(struct sock *sk)
 {
 	struct packet_sock *po = pkt_sk(sk);
+
 	if (!po->running) {
-		if (po->fanout)
+		if (po->fanout) {
 			__fanout_link(sk, po);
-		else
+		} else {
 			dev_add_pack(&po->prot_hook);
+			rcu_assign_pointer(po->cached_dev, po->prot_hook.dev);
+		}
+
 		sock_hold(sk);
 		po->running = 1;
 	}
@@ -266,10 +270,13 @@ static void __unregister_prot_hook(struc
 	struct packet_sock *po = pkt_sk(sk);
 
 	po->running = 0;
-	if (po->fanout)
+	if (po->fanout) {
 		__fanout_unlink(sk, po);
-	else
+	} else {
 		__dev_remove_pack(&po->prot_hook);
+		RCU_INIT_POINTER(po->cached_dev, NULL);
+	}
+
 	__sock_put(sk);
 
 	if (sync) {
@@ -2041,12 +2048,24 @@ static int tpacket_fill_skb(struct packe
 	return tp_len;
 }
 
+static struct net_device *packet_cached_dev_get(struct packet_sock *po)
+{
+	struct net_device *dev;
+
+	rcu_read_lock();
+	dev = rcu_dereference(po->cached_dev);
+	if (dev)
+		dev_hold(dev);
+	rcu_read_unlock();
+
+	return dev;
+}
+
 static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 {
 	struct sk_buff *skb;
 	struct net_device *dev;
 	__be16 proto;
-	bool need_rls_dev = false;
 	int err, reserve = 0;
 	void *ph;
 	struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
@@ -2059,7 +2078,7 @@ static int tpacket_snd(struct packet_soc
 	mutex_lock(&po->pg_vec_lock);
 
 	if (saddr == NULL) {
-		dev = po->prot_hook.dev;
+		dev	= packet_cached_dev_get(po);
 		proto	= po->num;
 		addr	= NULL;
 	} else {
@@ -2073,19 +2092,17 @@ static int tpacket_snd(struct packet_soc
 		proto	= saddr->sll_protocol;
 		addr	= saddr->sll_addr;
 		dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
-		need_rls_dev = true;
 	}
 
 	err = -ENXIO;
 	if (unlikely(dev == NULL))
 		goto out;
-
-	reserve = dev->hard_header_len;
-
 	err = -ENETDOWN;
 	if (unlikely(!(dev->flags & IFF_UP)))
 		goto out_put;
 
+	reserve = dev->hard_header_len;
+
 	size_max = po->tx_ring.frame_size
 		- (po->tp_hdrlen - sizeof(struct sockaddr_ll));
 
@@ -2162,8 +2179,7 @@ out_status:
 	__packet_set_status(po, ph, status);
 	kfree_skb(skb);
 out_put:
-	if (need_rls_dev)
-		dev_put(dev);
+	dev_put(dev);
 out:
 	mutex_unlock(&po->pg_vec_lock);
 	return err;
@@ -2201,7 +2217,6 @@ static int packet_snd(struct socket *soc
 	struct sk_buff *skb;
 	struct net_device *dev;
 	__be16 proto;
-	bool need_rls_dev = false;
 	unsigned char *addr;
 	int err, reserve = 0;
 	struct virtio_net_hdr vnet_hdr = { 0 };
@@ -2217,7 +2232,7 @@ static int packet_snd(struct socket *soc
 	 */
 
 	if (saddr == NULL) {
-		dev = po->prot_hook.dev;
+		dev	= packet_cached_dev_get(po);
 		proto	= po->num;
 		addr	= NULL;
 	} else {
@@ -2229,19 +2244,17 @@ static int packet_snd(struct socket *soc
 		proto	= saddr->sll_protocol;
 		addr	= saddr->sll_addr;
 		dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
-		need_rls_dev = true;
 	}
 
 	err = -ENXIO;
-	if (dev == NULL)
+	if (unlikely(dev == NULL))
 		goto out_unlock;
-	if (sock->type == SOCK_RAW)
-		reserve = dev->hard_header_len;
-
 	err = -ENETDOWN;
-	if (!(dev->flags & IFF_UP))
+	if (unlikely(!(dev->flags & IFF_UP)))
 		goto out_unlock;
 
+	if (sock->type == SOCK_RAW)
+		reserve = dev->hard_header_len;
 	if (po->has_vnet_hdr) {
 		vnet_hdr_len = sizeof(vnet_hdr);
 
@@ -2375,15 +2388,14 @@ static int packet_snd(struct socket *soc
 	if (err > 0 && (err = net_xmit_errno(err)) != 0)
 		goto out_unlock;
 
-	if (need_rls_dev)
-		dev_put(dev);
+	dev_put(dev);
 
 	return len;
 
 out_free:
 	kfree_skb(skb);
 out_unlock:
-	if (dev && need_rls_dev)
+	if (dev)
 		dev_put(dev);
 out:
 	return err;
@@ -2603,6 +2615,7 @@ static int packet_create(struct net *net
 	po = pkt_sk(sk);
 	sk->sk_family = PF_PACKET;
 	po->num = proto;
+	RCU_INIT_POINTER(po->cached_dev, NULL);
 
 	sk->sk_destruct = packet_sock_destruct;
 	sk_refcnt_debug_inc(sk);
net/packet/internal.h +1 -0
@@ -113,6 +113,7 @@ struct packet_sock {
 	unsigned int		tp_loss:1;
 	unsigned int		tp_tx_has_off:1;
 	unsigned int		tp_tstamp;
+	struct net_device __rcu	*cached_dev;
 	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
 };
 
author maintainer
#33 lore raw

PATCH 33/58 af_packet: block BH in prb_shutdown_retire_blk_timer()

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Veaceslav Falico <[email protected]>

[ Upstream commit ec6f809ff6f19fafba3212f6aff0dda71dfac8e8 ]

Currently we're using plain spin_lock() in prb_shutdown_retire_blk_timer(), however the timer might fire right in the middle and thus try to re-aquire the same spinlock, leaving us in a endless loop.

To fix that, use the spin_lock_bh() to block it.

Fixes f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.")
CC "David S. Miller" <[email protected]>
CC Daniel Borkmann <[email protected]>
CC Willem de Bruijn <[email protected]>
CC Phil Sutter <[email protected]>
CC Eric Dumazet <[email protected]>
---
 net/packet/af_packet.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/packet/af_packet.c +2 -2
@@ -439,9 +439,9 @@ static void prb_shutdown_retire_blk_time
 
 	pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc;
 
-	spin_lock(&rb_queue->lock);
+	spin_lock_bh(&rb_queue->lock);
 	pkc->delete_blk_timer = 1;
-	spin_unlock(&rb_queue->lock);
+	spin_unlock_bh(&rb_queue->lock);
 
 	prb_del_retire_blk_timer(pkc);
 }
author maintainer
#34 lore raw

PATCH 34/58 r8169: check ALDPS bit and disable it if enabled for the 8168g

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Chang <[email protected]>

[ Upstream commit 1bac1072425c86f1ac85bd5967910706677ef8b3 ]

Windows driver will enable ALDPS function, but linux driver and firmware do not have any configuration related to ALDPS function for 8168g. So restart system to linux and remove the NIC cable, LAN enter ALDPS, then LAN RX will be disabled.

This issue can be easily reproduced on dual boot windows and linux system with RTL_GIGA_MAC_VER_40 chip.

Realtek said, ALDPS function can be disabled by configuring to PHY, switch to page 0x0A43, reg0x10 bit2=0.

---
 drivers/net/ethernet/realtek/r8169.c |    5 +++++
 1 file changed, 5 insertions(+)
drivers/net/ethernet/realtek/r8169.c +5 -0
@@ -3456,6 +3456,11 @@ static void rtl8168g_1_hw_phy_config(str
 	rtl_writephy(tp, 0x14, 0x9065);
 	rtl_writephy(tp, 0x14, 0x1065);
 
+	/* Check ALDPS bit, disable it if enabled */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	if (rtl_readphy(tp, 0x10) & 0x0004)
+		rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
+
 	rtl_writephy(tp, 0x1f, 0x0000);
 }
 
author maintainer
#35 lore raw

PATCH 35/58 net: 8139cp: fix a BUG_ON triggered by wrong bytes_compl

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Yang Yingliang <[email protected]>

[ Upstream commit 7fe0ee099ad5e3dea88d4ee1b6f20246b1ca57c3 ]

Using iperf to send packets(GSO mode is on), a bug is triggered:

[  212.672781] kernel BUG at lib/dynamic_queue_limits.c:26!
[  212.673396] invalid opcode: 0000 [#1] SMP
[  212.673882] Modules linked in: 8139cp(O) nls_utf8 edd fuse loop dm_mod ipv6 i2c_piix4 8139too i2c_core intel_agp joydev pcspkr hid_generic intel_gtt floppy sr_mod mii button sg cdrom ext3 jbd mbcache usbhid hid uhci_hcd ehci_hcd usbcore sd_mod usb_common crc_t10dif crct10dif_common processor thermal_sys hwmon scsi_dh_emc scsi_dh_rdac scsi_dh_hp_sw scsi_dh ata_generic ata_piix libata scsi_mod [last unloaded: 8139cp]
[  212.676084] CPU: 0 PID: 4124 Comm: iperf Tainted: G           O 3.12.0-0.7-default+ #16
[  212.676084] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
[  212.676084] task: ffff8800d83966c0 ti: ffff8800db4c8000 task.ti: ffff8800db4c8000
[  212.676084] RIP: 0010:[<ffffffff8122e23f>]  [<ffffffff8122e23f>] dql_completed+0x17f/0x190
[  212.676084] RSP: 0018:ffff880116e03e30  EFLAGS: 00010083
[  212.676084] RAX: 00000000000005ea RBX: 0000000000000f7c RCX: 0000000000000002
[  212.676084] RDX: ffff880111dd0dc0 RSI: 0000000000000bd4 RDI: ffff8800db6ffcc0
[  212.676084] RBP: ffff880116e03e48 R08: 0000000000000992 R09: 0000000000000000
[  212.676084] R10: ffffffff8181e400 R11: 0000000000000004 R12: 000000000000000f
[  212.676084] R13: ffff8800d94ec840 R14: ffff8800db440c80 R15: 000000000000000e
[  212.676084] FS:  00007f6685a3c700(0000) GS:ffff880116e00000(0000) knlGS:0000000000000000
[  212.676084] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  212.676084] CR2: 00007f6685ad6460 CR3: 00000000db714000 CR4: 00000000000006f0
[  212.676084] Stack:
[  212.676084]  ffff8800db6ffc00 000000000000000f ffff8800d94ec840 ffff880116e03eb8
[  212.676084]  ffffffffa041509f ffff880116e03e88 0000000f16e03e88 ffff8800d94ec000
[  212.676084]  00000bd400059858 000000050000000f ffffffff81094c36 ffff880116e03eb8
[  212.676084] Call Trace:
[  212.676084]  <IRQ>
[  212.676084]  [<ffffffffa041509f>] cp_interrupt+0x4ef/0x590 [8139cp]
[  212.676084]  [<ffffffff81094c36>] ? ktime_get+0x56/0xd0
[  212.676084]  [<ffffffff8108cf73>] handle_irq_event_percpu+0x53/0x170
[  212.676084]  [<ffffffff8108d0cc>] handle_irq_event+0x3c/0x60
[  212.676084]  [<ffffffff8108fdb5>] handle_fasteoi_irq+0x55/0xf0
[  212.676084]  [<ffffffff810045df>] handle_irq+0x1f/0x30
[  212.676084]  [<ffffffff81003c8b>] do_IRQ+0x5b/0xe0
[  212.676084]  [<ffffffff8142beaa>] common_interrupt+0x6a/0x6a
[  212.676084]  <EOI>
[  212.676084]  [<ffffffffa0416a21>] ? cp_start_xmit+0x621/0x97c [8139cp]
[  212.676084]  [<ffffffffa0416a09>] ? cp_start_xmit+0x609/0x97c [8139cp]
[  212.676084]  [<ffffffff81378ed9>] dev_hard_start_xmit+0x2c9/0x550
[  212.676084]  [<ffffffff813960a9>] sch_direct_xmit+0x179/0x1d0
[  212.676084]  [<ffffffff813793f3>] dev_queue_xmit+0x293/0x440
[  212.676084]  [<ffffffff813b0e46>] ip_finish_output+0x236/0x450
[  212.676084]  [<ffffffff810e59e7>] ? __alloc_pages_nodemask+0x187/0xb10
[  212.676084]  [<ffffffff813b10e8>] ip_output+0x88/0x90
[  212.676084]  [<ffffffff813afa64>] ip_local_out+0x24/0x30
[  212.676084]  [<ffffffff813aff0d>] ip_queue_xmit+0x14d/0x3e0
[  212.676084]  [<ffffffff813c6fd1>] tcp_transmit_skb+0x501/0x840
[  212.676084]  [<ffffffff813c8323>] tcp_write_xmit+0x1e3/0xb20
[  212.676084]  [<ffffffff81363237>] ? skb_page_frag_refill+0x87/0xd0
[  212.676084]  [<ffffffff813c8c8b>] tcp_push_one+0x2b/0x40
[  212.676084]  [<ffffffff813bb7e6>] tcp_sendmsg+0x926/0xc90
[  212.676084]  [<ffffffff813e1d21>] inet_sendmsg+0x61/0xc0
[  212.676084]  [<ffffffff8135e861>] sock_aio_write+0x101/0x120
[  212.676084]  [<ffffffff81107cf1>] ? vma_adjust+0x2e1/0x5d0
[  212.676084]  [<ffffffff812163e0>] ? timerqueue_add+0x60/0xb0
[  212.676084]  [<ffffffff81130b60>] do_sync_write+0x60/0x90
[  212.676084]  [<ffffffff81130d44>] ? rw_verify_area+0x54/0xf0
[  212.676084]  [<ffffffff81130f66>] vfs_write+0x186/0x190
[  212.676084]  [<ffffffff811317fd>] SyS_write+0x5d/0xa0
[  212.676084]  [<ffffffff814321e2>] system_call_fastpath+0x16/0x1b
[  212.676084] Code: ca 41 89 dc 41 29 cc 45 31 db 29 c2 41 89 c5 89 d0 45 29 c5 f7 d0 c1 e8 1f e9 43 ff ff ff 66 0f 1f 44 00 00 31 c0 e9 7b ff ff ff <0f> 0b eb fe 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 c7 47 40 00
[  212.676084] RIP  [<ffffffff8122e23f>] dql_completed+0x17f/0x190
------------[ cut here ]------------

When a skb has frags, bytes_compl plus skb->len nr_frags times in cp_tx(). It's not the correct value(actually, it should plus skb->len once) and it will trigger the BUG_ON(bytes_compl > num_queued - dql->num_completed). So only increase bytes_compl when finish sending all frags. pkts_compl also has a wrong value, fix it too.

It's introduced by commit 871f0d4c ("8139cp: enable bql").

---
 drivers/net/ethernet/realtek/8139cp.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/net/ethernet/realtek/8139cp.c +2 -3
@@ -678,9 +678,6 @@ static void cp_tx (struct cp_private *cp
 				 le32_to_cpu(txd->opts1) & 0xffff,
 				 PCI_DMA_TODEVICE);
 
-		bytes_compl += skb->len;
-		pkts_compl++;
-
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
 				netif_dbg(cp, tx_err, cp->dev,
@@ -702,6 +699,8 @@ static void cp_tx (struct cp_private *cp
 				netif_dbg(cp, tx_done, cp->dev,
 					  "tx done, slot %d\n", tx_tail);
 			}
+			bytes_compl += skb->len;
+			pkts_compl++;
 			dev_kfree_skb_irq(skb);
 		}
 
author maintainer
#36 lore raw

PATCH 36/58 net: update consumers of MSG_MORE to recognize MSG_SENDPAGE_NOTLAST

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Shawn Landden <[email protected]>

[ Upstream commit d3f7d56a7a4671d395e8af87071068a195257bf6 ]

Commit 35f9c09fe (tcp: tcp_sendpages() should call tcp_push() once) added an internal flag MSG_SENDPAGE_NOTLAST, similar to MSG_MORE.

algif_hash, algif_skcipher, and udp used MSG_MORE from tcp_sendpages() and need to see the new flag as identical to MSG_MORE.

This fixes sendfile() on AF_ALG.

v3: also fix udp

Reported-and-tested-by Shawn Landden <[email protected]>
Cc Tom Herbert <[email protected]>
Cc Eric Dumazet <[email protected]>
Cc David S. Miller <[email protected]>

Original-patch: Richard Weinberger <[email protected]>

---
 crypto/algif_hash.c     |    3 +++
 crypto/algif_skcipher.c |    3 +++
 net/ipv4/udp.c          |    3 +++
 3 files changed, 9 insertions(+)
crypto/algif_hash.c +3 -0
@@ -114,6 +114,9 @@ static ssize_t hash_sendpage(struct sock
 	struct hash_ctx *ctx = ask->private;
 	int err;
 
+	if (flags & MSG_SENDPAGE_NOTLAST)
+		flags |= MSG_MORE;
+
 	lock_sock(sk);
 	sg_init_table(ctx->sgl.sg, 1);
 	sg_set_page(ctx->sgl.sg, page, size, offset);
crypto/algif_skcipher.c +3 -0
@@ -378,6 +378,9 @@ static ssize_t skcipher_sendpage(struct
 	struct skcipher_sg_list *sgl;
 	int err = -EINVAL;
 
+	if (flags & MSG_SENDPAGE_NOTLAST)
+		flags |= MSG_MORE;
+
 	lock_sock(sk);
 	if (!ctx->more && ctx->used)
 		goto unlock;
net/ipv4/udp.c +3 -0
@@ -1070,6 +1070,9 @@ int udp_sendpage(struct sock *sk, struct
 	struct udp_sock *up = udp_sk(sk);
 	int ret;
 
+	if (flags & MSG_SENDPAGE_NOTLAST)
+		flags |= MSG_MORE;
+
 	if (!up->pending) {
 		struct msghdr msg = {	.msg_flags = flags|MSG_MORE };
 
author maintainer
#37 lore raw

PATCH 37/58 team: fix master carrier set when user linkup is enabled

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jiri Pirko <[email protected]>

[ Upstream commit f5e0d34382e18f396d7673a84df8e3342bea7eb6 ]

When user linkup is enabled and user sets linkup of individual port, we need to recompute linkup (carrier) of master interface so the change is reflected. Fix this by calling __team_carrier_check() which does the needed work.

Please apply to all stable kernels as well. Thanks.

---
 drivers/net/team/team.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/net/team/team.c +4 -0
@@ -1217,6 +1217,8 @@ static int team_user_linkup_option_get(s
 	return 0;
 }
 
+static void __team_carrier_check(struct team *team);
+
 static int team_user_linkup_option_set(struct team *team,
 				       struct team_gsetter_ctx *ctx)
 {
@@ -1224,6 +1226,7 @@ static int team_user_linkup_option_set(s
 
 	port->user.linkup = ctx->data.bool_val;
 	team_refresh_port_linkup(port);
+	__team_carrier_check(port->team);
 	return 0;
 }
 
@@ -1243,6 +1246,7 @@ static int team_user_linkup_en_option_se
 
 	port->user.linkup_enabled = ctx->data.bool_val;
 	team_refresh_port_linkup(port);
+	__team_carrier_check(port->team);
 	return 0;
 }
 
author maintainer
#38 lore raw

PATCH 38/58 inet: fix possible seqlock deadlocks

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit f1d8cba61c3c4b1eb88e507249c4cb8d635d9a76 ]

In commit c9e9042994d3 ("ipv4: fix possible seqlock deadlock") I left another places where IP_INC_STATS_BH() were improperly used.

udp_sendmsg(), ping_v4_sendmsg() and tcp_v4_connect() are called from process context, not from softirq context.

This was detected by lockdep seqlock support.

Fixes 584bdf8cbdf6 ("[IPV4]: Fix "ipOutNoRoutes" counter error for TCP and UDP")
Fixes c319b4d76b9e ("net: ipv4: add IPPROTO_ICMP socket kind")
Cc Hannes Frederic Sowa <[email protected]>
---
 net/ipv4/ping.c     |    2 +-
 net/ipv4/tcp_ipv4.c |    2 +-
 net/ipv4/udp.c      |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
net/ipv4/ping.c +1 -1
@@ -570,7 +570,7 @@ static int ping_sendmsg(struct kiocb *io
 		err = PTR_ERR(rt);
 		rt = NULL;
 		if (err == -ENETUNREACH)
-			IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+			IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
 		goto out;
 	}
 
net/ipv4/tcp_ipv4.c +1 -1
@@ -176,7 +176,7 @@ int tcp_v4_connect(struct sock *sk, stru
 	if (IS_ERR(rt)) {
 		err = PTR_ERR(rt);
 		if (err == -ENETUNREACH)
-			IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+			IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
 		return err;
 	}
 
net/ipv4/udp.c +1 -1
@@ -971,7 +971,7 @@ int udp_sendmsg(struct kiocb *iocb, stru
 			err = PTR_ERR(rt);
 			rt = NULL;
 			if (err == -ENETUNREACH)
-				IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+				IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
 			goto out;
 		}
 
author maintainer
#39 lore raw

PATCH 39/58 ipv6: fix possible seqlock deadlock in ip6_finish_output2

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hannes Frederic Sowa <[email protected]>

[ Upstream commit 7f88c6b23afbd31545c676dea77ba9593a1a14bf ]

IPv6 stats are 64 bits and thus are protected with a seqlock. By not disabling bottom-half we could deadlock here if we don't disable bh and a softirq reentrantly updates the same mib.

---
 net/ipv6/ip6_output.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/ipv6/ip6_output.c +2 -2
@@ -141,8 +141,8 @@ static int ip6_finish_output2(struct sk_
 	}
 	rcu_read_unlock_bh();
 
-	IP6_INC_STATS_BH(dev_net(dst->dev),
-			 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
+	IP6_INC_STATS(dev_net(dst->dev),
+		      ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
 	kfree_skb(skb);
 	return -EINVAL;
 }
author maintainer
#40 lore raw

PATCH 40/58 {pktgen, xfrm} Update IPv4 header total len and checksum after tranformation

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: "fan.du" <[email protected]>

[ Upstream commit 3868204d6b89ea373a273e760609cb08020beb1a ]

commit a553e4a6317b2cfc7659542c10fe43184ffe53da ("[PKTGEN]: IPSEC support") tried to support IPsec ESP transport transformation for pktgen, but acctually this doesn't work at all for two reasons(The orignal transformed packet has bad IPv4 checksum value, as well as wrong auth value, reported by wireshark)

- After transpormation, IPv4 header total length needs update, because encrypted payload's length is NOT same as that of plain text.

- After transformation, IPv4 checksum needs re-caculate because of payload has been changed.

With this patch, armmed pktgen with below cofiguration, Wireshark is able to decrypted ESP packet generated by pktgen without any IPv4 checksum error or auth value error.

pgset "flag IPSEC"
pgset "flows 1"

---
 net/core/pktgen.c |    7 +++++++
 1 file changed, 7 insertions(+)
net/core/pktgen.c +7 -0
@@ -2515,6 +2515,8 @@ static int process_ipsec(struct pktgen_d
 		if (x) {
 			int ret;
 			__u8 *eth;
+			struct iphdr *iph;
+
 			nhead = x->props.header_len - skb_headroom(skb);
 			if (nhead > 0) {
 				ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
@@ -2536,6 +2538,11 @@ static int process_ipsec(struct pktgen_d
 			eth = (__u8 *) skb_push(skb, ETH_HLEN);
 			memcpy(eth, pkt_dev->hh, 12);
 			*(u16 *) &eth[12] = protocol;
+
+			/* Update IPv4 header len as well as checksum value */
+			iph = ip_hdr(skb);
+			iph->tot_len = htons(skb->len - ETH_HLEN);
+			ip_send_check(iph);
 		}
 	}
 	return 1;
author maintainer
#41 lore raw

PATCH 41/58 tcp: gso: fix truesize tracking

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 0d08c42cf9a71530fef5ebcfe368f38f2dd0476f ]

commit 6ff50cd55545 ("tcp: gso: do not generate out of order packets") had an heuristic that can trigger a warning in skb_try_coalesce(), because skb->truesize of the gso segments were exactly set to mss.

This breaks the requirement that

skb->truesize >= skb->len + truesizeof(struct sk_buff);

It can trivially be reproduced by :

ifconfig lo mtu 1500
ethtool -K lo tso off
netperf

As the skbs are looped into the TCP networking stack, skb_try_coalesce() warns us of these skb under-estimating their truesize.

---
 net/ipv4/tcp.c |   13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)
net/ipv4/tcp.c +5 -8
@@ -2899,6 +2899,7 @@ struct sk_buff *tcp_tso_segment(struct s
 	netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	unsigned int sum_truesize = 0;
 	struct tcphdr *th;
 	unsigned int thlen;
 	unsigned int seq;
@@ -2982,13 +2983,7 @@ struct sk_buff *tcp_tso_segment(struct s
 		if (copy_destructor) {
 			skb->destructor = gso_skb->destructor;
 			skb->sk = gso_skb->sk;
-			/* {tcp|sock}_wfree() use exact truesize accounting :
-			 * sum(skb->truesize) MUST be exactly be gso_skb->truesize
-			 * So we account mss bytes of 'true size' for each segment.
-			 * The last segment will contain the remaining.
-			 */
-			skb->truesize = mss;
-			gso_skb->truesize -= mss;
+			sum_truesize += skb->truesize;
 		}
 		skb = skb->next;
 		th = tcp_hdr(skb);
@@ -3005,7 +3000,9 @@ struct sk_buff *tcp_tso_segment(struct s
 	if (copy_destructor) {
 		swap(gso_skb->sk, skb->sk);
 		swap(gso_skb->destructor, skb->destructor);
-		swap(gso_skb->truesize, skb->truesize);
+		sum_truesize += skb->truesize;
+		atomic_add(sum_truesize - gso_skb->truesize,
+			   &skb->sk->sk_wmem_alloc);
 	}
 
 	delta = htonl(oldlen + (skb->tail - skb->transport_header) +
author maintainer
#42 lore raw

PATCH 42/58 xfs: add capability check to free eofblocks ioctl

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dwight Engen <[email protected]>

commit 8c567a7fab6e086a0284eee2db82348521e7120c upstream.

Check for CAP_SYS_ADMIN since the caller can truncate preallocated blocks from files they do not own nor have write access to. A more fine grained access check was considered: require the caller to specify their own uid/gid and to use inode_permission to check for write, but this would not catch the case of an inode not reachable via path traversal from the callers mount namespace.

Add check for read-only filesystem to free eofblocks ioctl.

---
 fs/xfs/xfs_ioctl.c |    6 ++++++
 1 file changed, 6 insertions(+)
fs/xfs/xfs_ioctl.c +6 -0
@@ -1612,6 +1612,12 @@ xfs_file_ioctl(
 	case XFS_IOC_FREE_EOFBLOCKS: {
 		struct xfs_eofblocks eofb;
 
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		if (mp->m_flags & XFS_MOUNT_RDONLY)
+			return -XFS_ERROR(EROFS);
+
 		if (copy_from_user(&eofb, arg, sizeof(eofb)))
 			return -XFS_ERROR(EFAULT);
 
author maintainer
#43 lore raw

PATCH 43/58 mmc: block: fix a bug of error handling in MMC driver

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: KOBAYASHI Yoshitake <[email protected]>

commit c8760069627ad3b0dbbea170f0c4c58b16e18d3d upstream.

Current MMC driver doesn't handle generic error (bit19 of device status) in write sequence. As a result, write data gets lost when generic error occurs. For example, a generic error when updating a filesystem management information causes a loss of write data and corrupts the filesystem. In the worst case, the system will never boot.

This patch includes the following functionality:
1. To enable error checking for the response of CMD12 and CMD13 in write command sequence
2. To retry write sequence when a generic error occurs

Messages are added for v2 to show what occurs.

---
 drivers/mmc/card/block.c |   45 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 42 insertions(+), 3 deletions(-)
drivers/mmc/card/block.c +42 -3
@@ -769,7 +769,7 @@ static int mmc_blk_cmd_error(struct requ
  * Otherwise we don't understand what happened, so abort.
  */
 static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
-	struct mmc_blk_request *brq, int *ecc_err)
+	struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
 {
 	bool prev_cmd_status_valid = true;
 	u32 status, stop_status = 0;
@@ -807,6 +807,16 @@ static int mmc_blk_cmd_recovery(struct m
 	    (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
 		*ecc_err = 1;
 
+	/* Flag General errors */
+	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
+		if ((status & R1_ERROR) ||
+			(brq->stop.resp[0] & R1_ERROR)) {
+			pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
+			       req->rq_disk->disk_name, __func__,
+			       brq->stop.resp[0], status);
+			*gen_err = 1;
+		}
+
 	/*
 	 * Check the current card state.  If it is in some data transfer
 	 * mode, tell it to stop (and hopefully transition back to TRAN.)
@@ -826,6 +836,13 @@ static int mmc_blk_cmd_recovery(struct m
 			return ERR_ABORT;
 		if (stop_status & R1_CARD_ECC_FAILED)
 			*ecc_err = 1;
+		if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
+			if (stop_status & R1_ERROR) {
+				pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
+				       req->rq_disk->disk_name, __func__,
+				       stop_status);
+				*gen_err = 1;
+			}
 	}
 
 	/* Check for set block count errors */
@@ -1069,7 +1086,7 @@ static int mmc_blk_err_check(struct mmc_
 						    mmc_active);
 	struct mmc_blk_request *brq = &mq_mrq->brq;
 	struct request *req = mq_mrq->req;
-	int ecc_err = 0;
+	int ecc_err = 0, gen_err = 0;
 
 	/*
 	 * sbc.error indicates a problem with the set block count
@@ -1083,7 +1100,7 @@ static int mmc_blk_err_check(struct mmc_
 	 */
 	if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
 	    brq->data.error) {
-		switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) {
+		switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
 		case ERR_RETRY:
 			return MMC_BLK_RETRY;
 		case ERR_ABORT:
@@ -1115,6 +1132,14 @@ static int mmc_blk_err_check(struct mmc_
 		u32 status;
 		unsigned long timeout;
 
+		/* Check stop command response */
+		if (brq->stop.resp[0] & R1_ERROR) {
+			pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
+			       req->rq_disk->disk_name, __func__,
+			       brq->stop.resp[0]);
+			gen_err = 1;
+		}
+
 		timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
 		do {
 			int err = get_card_status(card, &status, 5);
@@ -1124,6 +1149,13 @@ static int mmc_blk_err_check(struct mmc_
 				return MMC_BLK_CMD_ERR;
 			}
 
+			if (status & R1_ERROR) {
+				pr_err("%s: %s: general error sending status command, card status %#x\n",
+				       req->rq_disk->disk_name, __func__,
+				       status);
+				gen_err = 1;
+			}
+
 			/* Timeout if the device never becomes ready for data
 			 * and never leaves the program state.
 			 */
@@ -1143,6 +1175,13 @@ static int mmc_blk_err_check(struct mmc_
 			 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
 	}
 
+	/* if general error occurs, retry the write operation. */
+	if (gen_err) {
+		pr_warn("%s: retrying write for general error\n",
+				req->rq_disk->disk_name);
+		return MMC_BLK_RETRY;
+	}
+
 	if (brq->data.error) {
 		pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
 		       req->rq_disk->disk_name, brq->data.error,
author maintainer
#44 lore raw

PATCH 44/58 aio: restore locking of ioctx list on removal

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mateusz Guzik <[email protected]>

Commit 36f5588905c10a8c4568a210d601fe8c3c27e0f0
"aio: refcounting cleanup" resulted in ioctx_lock not being held during ctx removal, leaving the list susceptible to corruptions.

In mainline kernel the issue went away as a side effect of db446a08c23d5475e6b08c87acca79ebb20f283c "aio: convert the ioctx list to table lookup v3".

Fix the problem by restoring appropriate locking.

---
 fs/aio.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
fs/aio.c +6 -4
@@ -423,10 +423,12 @@ static void kill_ioctx_rcu(struct rcu_he
  *	when the processes owning a context have all exited to encourage
  *	the rapid destruction of the kioctx.
  */
-static void kill_ioctx(struct kioctx *ctx)
+static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
 {
 	if (!atomic_xchg(&ctx->dead, 1)) {
+		spin_lock(&mm->ioctx_lock);
 		hlist_del_rcu(&ctx->list);
+		spin_unlock(&mm->ioctx_lock);
 
 		/*
 		 * It'd be more correct to do this in free_ioctx(), after all
@@ -494,7 +496,7 @@ void exit_aio(struct mm_struct *mm)
 		 */
 		ctx->mmap_size = 0;
 
-		kill_ioctx(ctx);
+		kill_ioctx(mm, ctx);
 	}
 }
 
@@ -852,7 +854,7 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_e
 	if (!IS_ERR(ioctx)) {
 		ret = put_user(ioctx->user_id, ctxp);
 		if (ret)
-			kill_ioctx(ioctx);
+			kill_ioctx(current->mm, ioctx);
 		put_ioctx(ioctx);
 	}
 
@@ -870,7 +872,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_
 {
 	struct kioctx *ioctx = lookup_ioctx(ctx);
 	if (likely(NULL != ioctx)) {
-		kill_ioctx(ioctx);
+		kill_ioctx(current->mm, ioctx);
 		put_ioctx(ioctx);
 		return 0;
 	}
author maintainer
#45 lore raw

PATCH 45/58 clockevents: Get rid of the notifier chain

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Gleixner <[email protected]>

commit 7172a286ced0c1f4f239a0fa09db54ed37d3ead2 upstream.

7+ years and still a single user. Kill it.

---
 include/linux/clockchips.h   |    1 -
 kernel/time/clockevents.c    |   35 +++--------------------------------
 kernel/time/tick-broadcast.c |    5 ++---
 kernel/time/tick-common.c    |   30 +++++-------------------------
 kernel/time/tick-internal.h  |    7 ++++---
 5 files changed, 14 insertions(+), 64 deletions(-)
include/linux/clockchips.h +0 -1
@@ -150,7 +150,6 @@ extern void clockevents_exchange_device(
 					struct clock_event_device *new);
 extern void clockevents_set_mode(struct clock_event_device *dev,
 				 enum clock_event_mode mode);
-extern int clockevents_register_notifier(struct notifier_block *nb);
 extern int clockevents_program_event(struct clock_event_device *dev,
 				     ktime_t expires, bool force);
 
kernel/time/clockevents.c +3 -32
@@ -15,7 +15,6 @@
 #include <linux/hrtimer.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/notifier.h>
 #include <linux/smp.h>
 
 #include "tick-internal.h"
@@ -23,10 +22,6 @@
 /* The registered clock event devices */
 static LIST_HEAD(clockevent_devices);
 static LIST_HEAD(clockevents_released);
-
-/* Notification for clock events */
-static RAW_NOTIFIER_HEAD(clockevents_chain);
-
 /* Protection for the above */
 static DEFINE_RAW_SPINLOCK(clockevents_lock);
 
@@ -267,30 +262,6 @@ int clockevents_program_event(struct clo
 	return (rc && force) ? clockevents_program_min_delta(dev) : rc;
 }
 
-/**
- * clockevents_register_notifier - register a clock events change listener
- */
-int clockevents_register_notifier(struct notifier_block *nb)
-{
-	unsigned long flags;
-	int ret;
-
-	raw_spin_lock_irqsave(&clockevents_lock, flags);
-	ret = raw_notifier_chain_register(&clockevents_chain, nb);
-	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
-
-	return ret;
-}
-
-/*
- * Notify about a clock event change. Called with clockevents_lock
- * held.
- */
-static void clockevents_do_notify(unsigned long reason, void *dev)
-{
-	raw_notifier_call_chain(&clockevents_chain, reason, dev);
-}
-
 /*
  * Called after a notify add to make devices available which were
  * released from the notifier call.
@@ -304,7 +275,7 @@ static void clockevents_notify_released(
 				 struct clock_event_device, list);
 		list_del(&dev->list);
 		list_add(&dev->list, &clockevent_devices);
-		clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
+		tick_check_new_device(dev);
 	}
 }
 
@@ -325,7 +296,7 @@ void clockevents_register_device(struct
 	raw_spin_lock_irqsave(&clockevents_lock, flags);
 
 	list_add(&dev->list, &clockevent_devices);
-	clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
+	tick_check_new_device(dev);
 	clockevents_notify_released();
 
 	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
@@ -468,7 +439,7 @@ void clockevents_notify(unsigned long re
 	int cpu;
 
 	raw_spin_lock_irqsave(&clockevents_lock, flags);
-	clockevents_do_notify(reason, arg);
+	tick_notify(reason, arg);
 
 	switch (reason) {
 	case CLOCK_EVT_NOTIFY_CPU_DEAD:
kernel/time/tick-broadcast.c +2 -3
@@ -65,7 +65,7 @@ static void tick_broadcast_start_periodi
 /*
  * Check, if the device can be utilized as broadcast device:
  */
-int tick_check_broadcast_device(struct clock_event_device *dev)
+void tick_install_broadcast_device(struct clock_event_device *dev)
 {
 	struct clock_event_device *cur = tick_broadcast_device.evtdev;
 
@@ -73,7 +73,7 @@ int tick_check_broadcast_device(struct c
 	    (tick_broadcast_device.evtdev &&
 	     tick_broadcast_device.evtdev->rating >= dev->rating) ||
 	     (dev->features & CLOCK_EVT_FEAT_C3STOP))
-		return 0;
+		return;
 
 	clockevents_exchange_device(tick_broadcast_device.evtdev, dev);
 	if (cur)
@@ -91,7 +91,6 @@ int tick_check_broadcast_device(struct c
 	 */
 	if (dev->features & CLOCK_EVT_FEAT_ONESHOT)
 		tick_clock_notify();
-	return 1;
 }
 
 /*
kernel/time/tick-common.c +5 -25
@@ -209,11 +209,11 @@ static void tick_setup_device(struct tic
 /*
  * Check, if the new registered device should be used.
  */
-static int tick_check_new_device(struct clock_event_device *newdev)
+void tick_check_new_device(struct clock_event_device *newdev)
 {
 	struct clock_event_device *curdev;
 	struct tick_device *td;
-	int cpu, ret = NOTIFY_OK;
+	int cpu;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&tick_device_lock, flags);
@@ -276,18 +276,14 @@ static int tick_check_new_device(struct
 		tick_oneshot_notify();
 
 	raw_spin_unlock_irqrestore(&tick_device_lock, flags);
-	return NOTIFY_STOP;
+	return;
 
 out_bc:
 	/*
 	 * Can the new device be used as a broadcast device ?
 	 */
-	if (tick_check_broadcast_device(newdev))
-		ret = NOTIFY_STOP;
-
+	tick_install_broadcast_device(newdev);
 	raw_spin_unlock_irqrestore(&tick_device_lock, flags);
-
-	return ret;
 }
 
 /*
@@ -361,17 +357,10 @@ static void tick_resume(void)
 	raw_spin_unlock_irqrestore(&tick_device_lock, flags);
 }
 
-/*
- * Notification about clock event devices
- */
-static int tick_notify(struct notifier_block *nb, unsigned long reason,
-			       void *dev)
+void tick_notify(unsigned long reason, void *dev)
 {
 	switch (reason) {
 
-	case CLOCK_EVT_NOTIFY_ADD:
-		return tick_check_new_device(dev);
-
 	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
 	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
 	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
@@ -405,21 +394,12 @@ static int tick_notify(struct notifier_b
 	default:
 		break;
 	}
-
-	return NOTIFY_OK;
 }
 
-static struct notifier_block tick_notifier = {
-	.notifier_call = tick_notify,
-};
-
 /**
  * tick_init - initialize the tick control
- *
- * Register the notifier with the clockevents framework
  */
 void __init tick_init(void)
 {
-	clockevents_register_notifier(&tick_notifier);
 	tick_broadcast_init();
 }
kernel/time/tick-internal.h +4 -3
@@ -18,6 +18,8 @@ extern int tick_do_timer_cpu __read_most
 
 extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
 extern void tick_handle_periodic(struct clock_event_device *dev);
+extern void tick_notify(unsigned long reason, void *dev);
+extern void tick_check_new_device(struct clock_event_device *dev);
 
 extern void clockevents_shutdown(struct clock_event_device *dev);
 
@@ -90,7 +92,7 @@ static inline bool tick_broadcast_onesho
  */
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
-extern int tick_check_broadcast_device(struct clock_event_device *dev);
+extern void tick_install_broadcast_device(struct clock_event_device *dev);
 extern int tick_is_broadcast_device(struct clock_event_device *dev);
 extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
 extern void tick_shutdown_broadcast(unsigned int *cpup);
@@ -102,9 +104,8 @@ tick_set_periodic_handler(struct clock_e
 
 #else /* !BROADCAST */
 
-static inline int tick_check_broadcast_device(struct clock_event_device *dev)
+static inline void tick_install_broadcast_device(struct clock_event_device *dev)
 {
-	return 0;
 }
 
 static inline int tick_is_broadcast_device(struct clock_event_device *dev)
author maintainer
#46 lore raw

PATCH 46/58 clockevents: Add module refcount

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Gleixner <[email protected]>

commit ccf33d6880f39a35158fff66db13000ae4943fac upstream.

We want to be able to remove clockevent modules as well. Add a refcount so we don't remove a module with an active clock event device.

---
 include/linux/clockchips.h   |    3 +++
 kernel/time/clockevents.c    |    1 +
 kernel/time/tick-broadcast.c |    3 +++
 kernel/time/tick-common.c    |    4 ++++
 4 files changed, 11 insertions(+)
include/linux/clockchips.h +3 -0
@@ -30,6 +30,7 @@ enum clock_event_nofitiers {
 #include <linux/notifier.h>
 
 struct clock_event_device;
+struct module;
 
 /* Clock event mode commands */
 enum clock_event_mode {
@@ -83,6 +84,7 @@ enum clock_event_mode {
  * @irq:		IRQ number (only for non CPU local devices)
  * @cpumask:		cpumask to indicate for which CPUs this device works
  * @list:		list head for the management code
+ * @owner:		module reference
  */
 struct clock_event_device {
 	void			(*event_handler)(struct clock_event_device *);
@@ -112,6 +114,7 @@ struct clock_event_device {
 	int			irq;
 	const struct cpumask	*cpumask;
 	struct list_head	list;
+	struct module		*owner;
 } ____cacheline_aligned;
 
 /*
kernel/time/clockevents.c +1 -0
@@ -392,6 +392,7 @@ void clockevents_exchange_device(struct
 	 * released list and do a notify add later.
 	 */
 	if (old) {
+		module_put(old->owner);
 		clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
 		list_del(&old->list);
 		list_add(&old->list, &clockevents_released);
kernel/time/tick-broadcast.c +3 -0
@@ -19,6 +19,7 @@
 #include <linux/profile.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
+#include <linux/module.h>
 
 #include "tick-internal.h"
 
@@ -74,6 +75,8 @@ void tick_install_broadcast_device(struc
 	     tick_broadcast_device.evtdev->rating >= dev->rating) ||
 	     (dev->features & CLOCK_EVT_FEAT_C3STOP))
 		return;
+	if (!try_module_get(dev->owner))
+		return;
 
 	clockevents_exchange_device(tick_broadcast_device.evtdev, dev);
 	if (cur)
kernel/time/tick-common.c +4 -0
@@ -18,6 +18,7 @@
 #include <linux/percpu.h>
 #include <linux/profile.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 
 #include <asm/irq_regs.h>
 
@@ -261,6 +262,9 @@ void tick_check_new_device(struct clock_
 			goto out_bc;
 	}
 
+	if (!try_module_get(newdev->owner))
+		return;
+
 	/*
 	 * Replace the eventually existing device by the new
 	 * device. If the current device is the broadcast device, do
author maintainer
#47 lore raw

PATCH 47/58 clockevents: Split out selection logic

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Gleixner <[email protected]>

commit 45cb8e01b2ecef1c2afb18333e95793fa1a90281 upstream.

Split out the clockevent device selection logic. Preparatory patch to allow unbinding active clockevent devices.

---
 kernel/time/tick-broadcast.c |   25 ++++++++++++---
 kernel/time/tick-common.c    |   69 ++++++++++++++++++++++---------------------
 2 files changed, 56 insertions(+), 38 deletions(-)
kernel/time/tick-broadcast.c +20 -5
@@ -66,19 +66,34 @@ static void tick_broadcast_start_periodi
 /*
  * Check, if the device can be utilized as broadcast device:
  */
+static bool tick_check_broadcast_device(struct clock_event_device *curdev,
+					struct clock_event_device *newdev)
+{
+	if ((newdev->features & CLOCK_EVT_FEAT_DUMMY) ||
+	    (newdev->features & CLOCK_EVT_FEAT_C3STOP))
+		return false;
+
+	if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT &&
+	    !(newdev->features & CLOCK_EVT_FEAT_ONESHOT))
+		return false;
+
+	return !curdev || newdev->rating > curdev->rating;
+}
+
+/*
+ * Conditionally install/replace broadcast device
+ */
 void tick_install_broadcast_device(struct clock_event_device *dev)
 {
 	struct clock_event_device *cur = tick_broadcast_device.evtdev;
 
-	if ((dev->features & CLOCK_EVT_FEAT_DUMMY) ||
-	    (tick_broadcast_device.evtdev &&
-	     tick_broadcast_device.evtdev->rating >= dev->rating) ||
-	     (dev->features & CLOCK_EVT_FEAT_C3STOP))
+	if (!tick_check_broadcast_device(cur, dev))
 		return;
+
 	if (!try_module_get(dev->owner))
 		return;
 
-	clockevents_exchange_device(tick_broadcast_device.evtdev, dev);
+	clockevents_exchange_device(cur, dev);
 	if (cur)
 		cur->event_handler = clockevents_handle_noop;
 	tick_broadcast_device.evtdev = dev;
kernel/time/tick-common.c +36 -33

82 lines not on this page · raw message

author maintainer
#48 lore raw

PATCH 48/58 clockevents: Prefer CPU local devices over global devices

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stephen Boyd <[email protected]>

commit 70e5975d3a04be5479a28eec4a2fb10f98ad2785 upstream.

On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.

If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.

Reported-and-tested-by Mark Rutland <[email protected]>
Tested-by soren.brinkmann at xilinx.com
Cc John Stultz <[email protected]>
Cc Daniel Lezcano <[email protected]>
Cc linux-arm-kernel at lists.infradead.org
Cc John Stultz <[email protected]>
Cc Kim Phillips <[email protected]>
---
 kernel/time/tick-common.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
kernel/time/tick-common.c +7 -2
@@ -234,8 +234,13 @@ static bool tick_check_preferred(struct
 			return false;
 	}
 
-	/* Use the higher rated one */
-	return !curdev || newdev->rating > curdev->rating;
+	/*
+	 * Use the higher rated one, but prefer a CPU local device with a lower
+	 * rating than a non-CPU local device
+	 */
+	return !curdev ||
+		newdev->rating > curdev->rating ||
+	       !cpumask_equal(curdev->cpumask, newdev->cpumask);
 }
 
 /*
author maintainer
#49 lore raw

PATCH 49/58 mm: numa: return the number of base pages altered by protection changes

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mel Gorman <[email protected]>

commit 72403b4a0fbdf433c1fe0127e49864658f6f6468 upstream.

Commit 0255d4918480 ("mm: Account for a THP NUMA hinting update as one PTE update") was added to account for the number of PTE updates when marking pages prot_numa. task_numa_work was using the old return value to track how much address space had been updated. Altering the return value causes the scanner to do more work than it is configured or documented to in a single unit of work.

This patch reverts that commit and accounts for the number of THP updates separately in vmstat. It is up to the administrator to interpret the pair of values correctly. This is a straight-forward operation and likely to only be of interest when actively debugging NUMA balancing problems.

The impact of this patch is that the NUMA PTE scanner will scan slower when THP is enabled and workloads may converge slower as a result. On the flip size system CPU usage should be lower than recent tests reported. This is an illustrative example of a short single JVM specjbb test

specjbb

                       3.12.0                3.12.0
                      vanilla      acctupdates
TPut 1      26143.00 (  0.00%)     25747.00 ( -1.51%)
TPut 7     185257.00 (  0.00%)    183202.00 ( -1.11%)
TPut 13    329760.00 (  0.00%)    346577.00 (  5.10%)
TPut 19    442502.00 (  0.00%)    460146.00 (  3.99%)
TPut 25    540634.00 (  0.00%)    549053.00 (  1.56%)
TPut 31    512098.00 (  0.00%)    519611.00 (  1.47%)
TPut 37    461276.00 (  0.00%)    474973.00 (  2.97%)
TPut 43    403089.00 (  0.00%)    414172.00 (  2.75%)
              3.12.0      3.12.0
             vanillaacctupdates

User 5169.64 5184.14
System 100.45 80.02
Elapsed 252.75 251.85

Performance is similar but note the reduction in system CPU time. While this showed a performance gain, it will not be universal but at least it'll be behaving as documented. The vmstats are obviously different but here is an obvious interpretation of them from mmtests.

                                3.12.0      3.12.0
                               vanillaacctupdates

NUMA page range updates 1408326 11043064
NUMA huge PMD updates 0 21040
NUMA PTE updates 1408326 291624

"NUMA page range updates" == nr_pte_updates and is the value returned to the NUMA pte scanner. NUMA huge PMD updates were the number of THP updates which in combination can be used to calculate how many ptes were updated from userspace.

---
 include/linux/vm_event_item.h |    1 +
 mm/mprotect.c                 |    7 ++++++-
 mm/vmstat.c                   |    1 +
 3 files changed, 8 insertions(+), 1 deletion(-)
include/linux/vm_event_item.h +1 -0
@@ -39,6 +39,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PS
 		PAGEOUTRUN, ALLOCSTALL, PGROTATED,
 #ifdef CONFIG_NUMA_BALANCING
 		NUMA_PTE_UPDATES,
+		NUMA_HUGE_PTE_UPDATES,
 		NUMA_HINT_FAULTS,
 		NUMA_HINT_FAULTS_LOCAL,
 		NUMA_PAGE_MIGRATE,
mm/mprotect.c +6 -1
@@ -135,6 +135,7 @@ static inline unsigned long change_pmd_r
 	pmd_t *pmd;
 	unsigned long next;
 	unsigned long pages = 0;
+	unsigned long nr_huge_updates = 0;
 	bool all_same_node;
 
 	pmd = pmd_offset(pud, addr);
@@ -145,7 +146,8 @@ static inline unsigned long change_pmd_r
 				split_huge_page_pmd(vma, addr, pmd);
 			else if (change_huge_pmd(vma, pmd, addr, newprot,
 						 prot_numa)) {
-				pages++;
+				pages += HPAGE_PMD_NR;
+				nr_huge_updates++;
 				continue;
 			}
 			/* fall through */
@@ -165,6 +167,9 @@ static inline unsigned long change_pmd_r
 			change_pmd_protnuma(vma->vm_mm, addr, pmd);
 	} while (pmd++, addr = next, addr != end);
 
+	if (nr_huge_updates)
+		count_vm_numa_events(NUMA_HUGE_PTE_UPDATES, nr_huge_updates);
+
 	return pages;
 }
 
mm/vmstat.c +1 -0
@@ -779,6 +779,7 @@ const char * const vmstat_text[] = {
 
 #ifdef CONFIG_NUMA_BALANCING
 	"numa_pte_updates",
+	"numa_huge_pte_updates",
 	"numa_hint_faults",
 	"numa_hint_faults_local",
 	"numa_pages_migrated",
author maintainer
#50 lore raw

PATCH 50/58 video: kyro: fix incorrect sizes when copying to userspace

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sasha Levin <[email protected]>

commit 2ab68ec927310dc488f3403bb48f9e4ad00a9491 upstream.

kyro would copy u32s and specify sizeof(unsigned long) as the size to copy.

This would copy more data than intended and cause memory corruption and might leak kernel memory.

---
 drivers/video/kyro/fbdev.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/video/kyro/fbdev.c +3 -3
@@ -625,15 +625,15 @@ static int kyrofb_ioctl(struct fb_info *
 		}
 		break;
 	case KYRO_IOCTL_UVSTRIDE:
-		if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
+		if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride)))
 			return -EFAULT;
 		break;
 	case KYRO_IOCTL_STRIDE:
-		if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)))
+		if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride)))
 			return -EFAULT;
 		break;
 	case KYRO_IOCTL_OVERLAY_OFFSET:
-		if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)))
+		if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset)))
 			return -EFAULT;
 		break;
 	}
author maintainer
#51 lore raw

PATCH 51/58 HID: lg: fix Report Descriptor for Logitech MOMO Force (Black)

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Simon Wood <[email protected]>

commit 348cbaa800f8161168b20f85f72abb541c145132 upstream.

By default the Logitech MOMO Force (Black) presents a combined accel/brake axis ('Y'). This patch modifies the HID descriptor to present seperate accel/brake axes ('Y' and 'Z').

---
 drivers/hid/hid-lg.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
drivers/hid/hid-lg.c +58 -0
@@ -47,6 +47,7 @@
 #define DFP_RDESC_ORIG_SIZE	97
 #define FV_RDESC_ORIG_SIZE	130
 #define MOMO_RDESC_ORIG_SIZE	87
+#define MOMO2_RDESC_ORIG_SIZE	87
 
 /* Fixed report descriptors for Logitech Driving Force (and Pro)
  * wheel controllers
@@ -284,6 +285,54 @@ static __u8 momo_rdesc_fixed[] = {
 0xC0                /*  End Collection                      */
 };
 
+static __u8 momo2_rdesc_fixed[] = {
+0x05, 0x01,         /*  Usage Page (Desktop),               */
+0x09, 0x04,         /*  Usage (Joystik),                    */
+0xA1, 0x01,         /*  Collection (Application),           */
+0xA1, 0x02,         /*      Collection (Logical),           */
+0x95, 0x01,         /*          Report Count (1),           */
+0x75, 0x0A,         /*          Report Size (10),           */
+0x15, 0x00,         /*          Logical Minimum (0),        */
+0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+0x35, 0x00,         /*          Physical Minimum (0),       */
+0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
+0x09, 0x30,         /*          Usage (X),                  */
+0x81, 0x02,         /*          Input (Variable),           */
+0x95, 0x0A,         /*          Report Count (10),          */
+0x75, 0x01,         /*          Report Size (1),            */
+0x25, 0x01,         /*          Logical Maximum (1),        */
+0x45, 0x01,         /*          Physical Maximum (1),       */
+0x05, 0x09,         /*          Usage Page (Button),        */
+0x19, 0x01,         /*          Usage Minimum (01h),        */
+0x29, 0x0A,         /*          Usage Maximum (0Ah),        */
+0x81, 0x02,         /*          Input (Variable),           */
+0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
+0x09, 0x00,         /*          Usage (00h),                */
+0x95, 0x04,         /*          Report Count (4),           */
+0x81, 0x02,         /*          Input (Variable),           */
+0x95, 0x01,         /*          Report Count (1),           */
+0x75, 0x08,         /*          Report Size (8),            */
+0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
+0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
+0x09, 0x01,         /*          Usage (01h),                */
+0x81, 0x02,         /*          Input (Variable),           */
+0x05, 0x01,         /*          Usage Page (Desktop),       */
+0x09, 0x31,         /*          Usage (Y),                  */
+0x81, 0x02,         /*          Input (Variable),           */
+0x09, 0x32,         /*          Usage (Z),                  */
+0x81, 0x02,         /*          Input (Variable),           */
+0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
+0x09, 0x00,         /*          Usage (00h),                */
+0x81, 0x02,         /*          Input (Variable),           */
+0xC0,               /*      End Collection,                 */
+0xA1, 0x02,         /*      Collection (Logical),           */
+0x09, 0x02,         /*          Usage (02h),                */
+0x95, 0x07,         /*          Report Count (7),           */
+0x91, 0x02,         /*          Output (Variable),          */
+0xC0,               /*      End Collection,                 */
+0xC0                /*  End Collection                      */
+};
+
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
  * above the logical maximum described in descriptor. This extends
@@ -343,6 +392,15 @@ static __u8 *lg_report_fixup(struct hid_
 		}
 		break;
 
+	case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+		if (*rsize == MOMO2_RDESC_ORIG_SIZE) {
+			hid_info(hdev,
+				"fixing up Logitech Momo Racing Force (Black) report descriptor\n");
+			rdesc = momo2_rdesc_fixed;
+			*rsize = sizeof(momo2_rdesc_fixed);
+		}
+		break;
+
 	case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
 		if (*rsize == FV_RDESC_ORIG_SIZE) {
 			hid_info(hdev,
author maintainer
#52 lore raw

PATCH 52/58 iommu/vt-d: Fixed interaction of VFIO_IOMMU_MAP_DMA with IOMMU address limits

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Julian Stecklina <[email protected]>

commit f9423606ade08653dd8a43334f0a7fb45504c5cc upstream.

The BUG_ON in drivers/iommu/intel-iommu.c:785 can be triggered from userspace via VFIO by calling the VFIO_IOMMU_MAP_DMA ioctl on a vfio device with any address beyond the addressing capabilities of the IOMMU. The problem is that the ioctl code calls iommu_iova_to_phys before it calls iommu_map. iommu_map handles the case that it gets addresses beyond the addressing capabilities of its IOMMU. intel_iommu_iova_to_phys does not.

This patch fixes iommu_iova_to_phys to return NULL for addresses beyond what the IOMMU can handle. This in turn causes the ioctl call to fail in iommu_map and (correctly) return EFAULT to the user with a helpful warning message in the kernel log.

---
 drivers/iommu/intel-iommu.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/iommu/intel-iommu.c +5 -1
@@ -782,7 +782,11 @@ static struct dma_pte *pfn_to_dma_pte(st
 	int offset;
 
 	BUG_ON(!domain->pgd);
-	BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width);
+
+	if (addr_width < BITS_PER_LONG && pfn >> addr_width)
+		/* Address beyond IOMMU's addressing capabilities. */
+		return NULL;
+
 	parent = domain->pgd;
 
 	while (level > 0) {
author maintainer
#53 lore raw

PATCH 53/58 iommu: Remove stack trace from broken irq remapping warning

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Neil Horman <[email protected]>

commit 05104a4e8713b27291c7bb49c1e7e68b4e243571 upstream.

The warning for the irq remapping broken check in intel_irq_remapping.c is pretty pointless. We need the warning, but we know where its comming from, the stack trace will always be the same, and it needlessly triggers things like Abrt. This changes the warning to just print a text warning about BIOS being broken, without the stack trace, then sets the appropriate taint bit. Since we automatically disable irq remapping, theres no need to contiue making Abrt jump at this problem

CC Joerg Roedel <[email protected]>
CC Bjorn Helgaas <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Konrad Rzeszutek Wilk <[email protected]>
CC Sebastian Andrzej Siewior <[email protected]>
---
 drivers/iommu/intel_irq_remapping.c |   13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/iommu/intel_irq_remapping.c +7 -6
@@ -525,12 +525,13 @@ static int __init intel_irq_remapping_su
 	if (disable_irq_remap)
 		return 0;
 	if (irq_remap_broken) {
-		WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
-			   "This system BIOS has enabled interrupt remapping\n"
-			   "on a chipset that contains an erratum making that\n"
-			   "feature unstable.  To maintain system stability\n"
-			   "interrupt remapping is being disabled.  Please\n"
-			   "contact your BIOS vendor for an update\n");
+		printk(KERN_WARNING
+			"This system BIOS has enabled interrupt remapping\n"
+			"on a chipset that contains an erratum making that\n"
+			"feature unstable.  To maintain system stability\n"
+			"interrupt remapping is being disabled.  Please\n"
+			"contact your BIOS vendor for an update\n");
+		add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
 		disable_irq_remap = 1;
 		return 0;
 	}
author maintainer
#54 lore raw

PATCH 54/58 elevator: Fix a race in elevator switching and md device initialization

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tomoki Sekiyama <[email protected]>

commit eb1c160b22655fd4ec44be732d6594fd1b1e44f4 upstream.

The soft lockup below happens at the boot time of the system using dm multipath and the udev rules to switch scheduler.

[  356.127001] BUG: soft lockup - CPU#3 stuck for 22s! [sh:483]
[  356.127001] RIP: 0010:[<ffffffff81072a7d>]  [<ffffffff81072a7d>] lock_timer_base.isra.35+0x1d/0x50
...
[  356.127001] Call Trace:
[  356.127001]  [<ffffffff81073810>] try_to_del_timer_sync+0x20/0x70
[  356.127001]  [<ffffffff8118b08a>] ? kmem_cache_alloc_node_trace+0x20a/0x230
[  356.127001]  [<ffffffff810738b2>] del_timer_sync+0x52/0x60
[  356.127001]  [<ffffffff812ece22>] cfq_exit_queue+0x32/0xf0
[  356.127001]  [<ffffffff812c98df>] elevator_exit+0x2f/0x50
[  356.127001]  [<ffffffff812c9f21>] elevator_change+0xf1/0x1c0
[  356.127001]  [<ffffffff812caa50>] elv_iosched_store+0x20/0x50
[  356.127001]  [<ffffffff812d1d09>] queue_attr_store+0x59/0xb0
[  356.127001]  [<ffffffff812143f6>] sysfs_write_file+0xc6/0x140
[  356.127001]  [<ffffffff811a326d>] vfs_write+0xbd/0x1e0
[  356.127001]  [<ffffffff811a3ca9>] SyS_write+0x49/0xa0
[  356.127001]  [<ffffffff8164e899>] system_call_fastpath+0x16/0x1b

This is caused by a race between md device initialization by multipathd and shell script to switch the scheduler using sysfs.

- multipathd:
SyS_ioctl -> do_vfs_ioctl -> dm_ctl_ioctl -> ctl_ioctl -> table_load -> dm_setup_md_queue -> blk_init_allocated_queue -> elevator_init

    q->elevator = elevator_alloc(q, e); // not yet initialized

- sh -c 'echo deadline > /sys/$DEVPATH/queue/scheduler':
elevator_switch (in the call trace above)

    struct elevator_queue *old = q->elevator;
    q->elevator = elevator_alloc(q, new_e);
    elevator_exit(old);                 // lockup! (*)

- multipathd: (cont.)

    err = e->ops.elevator_init_fn(q);   // init fails; q->elevator is modified

(*) When del_timer_sync() is called, lock_timer_base() will loop infinitely while timer->base == NULL. In this case, as timer will never initialized, it results in lockup.

This patch introduces acquisition of q->sysfs_lock around elevator_init() into blk_init_allocated_queue(), to provide mutual exclusion between initialization of the q->scheduler and switching of the scheduler.

This should fix this bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=902012

---
 block/blk-core.c |   10 +++++++++-
 block/elevator.c |    6 ++++++
 2 files changed, 15 insertions(+), 1 deletion(-)
block/blk-core.c +9 -1
@@ -741,9 +741,17 @@ blk_init_allocated_queue(struct request_
 
 	q->sg_reserved_size = INT_MAX;
 
+	/* Protect q->elevator from elevator_change */
+	mutex_lock(&q->sysfs_lock);
+
 	/* init elevator */
-	if (elevator_init(q, NULL))
+	if (elevator_init(q, NULL)) {
+		mutex_unlock(&q->sysfs_lock);
 		return NULL;
+	}
+
+	mutex_unlock(&q->sysfs_lock);
+
 	return q;
 }
 EXPORT_SYMBOL(blk_init_allocated_queue);
block/elevator.c +6 -0
@@ -186,6 +186,12 @@ int elevator_init(struct request_queue *
 	struct elevator_type *e = NULL;
 	int err;
 
+	/*
+	 * q->sysfs_lock must be held to provide mutual exclusion between
+	 * elevator_switch() and here.
+	 */
+	lockdep_assert_held(&q->sysfs_lock);
+
 	if (unlikely(q->elevator))
 		return 0;
 
author maintainer
#55 lore raw

PATCH 55/58 elevator: acquire q->sysfs_lock in elevator_change()

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tomoki Sekiyama <[email protected]>

commit 7c8a3679e3d8e9d92d58f282161760a0e247df97 upstream.

Add locking of q->sysfs_lock into elevator_change() (an exported function) to ensure it is held to protect q->elevator from elevator_init(), even if elevator_change() is called from non-sysfs paths.
sysfs path (elv_iosched_store) uses __elevator_change(), non-locking version, as the lock is already taken by elv_iosched_store().

---
 block/elevator.c |   16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
block/elevator.c +14 -2
@@ -965,7 +965,7 @@ fail_init:
 /*
  * Switch this queue to the given IO scheduler.
  */
-int elevator_change(struct request_queue *q, const char *name)
+static int __elevator_change(struct request_queue *q, const char *name)
 {
 	char elevator_name[ELV_NAME_MAX];
 	struct elevator_type *e;
@@ -987,6 +987,18 @@ int elevator_change(struct request_queue
 
 	return elevator_switch(q, e);
 }
+
+int elevator_change(struct request_queue *q, const char *name)
+{
+	int ret;
+
+	/* Protect q->elevator from elevator_init() */
+	mutex_lock(&q->sysfs_lock);
+	ret = __elevator_change(q, name);
+	mutex_unlock(&q->sysfs_lock);
+
+	return ret;
+}
 EXPORT_SYMBOL(elevator_change);
 
 ssize_t elv_iosched_store(struct request_queue *q, const char *name,
@@ -997,7 +1009,7 @@ ssize_t elv_iosched_store(struct request
 	if (!q->elevator)
 		return count;
 
-	ret = elevator_change(q, name);
+	ret = __elevator_change(q, name);
 	if (!ret)
 		return count;
 
author maintainer
#56 lore raw

PATCH 56/58 ntp: Make periodic RTC update more reliable

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miroslav Lichvar <[email protected]>

commit a97ad0c4b447a132a322cedc3a5f7fa4cab4b304 upstream.

The current code requires that the scheduled update of the RTC happens in the closest tick to the half of the second. This seems to be difficult to achieve reliably. The scheduled work may be missing the target time by a tick or two and be constantly rescheduled every second.

Relax the limit to 10 ticks. As a typical RTC drifts in the 11-minute update interval by several milliseconds, this shouldn't affect the overall accuracy of the RTC much.

---
 kernel/time/ntp.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/time/ntp.c +2 -1
@@ -475,6 +475,7 @@ static void sync_cmos_clock(struct work_
 	 * called as close as possible to 500 ms before the new second starts.
 	 * This code is run on a timer.  If the clock is set, that timer
 	 * may not expire at the correct time.  Thus, we adjust...
+	 * We want the clock to be within a couple of ticks from the target.
 	 */
 	if (!ntp_synced()) {
 		/*
@@ -485,7 +486,7 @@ static void sync_cmos_clock(struct work_
 	}
 
 	getnstimeofday(&now);
-	if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) {
+	if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) {
 		struct timespec adjust = now;
 
 		fail = -ENODEV;
author maintainer
#57 lore raw

PATCH 57/58 drm/radeon/audio: improve ACR calculation

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pierre Ossman <[email protected]>

commit a2098250fbda149cfad9e626afe80abe3b21e574 upstream.

In order to have any realistic chance of calculating proper ACR values, we need to be able to calculate both N and CTS, not just CTS. We still aim for the ideal N as specified in the HDMI spec though.

bug:
https://bugs.freedesktop.org/show_bug.cgi?id=69675

---
 drivers/gpu/drm/radeon/r600_hdmi.c |   68 +++++++++++++++++++++++++------------
 1 file changed, 46 insertions(+), 22 deletions(-)
drivers/gpu/drm/radeon/r600_hdmi.c +46 -22
@@ -24,6 +24,7 @@
  * Authors: Christian König
  */
 #include <linux/hdmi.h>
+#include <linux/gcd.h>
 #include <drm/drmP.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
@@ -67,25 +68,47 @@ static const struct radeon_hdmi_acr r600
     {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
     { 148352, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
     { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
-    {      0,  4096,      0,  6272,      0,  6144,      0 }  /* Other */
 };
 
+
 /*
- * calculate CTS value if it's not found in the table
+ * calculate CTS and N values if they are not found in the table
  */
-static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq)
+static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq)
 {
-	u64 n;
-	u32 d;
+	int n, cts;
+	unsigned long div, mul;
 
-	if (*CTS == 0) {
-		n = (u64)clock * (u64)N * 1000ULL;
-		d = 128 * freq;
-		do_div(n, d);
-		*CTS = n;
-	}
-	DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
-		  N, *CTS, freq);
+	/* Safe, but overly large values */
+	n = 128 * freq;
+	cts = clock * 1000;
+
+	/* Smallest valid fraction */
+	div = gcd(n, cts);
+
+	n /= div;
+	cts /= div;
+
+	/*
+	 * The optimal N is 128*freq/1000. Calculate the closest larger
+	 * value that doesn't truncate any bits.
+	 */
+	mul = ((128*freq/1000) + (n-1))/n;
+
+	n *= mul;
+	cts *= mul;
+
+	/* Check that we are in spec (not always possible) */
+	if (n < (128*freq/1500))
+		printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n");
+	if (n > (128*freq/300))
+		printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n");
+
+	*N = n;
+	*CTS = cts;
+
+	DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
+		  *N, *CTS, freq);
 }
 
 struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
@@ -93,15 +116,16 @@ struct radeon_hdmi_acr r600_hdmi_acr(uin
 	struct radeon_hdmi_acr res;
 	u8 i;
 
-	for (i = 0; r600_hdmi_predefined_acr[i].clock != clock &&
-	     r600_hdmi_predefined_acr[i].clock != 0; i++)
-		;
-	res = r600_hdmi_predefined_acr[i];
-
-	/* In case some CTS are missing */
-	r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000);
-	r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100);
-	r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000);
+	/* Precalculated values for common clocks */
+	for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) {
+		if (r600_hdmi_predefined_acr[i].clock == clock)
+			return r600_hdmi_predefined_acr[i];
+	}
+
+	/* And odd clocks get manually calculated */
+	r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
+	r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
+	r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
 
 	return res;
 }
author maintainer
#58 lore raw

PATCH 58/58 drm/radeon/audio: correct ACR table

In reply to Greg Kroah-Hartman

3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pierre Ossman <[email protected]>

commit 3e71985f2439d8c4090dc2820e497e6f3d72dcff upstream.

The values were taken from the HDMI spec, but they assumed exact x/1.001 clocks. Since we round the clocks, we also need to calculate different N and CTS values.

Note that the N for 25.2/1.001 MHz at 44.1 kHz audio is out of spec. Hopefully this mode is rarely used and/or HDMI sinks tolerate overly large values of N.

bug:
https://bugs.freedesktop.org/show_bug.cgi?id=69675

---
 drivers/gpu/drm/radeon/r600_hdmi.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/radeon/r600_hdmi.c +3 -3
@@ -58,15 +58,15 @@ enum r600_hdmi_iec_status_bits {
 static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
     /*	     32kHz	  44.1kHz	48kHz    */
     /* Clock      N     CTS      N     CTS      N     CTS */
-    {  25175,  4576,  28125,  7007,  31250,  6864,  28125 }, /*  25,20/1.001 MHz */
+    {  25175,  4096,  25175, 28224, 125875,  6144,  25175 }, /*  25,20/1.001 MHz */
     {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
     {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
     {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
     {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
     {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
-    {  74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /*  74.25/1.001 MHz */
+    {  74176,  4096,  74176,  5733,  75335,  6144,  74176 }, /*  74.25/1.001 MHz */
     {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
-    { 148352, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
+    { 148352,  4096, 148352,  5733, 150670,  6144, 148352 }, /* 148.50/1.001 MHz */
     { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
 };
 
#59 lore raw
In reply to Greg Kroah-Hartman
Quoted 8 lines · Greg Kroah-Hartman

This is the start of the stable review cycle for the 3.10.23 release. There are 58 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Sun Dec 8 21:47:53 UTC 2013. Anything received after that time might be too late.

Build results:

	total: 110 pass: 109 skipped: 0 fail: 1

Build avr32:atngw100mkii_evklcd101_defconfig still fails.

qemu tests all passed.

Results are as expected.
Details are available as usual at http://server.roeck-us.net:8010/builders.

Guenter

author maintainer
#60 lore raw
Quoted 6 lines · Guenter Roeck
Quoted 5 lines · Greg Kroah-Hartman

This is the start of the stable review cycle for the 3.10.23 release. There are 58 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Quoted 8 lines
Quoted 3 lines

Responses should be made by Sun Dec 8 21:47:53 UTC 2013. Anything received after that time might be too late.

Build results:

	total: 110 pass: 109 skipped: 0 fail: 1

Build avr32:atngw100mkii_evklcd101_defconfig still fails.

Hopefully one of the avr32 people will fix it, if they care about 3.10...

Quoted 4 lines

qemu tests all passed.

Results are as expected.
Details are available as usual at http://server.roeck-us.net:8010/builders.

Thanks for letting me know.

greg k-h

#61 lore raw
In reply to Greg Kroah-Hartman
Quoted 8 lines · Greg Kroah-Hartman

This is the start of the stable review cycle for the 3.10.23 release. There are 58 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Sun Dec 8 21:47:53 UTC 2013. Anything received after that time might be too late.

Quoted 7 lines

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v3.0/stable-review/patch-3.10.23-rc1.gz

and the diffstat can be found below.

thanks,

greg k-h

patch applied cleanly.
Compile testing - passed
Boot testing - passed
dmesg regression testing - passed
dmesgs look good. No regressions compared to the previous dmesgs for this release. dmesg emerg, crit, alert, err are clean. No regressions in warn.

Test systems

Samsung Series 9 900X4C Intel Corei5 (3.4 and later) HP ProBook 6475b AMD A10-4600M APU with Radeon(tm) HD Graphics Dell OptiPlex 790 Intel(R) Core(TM) i5-2400

-- Shuah

Signature · 4 lines
Shuah Khan
Senior Linux Kernel Developer - Open Source Group
Samsung Research America(Silicon Valley)
[email protected] | (970) 672-0658