From ae35b56e367b9fef7f5de701cf8c1c3dd954dded Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 10 Dec 2015 18:22:31 +0200 Subject: drm/i915: Unbreak check_digital_port_conflicts() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atomic changes broke check_digital_port_conflicts(). It needs to look at the global situation instead of just trying to find a conflict within the current atomic state. This bug made my HSW explode spectacularly after I had split the DDI encoders into separate DP and HDMI encoders. With the fix, things seem much more solid. I hope holding the connection_mutex is enough protection that we can actually walk the connectors even if they're not part of the current atomic state... v2: Regenerate the patch so that it actually applies (Jani) Cc: stable@vger.kernel.org Cc: Ander Conselvan de Oliveira Fixes: 5448a00d3f06 ("drm/i915: Don't use staged config in check_digital_port_conflicts()") Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449764551-12466-1-git-send-email-ville.syrjala@linux.intel.com (cherry picked from commit 0bff4858653312a10c83709e0009c3adb87e6f1e) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index beb0374a19f1..32cf97346978 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12123,18 +12123,22 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, static bool check_digital_port_conflicts(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; - struct intel_encoder *encoder; struct drm_connector *connector; - struct drm_connector_state *connector_state; unsigned int used_ports = 0; - int i; /* * Walk the connector list instead of the encoder * list to detect the problem on ddi platforms * where there's just one encoder per digital port. */ - for_each_connector_in_state(state, connector, connector_state, i) { + drm_for_each_connector(connector, dev) { + struct drm_connector_state *connector_state; + struct intel_encoder *encoder; + + connector_state = drm_atomic_get_existing_connector_state(state, connector); + if (!connector_state) + connector_state = connector->state; + if (!connector_state->best_encoder) continue; -- cgit v1.2.3 From 398c7500a1f5f74e207bd2edca1b1721b3cc1f1e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 23 Dec 2015 21:04:31 -0800 Subject: MIPS: VDSO: Fix build error with binutils 2.24 and earlier Commit 2a037f310bab ("MIPS: VDSO: Fix build error") tries to fix a build error seen with binutils 2.24 and earlier. However, the fix does not work, and again results in the already known build errors if the kernel is built with an earlier version of binutils. CC arch/mips/vdso/gettimeofday.o /tmp/ccnOVbHT.s: Assembler messages: /tmp/ccnOVbHT.s:50: Error: can't resolve `_start' {*UND* section} - `L0 {.text section} /tmp/ccnOVbHT.s:374: Error: can't resolve `_start' {*UND* section} - `L0 {.text section} scripts/Makefile.build:258: recipe for target 'arch/mips/vdso/gettimeofday.o' failed make[2]: *** [arch/mips/vdso/gettimeofday.o] Error 1 Fixes: 2a037f310bab ("MIPS: VDSO: Fix build error") Cc: Qais Yousef Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11926/ Signed-off-by: Guenter Roeck Signed-off-by: Ralf Baechle --- arch/mips/vdso/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile index 018f8c7b94f2..14568900fc1d 100644 --- a/arch/mips/vdso/Makefile +++ b/arch/mips/vdso/Makefile @@ -26,7 +26,7 @@ aflags-vdso := $(ccflags-vdso) \ # the comments on that file. # ifndef CONFIG_CPU_MIPSR6 - ifeq ($(call ld-ifversion, -lt, 22500000, y),) + ifeq ($(call ld-ifversion, -lt, 22500000, y),y) $(warning MIPS VDSO requires binutils >= 2.25) obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y)) ccflags-vdso += -DDISABLE_MIPS_VDSO -- cgit v1.2.3 From 3d8acd1f667b45c531401c8f0c2033072e32a05d Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Wed, 23 Dec 2015 16:11:35 +0800 Subject: drm/i915: increase the tries for HDMI hotplug live status checking The total delay of HDMI hotplug detecting with 30ms is sometimes not enoughtfor HDMI live status up with specific HDMI monitors in BSW platform. After doing experiments for following monitors, it needs 80ms at least for those worst cases. Lenovo L246 1xwA (4 failed, necessary hot-plug delay: 58/40/60/40ms) Philips HH2AP (9 failed, necessary hot-plug delay: 80/50/50/60/46/40/58/58/39ms) BENQ ET-0035-N (6 failed, necessary hot-plug delay: 60/50/50/80/80/40ms) DELL U2713HM (2 failed, necessary hot-plug delay: 58/59ms) HP HP-LP2475w (5 failed, necessary hot-plug delay: 70/50/40/60/40ms) It looks like 70-80 ms is BSW platform needs in some bad cases of the monitors at this end (8 times delay at most). Keep less than 100ms for HDCP pulse HPD low (with at least 100ms) to respond a plug out. Reviewed-by: Cooper Chiou Tested-by: Gary Wang Cc: Gavin Hindman Cc: Sonika Jindal Cc: Shashank Sharma Cc: Shobhit Kumar Signed-off-by: Gary Wang Link: http://patchwork.freedesktop.org/patch/msgid/1450858295-12804-1-git-send-email-gary.c.wang@intel.com Tested-by: Shobhit Kumar Cc: drm-intel-fixes@lists.freedesktop.org Fixes: 237ed86c693d ("drm/i915: Check live status before reading edid") Signed-off-by: Daniel Vetter (cherry picked from commit f8d03ea0053b23de42c828d559016eabe0b91523) [Jani: undo the file mode change of the original commit] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 64086f2d4e26..e6c035b0fc1c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1381,7 +1381,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - for (try = 0; !live_status && try < 4; try++) { + for (try = 0; !live_status && try < 9; try++) { if (try) msleep(10); live_status = intel_digital_port_connected(dev_priv, -- cgit v1.2.3 From 168309855a7d1e16db751e9c647119fe2d2dc878 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 3 Jan 2016 15:15:37 -0800 Subject: Linux 4.4-rc8 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1122433a5cd5..9d94adeceab6 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 4 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -rc7 +EXTRAVERSION = -rc8 NAME = Blurry Fish Butt # *DOCUMENTATION* -- cgit v1.2.3 From 713a3e4de707fab49d5aa4bceb77db1058572a7b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 30 Dec 2015 23:06:41 +0000 Subject: ftrace/scripts: Fix incorrect use of sprintf in recordmcount Fix build warning: scripts/recordmcount.c:589:4: warning: format not a string literal and no format arguments [-Wformat-security] sprintf("%s: failed\n", file); Fixes: a50bd43935586 ("ftrace/scripts: Have recordmcount copy the object file") Link: http://lkml.kernel.org/r/1451516801-16951-1-git-send-email-colin.king@canonical.com Cc: Li Bin Cc: Russell King Cc: Will Deacon Cc: stable@vger.kernel.org # 2.6.37+ Signed-off-by: Colin Ian King Signed-off-by: Steven Rostedt --- scripts/recordmcount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index 301d70b0174f..e167592793a7 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -586,7 +586,7 @@ main(int argc, char *argv[]) do_file(file); break; case SJ_FAIL: /* error in do_file or below */ - sprintf("%s: failed\n", file); + fprintf(stderr, "%s: failed\n", file); ++n_error; break; case SJ_SUCCEED: /* premature success */ -- cgit v1.2.3 From f36d1be2930ede0a1947686e1126ffda5d5ee1bb Mon Sep 17 00:00:00 2001 From: Qiu Peiyang Date: Thu, 31 Dec 2015 13:11:28 +0800 Subject: tracing: Fix setting of start_index in find_next() When we do cat /sys/kernel/debug/tracing/printk_formats, we hit kernel panic at t_show. general protection fault: 0000 [#1] PREEMPT SMP CPU: 0 PID: 2957 Comm: sh Tainted: G W O 3.14.55-x86_64-01062-gd4acdc7 #2 RIP: 0010:[] [] t_show+0x22/0xe0 RSP: 0000:ffff88002b4ebe80 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000004 RDX: 0000000000000004 RSI: ffffffff81fd26a6 RDI: ffff880032f9f7b1 RBP: ffff88002b4ebe98 R08: 0000000000001000 R09: 000000000000ffec R10: 0000000000000000 R11: 000000000000000f R12: ffff880004d9b6c0 R13: 7365725f6d706400 R14: ffff880004d9b6c0 R15: ffffffff82020570 FS: 0000000000000000(0000) GS:ffff88003aa00000(0063) knlGS:00000000f776bc40 CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033 CR2: 00000000f6c02ff0 CR3: 000000002c2b3000 CR4: 00000000001007f0 Call Trace: [] seq_read+0x2f6/0x3e0 [] vfs_read+0x9b/0x160 [] SyS_read+0x49/0xb0 [] ia32_do_call+0x13/0x13 ---[ end trace 5bd9eb630614861e ]--- Kernel panic - not syncing: Fatal exception When the first time find_next calls find_next_mod_format, it should iterate the trace_bprintk_fmt_list to find the first print format of the module. However in current code, start_index is smaller than *pos at first, and code will not iterate the list. Latter container_of will get the wrong address with former v, which will cause mod_fmt be a meaningless object and so is the returned mod_fmt->fmt. This patch will fix it by correcting the start_index. After fixed, when the first time calls find_next_mod_format, start_index will be equal to *pos, and code will iterate the trace_bprintk_fmt_list to get the right module printk format, so is the returned mod_fmt->fmt. Link: http://lkml.kernel.org/r/5684B900.9000309@intel.com Cc: stable@vger.kernel.org # 3.12+ Fixes: 102c9323c35a8 "tracing: Add __tracepoint_string() to export string pointers" Signed-off-by: Qiu Peiyang Signed-off-by: Steven Rostedt --- kernel/trace/trace_printk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 1c2b28536feb..060df67dbdd1 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -273,6 +273,7 @@ static const char **find_next(void *v, loff_t *pos) if (*pos < last_index + start_index) return __start___tracepoint_str + (*pos - last_index); + start_index += last_index; return find_next_mod_format(start_index, v, fmt, pos); } -- cgit v1.2.3 From b77357b69225a8e68d222451911feab50f2c6652 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 15:02:18 -0500 Subject: qlcnic: correctly handle qlcnic_alloc_mbx_args Since qlcnic_alloc_mbx_args can be failed, return value should be checked. Signed-off-by: Insu Yun Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index a5f422f26cb4..daf05155b732 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -772,8 +772,10 @@ int qlcnic_82xx_config_intrpt(struct qlcnic_adapter *adapter, u8 op_type) int i, err = 0; for (i = 0; i < ahw->num_msix; i++) { - qlcnic_alloc_mbx_args(&cmd, adapter, - QLCNIC_CMD_MQ_TX_CONFIG_INTR); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_MQ_TX_CONFIG_INTR); + if (err) + return err; type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL; val = type | (ahw->intr_tbl[i].type << 4); if (ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX) -- cgit v1.2.3 From 3934aa4c1f7f4ccdff25f530b0e37d776ac453e2 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 17:20:11 -0500 Subject: cxgb4: correctly handling failed allocation Since t4_alloc_mem can be failed in memory pressure, if not properly handled, NULL dereference could be happened. Signed-off-by: Insu Yun Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c index c308429dd9c7..11dd91e4db56 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c +++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c @@ -295,6 +295,10 @@ struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start, INIT_LIST_HEAD(&ctbl->hash_list[i]); cl_list = t4_alloc_mem(clipt_size*sizeof(struct clip_entry)); + if (!cl_list) { + t4_free_mem(ctbl); + return NULL; + } ctbl->cl_list = (void *)cl_list; for (i = 0; i < clipt_size; i++) { -- cgit v1.2.3 From 55285bf09427c5abf43ee1d54e892f352092b1f1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 31 Dec 2015 14:26:33 +0100 Subject: connector: bump skb->users before callback invocation Dmitry reports memleak with syskaller program. Problem is that connector bumps skb usecount but might not invoke callback. So move skb_get to where we invoke the callback. Reported-by: Dmitry Vyukov Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- drivers/connector/connector.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index d7373ca69c99..25693b045371 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -179,26 +179,21 @@ static int cn_call_callback(struct sk_buff *skb) * * It checks skb, netlink header and msg sizes, and calls callback helper. */ -static void cn_rx_skb(struct sk_buff *__skb) +static void cn_rx_skb(struct sk_buff *skb) { struct nlmsghdr *nlh; - struct sk_buff *skb; int len, err; - skb = skb_get(__skb); - if (skb->len >= NLMSG_HDRLEN) { nlh = nlmsg_hdr(skb); len = nlmsg_len(nlh); if (len < (int)sizeof(struct cn_msg) || skb->len < nlh->nlmsg_len || - len > CONNECTOR_MAX_MSG_SIZE) { - kfree_skb(skb); + len > CONNECTOR_MAX_MSG_SIZE) return; - } - err = cn_call_callback(skb); + err = cn_call_callback(skb_get(skb)); if (err < 0) kfree_skb(skb); } -- cgit v1.2.3 From 7ec2541aa7a026874930d6117e86fe2e76fb1587 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Mon, 4 Jan 2016 14:38:46 +0800 Subject: r8152: add reset_resume function When the reset_resume() is called, the flag of SELECTIVE_SUSPEND should be cleared and reinitialize the device, whether the SELECTIVE_SUSPEND is set or not. If reset_resume() is called, it means the power supply is cut or the device is reset. That is, the device wouldn't be in runtime suspend state and the reinitialization is necessary. Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/usb/r8152.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2e32c41536ae..2fb637ad594a 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -3525,6 +3525,14 @@ static int rtl8152_resume(struct usb_interface *intf) return 0; } +static int rtl8152_reset_resume(struct usb_interface *intf) +{ + struct r8152 *tp = usb_get_intfdata(intf); + + clear_bit(SELECTIVE_SUSPEND, &tp->flags); + return rtl8152_resume(intf); +} + static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct r8152 *tp = netdev_priv(dev); @@ -4276,7 +4284,7 @@ static struct usb_driver rtl8152_driver = { .disconnect = rtl8152_disconnect, .suspend = rtl8152_suspend, .resume = rtl8152_resume, - .reset_resume = rtl8152_resume, + .reset_resume = rtl8152_reset_resume, .pre_reset = rtl8152_pre_reset, .post_reset = rtl8152_post_reset, .supports_autosuspend = 1, -- cgit v1.2.3 From b5bdacf3bb027ba0af4d61b38ec289bfc8b64372 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 4 Jan 2016 09:09:27 -0800 Subject: net: Propagate lookup failure in l3mdev_get_saddr to caller Commands run in a vrf context are not failing as expected on a route lookup: root@kenny:~# ip ro ls table vrf-red unreachable default root@kenny:~# ping -I vrf-red -c1 -w1 10.100.1.254 ping: Warning: source address might be selected on device other than vrf-red. PING 10.100.1.254 (10.100.1.254) from 0.0.0.0 vrf-red: 56(84) bytes of data. --- 10.100.1.254 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 999ms Since the vrf table does not have a route for 10.100.1.254 the ping should have failed. The saddr lookup causes a full VRF table lookup. Propogating a lookup failure to the user allows the command to fail as expected: root@kenny:~# ping -I vrf-red -c1 -w1 10.100.1.254 connect: No route to host Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 10 +++++++--- include/net/l3mdev.h | 16 ++++++++++------ include/net/route.h | 7 ++++++- net/ipv4/raw.c | 7 +++++-- net/ipv4/udp.c | 7 +++++-- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 4f9748457f5a..0a242b200df4 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -800,7 +800,7 @@ static struct rtable *vrf_get_rtable(const struct net_device *dev, } /* called under rcu_read_lock */ -static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) +static int vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) { struct fib_result res = { .tclassid = 0 }; struct net *net = dev_net(dev); @@ -808,9 +808,10 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) u8 flags = fl4->flowi4_flags; u8 scope = fl4->flowi4_scope; u8 tos = RT_FL_TOS(fl4); + int rc; if (unlikely(!fl4->daddr)) - return; + return 0; fl4->flowi4_flags |= FLOWI_FLAG_SKIP_NH_OIF; fl4->flowi4_iif = LOOPBACK_IFINDEX; @@ -818,7 +819,8 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) fl4->flowi4_scope = ((tos & RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); - if (!fib_lookup(net, fl4, &res, 0)) { + rc = fib_lookup(net, fl4, &res, 0); + if (!rc) { if (res.type == RTN_LOCAL) fl4->saddr = res.fi->fib_prefsrc ? : fl4->daddr; else @@ -828,6 +830,8 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) fl4->flowi4_flags = flags; fl4->flowi4_tos = orig_tos; fl4->flowi4_scope = scope; + + return rc; } #if IS_ENABLED(CONFIG_IPV6) diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h index 774d85b2d5d9..5689a0c749f7 100644 --- a/include/net/l3mdev.h +++ b/include/net/l3mdev.h @@ -29,7 +29,7 @@ struct l3mdev_ops { /* IPv4 ops */ struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev, const struct flowi4 *fl4); - void (*l3mdev_get_saddr)(struct net_device *dev, + int (*l3mdev_get_saddr)(struct net_device *dev, struct flowi4 *fl4); /* IPv6 ops */ @@ -112,10 +112,11 @@ static inline bool netif_index_is_l3_master(struct net *net, int ifindex) return rc; } -static inline void l3mdev_get_saddr(struct net *net, int ifindex, - struct flowi4 *fl4) +static inline int l3mdev_get_saddr(struct net *net, int ifindex, + struct flowi4 *fl4) { struct net_device *dev; + int rc = 0; if (ifindex) { @@ -124,11 +125,13 @@ static inline void l3mdev_get_saddr(struct net *net, int ifindex, dev = dev_get_by_index_rcu(net, ifindex); if (dev && netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_saddr) { - dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4); + rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4); } rcu_read_unlock(); } + + return rc; } static inline struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev, @@ -200,9 +203,10 @@ static inline bool netif_index_is_l3_master(struct net *net, int ifindex) return false; } -static inline void l3mdev_get_saddr(struct net *net, int ifindex, - struct flowi4 *fl4) +static inline int l3mdev_get_saddr(struct net *net, int ifindex, + struct flowi4 *fl4) { + return 0; } static inline diff --git a/include/net/route.h b/include/net/route.h index ee81307863d5..a3b9ef74a389 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -283,7 +283,12 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4, sport, dport, sk); if (!src && oif) { - l3mdev_get_saddr(net, oif, fl4); + int rc; + + rc = l3mdev_get_saddr(net, oif, fl4); + if (rc < 0) + return ERR_PTR(rc); + src = fl4->saddr; } if (!dst || !src) { diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 63e5be0abd86..bc35f1842512 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -601,8 +601,11 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), daddr, saddr, 0, 0); - if (!saddr && ipc.oif) - l3mdev_get_saddr(net, ipc.oif, &fl4); + if (!saddr && ipc.oif) { + err = l3mdev_get_saddr(net, ipc.oif, &fl4); + if (err < 0) + goto done; + } if (!inet->hdrincl) { rfv.msg = msg; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 0c7b0e61b917..c43890848641 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1025,8 +1025,11 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) flow_flags, faddr, saddr, dport, inet->inet_sport); - if (!saddr && ipc.oif) - l3mdev_get_saddr(net, ipc.oif, fl4); + if (!saddr && ipc.oif) { + err = l3mdev_get_saddr(net, ipc.oif, fl4); + if (err < 0) + goto out; + } security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); rt = ip_route_output_flow(net, fl4, sk); -- cgit v1.2.3 From c845acb324aa85a39650a14e7696982ceea75dc1 Mon Sep 17 00:00:00 2001 From: Rainer Weikusat Date: Sun, 3 Jan 2016 18:56:38 +0000 Subject: af_unix: Fix splice-bind deadlock On 2015/11/06, Dmitry Vyukov reported a deadlock involving the splice system call and AF_UNIX sockets, http://lists.openwall.net/netdev/2015/11/06/24 The situation was analyzed as (a while ago) A: socketpair() B: splice() from a pipe to /mnt/regular_file does sb_start_write() on /mnt C: try to freeze /mnt wait for B to finish with /mnt A: bind() try to bind our socket to /mnt/new_socket_name lock our socket, see it not bound yet decide that it needs to create something in /mnt try to do sb_start_write() on /mnt, block (it's waiting for C). D: splice() from the same pipe to our socket lock the pipe, see that socket is connected try to lock the socket, block waiting for A B: get around to actually feeding a chunk from pipe to file, try to lock the pipe. Deadlock. on 2015/11/10 by Al Viro, http://lists.openwall.net/netdev/2015/11/10/4 The patch fixes this by removing the kern_path_create related code from unix_mknod and executing it as part of unix_bind prior acquiring the readlock of the socket in question. This means that A (as used above) will sb_start_write on /mnt before it acquires the readlock, hence, it won't indirectly block B which first did a sb_start_write and then waited for a thread trying to acquire the readlock. Consequently, A being blocked by C waiting for B won't cause a deadlock anymore (effectively, both A and B acquire two locks in opposite order in the situation described above). Dmitry Vyukov() tested the original patch. Signed-off-by: Rainer Weikusat Signed-off-by: David S. Miller --- net/unix/af_unix.c | 66 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index a4631477cedf..ef05cd9403d4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -953,32 +953,20 @@ fail: return NULL; } -static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) +static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode, + struct path *res) { - struct dentry *dentry; - struct path path; - int err = 0; - /* - * Get the parent directory, calculate the hash for last - * component. - */ - dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - return err; + int err; - /* - * All right, let's create it. - */ - err = security_path_mknod(&path, dentry, mode, 0); + err = security_path_mknod(path, dentry, mode, 0); if (!err) { - err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0); + err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0); if (!err) { - res->mnt = mntget(path.mnt); + res->mnt = mntget(path->mnt); res->dentry = dget(dentry); } } - done_path_create(&path, dentry); + return err; } @@ -989,10 +977,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct unix_sock *u = unix_sk(sk); struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; char *sun_path = sunaddr->sun_path; - int err; + int err, name_err; unsigned int hash; struct unix_address *addr; struct hlist_head *list; + struct path path; + struct dentry *dentry; err = -EINVAL; if (sunaddr->sun_family != AF_UNIX) @@ -1008,14 +998,34 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out; addr_len = err; + name_err = 0; + dentry = NULL; + if (sun_path[0]) { + /* Get the parent directory, calculate the hash for last + * component. + */ + dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); + + if (IS_ERR(dentry)) { + /* delay report until after 'already bound' check */ + name_err = PTR_ERR(dentry); + dentry = NULL; + } + } + err = mutex_lock_interruptible(&u->readlock); if (err) - goto out; + goto out_path; err = -EINVAL; if (u->addr) goto out_up; + if (name_err) { + err = name_err == -EEXIST ? -EADDRINUSE : name_err; + goto out_up; + } + err = -ENOMEM; addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); if (!addr) @@ -1026,11 +1036,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) addr->hash = hash ^ sk->sk_type; atomic_set(&addr->refcnt, 1); - if (sun_path[0]) { - struct path path; + if (dentry) { + struct path u_path; umode_t mode = S_IFSOCK | (SOCK_INODE(sock)->i_mode & ~current_umask()); - err = unix_mknod(sun_path, mode, &path); + err = unix_mknod(dentry, &path, mode, &u_path); if (err) { if (err == -EEXIST) err = -EADDRINUSE; @@ -1038,9 +1048,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out_up; } addr->hash = UNIX_HASH_SIZE; - hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1); + hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1); spin_lock(&unix_table_lock); - u->path = path; + u->path = u_path; list = &unix_socket_table[hash]; } else { spin_lock(&unix_table_lock); @@ -1063,6 +1073,10 @@ out_unlock: spin_unlock(&unix_table_lock); out_up: mutex_unlock(&u->readlock); +out_path: + if (dentry) + done_path_create(&path, dentry); + out: return err; } -- cgit v1.2.3 From c1b27ab5d69099718f519127eea017120c180e71 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 22 Dec 2015 12:28:51 -0500 Subject: tile: provide CONFIG_PAGE_SIZE_64KB etc for tilepro This allows the build system to know that it can't attempt to configure the Lustre virtual block device, for example, when tilepro is using 64KB pages (as it does by default). The tilegx build already provided those symbols. Previously we required that the tilepro hypervisor be rebuilt with a different hardcoded page size in its headers, and then Linux be rebuilt using the updated hypervisor header. Now we allow each of the hypervisor and Linux to be built independently. We still check at boot time to ensure that the page size provided by the hypervisor matches what Linux expects. Signed-off-by: Chris Metcalf Cc: stable@vger.kernel.org [3.19+] --- arch/tile/Kconfig | 11 +++++------ arch/tile/include/asm/page.h | 8 +++++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 106c21bd7f44..8ec7a4599c08 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -176,8 +176,6 @@ config NR_CPUS smaller kernel memory footprint results from using a smaller value on chips with fewer tiles. -if TILEGX - choice prompt "Kernel page size" default PAGE_SIZE_64KB @@ -188,8 +186,11 @@ choice connections, etc., it may be better to select 16KB, which uses memory more efficiently at some cost in TLB performance. - Note that this option is TILE-Gx specific; currently - TILEPro page size is set by rebuilding the hypervisor. + Note that for TILEPro, you must also rebuild the hypervisor + with a matching page size. + +config PAGE_SIZE_4KB + bool "4KB" if TILEPRO config PAGE_SIZE_16KB bool "16KB" @@ -199,8 +200,6 @@ config PAGE_SIZE_64KB endchoice -endif - source "kernel/Kconfig.hz" config KEXEC diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h index a213a8d84a95..8eca6a0e1762 100644 --- a/arch/tile/include/asm/page.h +++ b/arch/tile/include/asm/page.h @@ -20,15 +20,17 @@ #include /* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */ -#if defined(CONFIG_PAGE_SIZE_16KB) +#if defined(CONFIG_PAGE_SIZE_4KB) /* tilepro only */ +#define PAGE_SHIFT 12 +#define CTX_PAGE_FLAG HV_CTX_PG_SM_4K +#elif defined(CONFIG_PAGE_SIZE_16KB) #define PAGE_SHIFT 14 #define CTX_PAGE_FLAG HV_CTX_PG_SM_16K #elif defined(CONFIG_PAGE_SIZE_64KB) #define PAGE_SHIFT 16 #define CTX_PAGE_FLAG HV_CTX_PG_SM_64K #else -#define PAGE_SHIFT HV_LOG2_DEFAULT_PAGE_SIZE_SMALL -#define CTX_PAGE_FLAG 0 +#error Page size not specified in Kconfig #endif #define HPAGE_SHIFT HV_LOG2_DEFAULT_PAGE_SIZE_LARGE -- cgit v1.2.3 From ff62198553e43cdffa9d539f6165d3e83f8a42bc Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 5 Jan 2016 10:46:00 +0100 Subject: bridge: Only call /sbin/bridge-stp for the initial network namespace [I stole this patch from Eric Biederman. He wrote:] > There is no defined mechanism to pass network namespace information > into /sbin/bridge-stp therefore don't even try to invoke it except > for bridge devices in the initial network namespace. > > It is possible for unprivileged users to cause /sbin/bridge-stp to be > invoked for any network device name which if /sbin/bridge-stp does not > guard against unreasonable arguments or being invoked twice on the > same network device could cause problems. [Hannes: changed patch using netns_eq] Cc: Eric W. Biederman Signed-off-by: Eric W. Biederman Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/bridge/br_stp_if.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 12045dea276c..8a7ada8bb947 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -142,7 +142,10 @@ static void br_stp_start(struct net_bridge *br) char *envp[] = { NULL }; struct net_bridge_port *p; - r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); + if (net_eq(dev_net(br->dev), &init_net)) + r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); + else + r = -ENOENT; spin_lock_bh(&br->lock); -- cgit v1.2.3 From 55795ef5469290f89f04e12e662ded604909e462 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 5 Jan 2016 16:23:07 +0100 Subject: net: filter: make JITs zero A for SKF_AD_ALU_XOR_X The SKF_AD_ALU_XOR_X ancillary is not like the other ancillary data instructions since it XORs A with X while all the others replace A with some loaded value. All the BPF JITs fail to clear A if this is used as the first instruction in a filter. This was found using american fuzzy lop. Add a helper to determine if A needs to be cleared given the first instruction in a filter, and use this in the JITs. Except for ARM, the rest have only been compile-tested. Fixes: 3480593131e0 ("net: filter: get rid of BPF_S_* enum") Signed-off-by: Rabin Vincent Acked-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- arch/arm/net/bpf_jit_32.c | 16 +--------------- arch/mips/net/bpf_jit.c | 16 +--------------- arch/powerpc/net/bpf_jit_comp.c | 13 ++----------- arch/sparc/net/bpf_jit_comp.c | 17 ++--------------- include/linux/filter.h | 19 +++++++++++++++++++ 5 files changed, 25 insertions(+), 56 deletions(-) diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 591f9db3bf40..e153eb065fe4 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -187,19 +187,6 @@ static inline int mem_words_used(struct jit_ctx *ctx) return fls(ctx->seen & SEEN_MEM); } -static inline bool is_load_to_a(u16 inst) -{ - switch (inst) { - case BPF_LD | BPF_W | BPF_LEN: - case BPF_LD | BPF_W | BPF_ABS: - case BPF_LD | BPF_H | BPF_ABS: - case BPF_LD | BPF_B | BPF_ABS: - return true; - default: - return false; - } -} - static void jit_fill_hole(void *area, unsigned int size) { u32 *ptr; @@ -211,7 +198,6 @@ static void jit_fill_hole(void *area, unsigned int size) static void build_prologue(struct jit_ctx *ctx) { u16 reg_set = saved_regs(ctx); - u16 first_inst = ctx->skf->insns[0].code; u16 off; #ifdef CONFIG_FRAME_POINTER @@ -241,7 +227,7 @@ static void build_prologue(struct jit_ctx *ctx) emit(ARM_MOV_I(r_X, 0), ctx); /* do not leak kernel data to userspace */ - if ((first_inst != (BPF_RET | BPF_K)) && !(is_load_to_a(first_inst))) + if (bpf_needs_clear_a(&ctx->skf->insns[0])) emit(ARM_MOV_I(r_A, 0), ctx); /* stack space for the BPF_MEM words */ diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index 77cb27309db2..1a8c96035716 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -521,19 +521,6 @@ static inline u16 align_sp(unsigned int num) return num; } -static bool is_load_to_a(u16 inst) -{ - switch (inst) { - case BPF_LD | BPF_W | BPF_LEN: - case BPF_LD | BPF_W | BPF_ABS: - case BPF_LD | BPF_H | BPF_ABS: - case BPF_LD | BPF_B | BPF_ABS: - return true; - default: - return false; - } -} - static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset) { int i = 0, real_off = 0; @@ -614,7 +601,6 @@ static unsigned int get_stack_depth(struct jit_ctx *ctx) static void build_prologue(struct jit_ctx *ctx) { - u16 first_inst = ctx->skf->insns[0].code; int sp_off; /* Calculate the total offset for the stack pointer */ @@ -641,7 +627,7 @@ static void build_prologue(struct jit_ctx *ctx) emit_jit_reg_move(r_X, r_zero, ctx); /* Do not leak kernel data to userspace */ - if ((first_inst != (BPF_RET | BPF_K)) && !(is_load_to_a(first_inst))) + if (bpf_needs_clear_a(&ctx->skf->insns[0])) emit_jit_reg_move(r_A, r_zero, ctx); } diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 04782164ee67..2d66a8446198 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -78,18 +78,9 @@ static void bpf_jit_build_prologue(struct bpf_prog *fp, u32 *image, PPC_LI(r_X, 0); } - switch (filter[0].code) { - case BPF_RET | BPF_K: - case BPF_LD | BPF_W | BPF_LEN: - case BPF_LD | BPF_W | BPF_ABS: - case BPF_LD | BPF_H | BPF_ABS: - case BPF_LD | BPF_B | BPF_ABS: - /* first instruction sets A register (or is RET 'constant') */ - break; - default: - /* make sure we dont leak kernel information to user */ + /* make sure we dont leak kernel information to user */ + if (bpf_needs_clear_a(&filter[0])) PPC_LI(r_A, 0); - } } static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index 22564f5f2364..3e6e05a7c4c2 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c @@ -420,22 +420,9 @@ void bpf_jit_compile(struct bpf_prog *fp) } emit_reg_move(O7, r_saved_O7); - switch (filter[0].code) { - case BPF_RET | BPF_K: - case BPF_LD | BPF_W | BPF_LEN: - case BPF_LD | BPF_W | BPF_ABS: - case BPF_LD | BPF_H | BPF_ABS: - case BPF_LD | BPF_B | BPF_ABS: - /* The first instruction sets the A register (or is - * a "RET 'constant'") - */ - break; - default: - /* Make sure we dont leak kernel information to the - * user. - */ + /* Make sure we dont leak kernel information to the user. */ + if (bpf_needs_clear_a(&filter[0])) emit_clear(r_A); /* A = 0 */ - } for (i = 0; i < flen; i++) { unsigned int K = filter[i].k; diff --git a/include/linux/filter.h b/include/linux/filter.h index 4165e9ac9e36..5972ffe5719a 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -493,6 +493,25 @@ static inline void bpf_jit_free(struct bpf_prog *fp) #define BPF_ANC BIT(15) +static inline bool bpf_needs_clear_a(const struct sock_filter *first) +{ + switch (first->code) { + case BPF_RET | BPF_K: + case BPF_LD | BPF_W | BPF_LEN: + return false; + + case BPF_LD | BPF_W | BPF_ABS: + case BPF_LD | BPF_H | BPF_ABS: + case BPF_LD | BPF_B | BPF_ABS: + if (first->k == SKF_AD_OFF + SKF_AD_ALU_XOR_X) + return true; + return false; + + default: + return true; + } +} + static inline u16 bpf_anc_helper(const struct sock_filter *ftest) { BUG_ON(ftest->code & BPF_ANC); -- cgit v1.2.3 From 60aa3b080a3d2b408af2ca114edb3efc84ad1838 Mon Sep 17 00:00:00 2001 From: One Thousand Gnomes Date: Tue, 5 Jan 2016 11:51:25 +0000 Subject: 6pack: fix free memory scribbles commit acf673a3187edf72068ee2f92f4dc47d66baed47 fixed a user triggerable free memory scribble but in doing so replaced it with a different one that allows the user to control the data and scribble even more. sixpack_close is called by the tty layer in tty context. The tty context is protected by sp_get() and sp_put(). However network layer activity via sp_xmit() is not protected this way. We must therefore stop the queue otherwise the user gets to dump a buffer mostly of their choice into freed kernel pages. Signed-off-by: Alan Cox Signed-off-by: David S. Miller --- drivers/net/hamradio/6pack.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 9f0b1c342b77..5a1e98547031 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -683,6 +683,12 @@ static void sixpack_close(struct tty_struct *tty) if (!atomic_dec_and_test(&sp->refcnt)) down(&sp->dead_sem); + /* We must stop the queue to avoid potentially scribbling + * on the free buffers. The sp->dead_sem is not sufficient + * to protect us from sp->xbuff access. + */ + netif_stop_queue(sp->dev); + del_timer_sync(&sp->tx_t); del_timer_sync(&sp->resync_t); -- cgit v1.2.3 From f941461c925832fbeb7876b794ab9fbec6a7a8af Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 5 Jan 2016 18:34:04 +0100 Subject: ARM: net: bpf: fix zero right shift The LSR instruction cannot be used to perform a zero right shift since a 0 as the immediate value (imm5) in the LSR instruction encoding means that a shift of 32 is perfomed. See DecodeIMMShift() in the ARM ARM. Make the JIT skip generation of the LSR if a zero-shift is requested. This was found using american fuzzy lop. Signed-off-by: Rabin Vincent Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- arch/arm/net/bpf_jit_32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index e153eb065fe4..93d0b6d0b63e 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -756,7 +756,8 @@ load_ind: case BPF_ALU | BPF_RSH | BPF_K: if (unlikely(k > 31)) return -1; - emit(ARM_LSR_I(r_A, r_A, k), ctx); + if (k) + emit(ARM_LSR_I(r_A, r_A, k), ctx); break; case BPF_ALU | BPF_RSH | BPF_X: update_on_xread(ctx); -- cgit v1.2.3 From 73c20a8b7245273125cfe92c4b46e6fdb568a801 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Tue, 5 Jan 2016 09:11:36 -0800 Subject: net: sched: fix missing free per cpu on qstats When a qdisc is using per cpu stats (currently just the ingress qdisc) only the bstats are being freed. This also free's the qstats. Fixes: b0ab6f92752b9f9d8 ("net: sched: enable per cpu qstats") Signed-off-by: John Fastabend Acked-by: Eric Dumazet Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/sched/sch_generic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index e82a1ad80aa5..16bc83b2842a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -658,8 +658,10 @@ static void qdisc_rcu_free(struct rcu_head *head) { struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head); - if (qdisc_is_percpu_stats(qdisc)) + if (qdisc_is_percpu_stats(qdisc)) { free_percpu(qdisc->cpu_bstats); + free_percpu(qdisc->cpu_qstats); + } kfree((char *) qdisc - qdisc->padded); } -- cgit v1.2.3 From 07a5d38453599052aff0877b16bb9c1585f08609 Mon Sep 17 00:00:00 2001 From: Francesco Ruggeri Date: Wed, 6 Jan 2016 00:18:48 -0800 Subject: net: possible use after free in dst_release dst_release should not access dst->flags after decrementing __refcnt to 0. The dst_entry may be in dst_busy_list and dst_gc_task may dst_destroy it before dst_release gets a chance to access dst->flags. Fixes: d69bbf88c8d0 ("net: fix a race in dst_release()") Fixes: 27b75c95f10d ("net: avoid RCU for NOCACHE dst") Signed-off-by: Francesco Ruggeri Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dst.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dst.c b/net/core/dst.c index e6dc77252fe9..a1656e3b8d72 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -301,12 +301,13 @@ void dst_release(struct dst_entry *dst) { if (dst) { int newrefcnt; + unsigned short nocache = dst->flags & DST_NOCACHE; newrefcnt = atomic_dec_return(&dst->__refcnt); if (unlikely(newrefcnt < 0)) net_warn_ratelimited("%s: dst:%p refcnt:%d\n", __func__, dst, newrefcnt); - if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE)) + if (!newrefcnt && unlikely(nocache)) call_rcu(&dst->rcu_head, dst_destroy_rcu); } } -- cgit v1.2.3 From fde55c45d2175bd3e33aa28ee31e4ea6efa354e1 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 6 Jan 2016 14:55:02 +0000 Subject: mkiss: fix scribble on freed memory commit d79f16c046086f4fe0d42184a458e187464eb83e fixed a user triggerable scribble on free memory but added a new one which allows the user to scribble even more and user controlled data into freed space. As with 6pack we need to halt the queue before we free the buffers, because the transmit logic is not protected by the semaphore. Signed-off-by: Alan Cox Signed-off-by: David S. Miller --- drivers/net/hamradio/mkiss.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 0b72b9de5207..85828f153445 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -797,6 +797,11 @@ static void mkiss_close(struct tty_struct *tty) */ if (!atomic_dec_and_test(&ax->refcnt)) down(&ax->dead_sem); + /* + * Halt the transmit queue so that a new transmit cannot scribble + * on our buffers + */ + netif_stop_queue(ax->dev); /* Free all AX25 frame buffers. */ kfree(ax->rbuff); -- cgit v1.2.3 From e439bd4a4fdeb29488f48f14845ad35607e6302c Mon Sep 17 00:00:00 2001 From: Kristian Evensen Date: Wed, 6 Jan 2016 14:15:50 +0100 Subject: net: qmi_wwan: Add WeTelecom-WPD600N MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The WeTelecom-WPD600N is an LTE module that, in addition to supporting most "normal" bands, also supports LTE over 450MHz. Manual testing showed that only interface number three replies to QMI messages. Cc: Bjørn Mork Signed-off-by: Kristian Evensen Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 9a5be8b85186..5fccc5a8153f 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -742,6 +742,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ + {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -- cgit v1.2.3 From 58caf637365fef97c8e84ea5699a8e34d68fce93 Mon Sep 17 00:00:00 2001 From: Shrikrishna Khare Date: Wed, 6 Jan 2016 10:44:27 -0800 Subject: Driver: Vmxnet3: Fix regression caused by 5738a09 Reported-by: Bingkuo Liu Signed-off-by: Shrikrishna Khare Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 8 ++++---- drivers/net/vmxnet3/vmxnet3_int.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 417903715437..0cbf520cea77 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1380,10 +1380,10 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, skip_page_frags = true; goto rcd_done; } - new_dma_addr = dma_map_page(&adapter->pdev->dev - , rbi->page, - 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); + new_dma_addr = dma_map_page(&adapter->pdev->dev, + new_page, + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); if (dma_mapping_error(&adapter->pdev->dev, new_dma_addr)) { put_page(new_page); diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 4c58c83dc225..bdb8a6c0f8aa 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -69,10 +69,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.4.4.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.4.5.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01040400 +#define VMXNET3_DRIVER_VERSION_NUM 0x01040500 #if defined(CONFIG_PCI_MSI) /* RSS only makes sense if MSI-X is supported. */ -- cgit v1.2.3 From 8b8a321ff72c785ed5e8b4cf6eda20b35d427390 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Wed, 6 Jan 2016 12:42:38 -0800 Subject: tcp: fix zero cwnd in tcp_cwnd_reduction Patch 3759824da87b ("tcp: PRR uses CRB mode by default and SS mode conditionally") introduced a bug that cwnd may become 0 when both inflight and sndcnt are 0 (cwnd = inflight + sndcnt). This may lead to a div-by-zero if the connection starts another cwnd reduction phase by setting tp->prior_cwnd to the current cwnd (0) in tcp_init_cwnd_reduction(). To prevent this we skip PRR operation when nothing is acked or sacked. Then cwnd must be positive in all cases as long as ssthresh is positive: 1) The proportional reduction mode inflight > ssthresh > 0 2) The reduction bound mode a) inflight == ssthresh > 0 b) inflight < ssthresh sndcnt > 0 since newly_acked_sacked > 0 and inflight < ssthresh Therefore in all cases inflight and sndcnt can not both be 0. We check invalid tp->prior_cwnd to avoid potential div0 bugs. In reality this bug is triggered only with a sequence of less common events. For example, the connection is terminating an ECN-triggered cwnd reduction with an inflight 0, then it receives reordered/old ACKs or DSACKs from prior transmission (which acks nothing). Or the connection is in fast recovery stage that marks everything lost, but fails to retransmit due to local issues, then receives data packets from other end which acks nothing. Fixes: 3759824da87b ("tcp: PRR uses CRB mode by default and SS mode conditionally") Reported-by: Oleksandr Natalenko Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2d656eef7f8e..d4c51158470f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2478,6 +2478,9 @@ static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, int newly_acked_sacked = prior_unsacked - (tp->packets_out - tp->sacked_out); + if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) + return; + tp->prr_delivered += newly_acked_sacked; if (delta < 0) { u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + -- cgit v1.2.3