Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1443159 > unrolled thread

[PATCH 3.12 00/88] 3.12.62-stable review

Started byJiri Slaby <jslaby@suse.cz>
First post2016-07-14 10:20 +0200
Last post2016-07-14 23:50 +0200
Articles 20 on this page of 98 — 8 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 3.12 00/88] 3.12.62-stable review Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
    [PATCH 3.12 01/88] PCI/AER: Clear error status registers during enumeration and restore Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 10/88] sparc64: Fix return from trap window fill crashes. Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 86/88] cdc_ncm: workaround for EM7455 "silent" data interface Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 40/88] netfilter: x_tables: xt_compat_match_from_user doesn't need a retval Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 15/88] tcp: record TLP and ER timer stats in v6 stats Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 62/88] NFS: Fix another OPEN_DOWNGRADE bug Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 38/88] netfilter: ip_tables: simplify translate_compat_table args Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 61/88] make nfs_atomic_open() call d_drop() on all ->open_context() errors. Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 85/88] HID: elo: kill not flush the work Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 83/88] HID: hiddev: validate num_values for HIDIOCGUSAGES, HIDIOCSUSAGES commands Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:20 +0200
      [PATCH 3.12 64/88] mm: Export migrate_page_move_mapping and migrate_page_copy Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 53/88] mac80211_hwsim: Add missing check for HWSIM_ATTR_SIGNAL Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 60/88] x86/amd_nb: Fix boot crash on non-AMD systems Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 65/88] UBIFS: Implement ->migratepage() Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 81/88] KVM: x86: expose invariant tsc cpuid bit (v2) Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
        Re: [PATCH 3.12 81/88] KVM: x86: expose invariant tsc cpuid bit (v2) Paolo Bonzini <pbonzini@redhat.com> - 2016-07-14 10:50 +0200
          Re: [PATCH 3.12 81/88] KVM: x86: expose invariant tsc cpuid bit (v2) Jiri Slaby <jslaby@suse.cz> - 2016-07-14 11:30 +0200
            Re: [PATCH 3.12 81/88] KVM: x86: expose invariant tsc cpuid bit (v2) Paolo Bonzini <pbonzini@redhat.com> - 2016-07-14 11:50 +0200
      [PATCH 3.12 79/88] KEYS: potential uninitialized variable Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 76/88] rds: fix an infoleak in rds_inc_info_copy Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 80/88] base: make module_create_drivers_dir race-free Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 78/88] SCSI: Increase REPORT_LUNS timeout Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 71/88] ALSA: hrtimer: Handle start/stop more properly Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 84/88] ALSA: compress: fix an integer overflow check Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 58/88] x86, build: copy ldlinux.c32 to image.iso Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 75/88] net/qlge: Avoids recursive EEH error Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 69/88] USB: usbfs: fix potential infoleak in devio Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 52/88] mac80211: mesh: flush mesh paths unconditionally Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 54/88] IB/mlx4: Properly initialize GRH TClass and FlowLabel in AHs Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 70/88] ktime: export ktime_divns Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 57/88] USB: EHCI: declare hostpc register as zero-length array Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 50/88] usb: musb: Stop bulk endpoint while queue is rotated Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 72/88] ALSA: timer: Fix leak in SNDRV_TIMER_IOCTL_PARAMS Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 73/88] ALSA: timer: Fix leak in events via snd_timer_user_ccallback Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 56/88] powerpc/pseries: Fix PCI config address for DDW Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 68/88] Bridge: Fix ipv6 mc snooping if bridge has no ipv6 address Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 63/88] ARM: 8578/1: mm: ensure pmd_present only checks the valid bit Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 74/88] ALSA: timer: Fix leak in events via snd_timer_user_tinterrupt Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 67/88] scsi_lib: correctly retry failed zero length REQ_TYPE_FS commands Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 77/88] EDAC: Remove arbitrary limit on number of channels Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 59/88] kprobes/x86: Clear TF bit in fault on single-stepping Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 55/88] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 66/88] scsi: remove scsi_end_request Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:30 +0200
      [PATCH 3.12 37/88] netfilter: arp_tables: simplify translate_compat_table args Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 51/88] usb: musb: Ensure rx reinit occurs for shared_fifo endpoints Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 45/88] crypto: ux500 - memmove the right size Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 43/88] Revert "netfilter: ensure number of counters is >0 in do_replace()" Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 48/88] net: alx: Work around the DMA RX overflow issue Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 47/88] ipmr/ip6mr: Initialize the last assert time of mfc entries. Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 44/88] netfilter: x_tables: introduce and use xt_copy_counters_from_user Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 46/88] sit: correct IP protocol used in ipip6_err Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 41/88] netfilter: ensure number of counters is >0 in do_replace() Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
        Re: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via  translate_table Michal Kubecek <mkubecek@suse.cz> - 2016-07-19 09:20 +0200
          Re: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via  translate_table Florian Westphal <fw@strlen.de> - 2016-07-19 10:50 +0200
            Re: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via  translate_table Florian Westphal <fw@strlen.de> - 2016-07-19 11:20 +0200
              Re: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via  translate_table Michal Kubecek <mkubecek@suse.cz> - 2016-07-19 11:50 +0200
      [PATCH 3.12 49/88] usb: quirks: Add no-lpm quirk for Acer C120 LED Projector Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:40 +0200
      [PATCH 3.12 19/88] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 28/88] netfilter: x_tables: validate targets of jumps Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
        Re: [PATCH 3.12 28/88] netfilter: x_tables: validate targets of jumps Jiri Slaby <jirislaby@gmail.com> - 2016-07-21 08:40 +0200
          Re: [PATCH 3.12 28/88] netfilter: x_tables: validate targets of jumps Greg KH <greg@kroah.com> - 2016-07-21 21:00 +0200
            Re: [PATCH 3.12 28/88] netfilter: x_tables: validate targets of jumps Jiri Slaby <jslaby@suse.cz> - 2016-07-21 21:10 +0200
              Re: [PATCH 3.12 28/88] netfilter: x_tables: validate targets of jumps Michal Kubecek <mkubecek@suse.cz> - 2016-07-25 07:50 +0200
                Re: [PATCH 3.12 28/88] netfilter: x_tables: validate targets of jumps Michal Kubecek <mkubecek@suse.cz> - 2016-07-25 09:00 +0200
                  Re: [PATCH 3.12 28/88] netfilter: x_tables: validate targets of jumps Florian Westphal <fw@strlen.de> - 2016-07-25 09:30 +0200
                Re: [PATCH 3.12 28/88] netfilter: x_tables: validate targets of jumps Florian Westphal <fw@strlen.de> - 2016-07-25 09:10 +0200
      [PATCH 3.12 11/88] perf/x86: Honor the architectural performance monitoring version Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 09/88] sparc: Harden signal return frame checks. Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 22/88] powerpc: Use privileged SPR number for MMCR2 Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 20/88] ARM: fix PTRACE_SETVFPREGS on SMP systems Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 21/88] powerpc: Fix definition of SIAR and SDAR registers Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 02/88] MIPS: Fix 64k page support for 32 bit kernels. Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 25/88] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 13/88] netlink: Fix dump skb leak/double free Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 29/88] netfilter: x_tables: add and use xt_check_entry_offsets Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 24/88] ecryptfs: forbid opening files without mmap handler Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 18/88] drivers: macintosh: rack-meter: limit idle ticks to total ticks Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 17/88] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 06/88] sparc64: Fix sparc64_set_context stack handling. Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 36/88] netfilter: x_tables: don't reject valid target size on some architectures Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 05/88] sparc64: Fix bootup regressions on some Kconfig combinations. Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 26/88] fix d_walk()/non-delayed __d_free() race Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 23/88] parisc: Fix pagefault crash in unaligned __get_user() call Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 31/88] netfilter: x_tables: assert minimum target size Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 33/88] netfilter: x_tables: check standard target size too Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 12/88] perf/x86: Fix undefined shift on 32-bit kernels Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 30/88] netfilter: x_tables: kill check_entry helper Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 16/88] ipv6: Skip XFRM lookup if dst_entry in socket cache is valid Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 34/88] netfilter: x_tables: check for bogus target offset Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 32/88] netfilter: x_tables: add compat version of xt_check_entry_offsets Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 07/88] sparc/PCI: Fix for panic while enabling SR-IOV Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 35/88] netfilter: x_tables: validate all offsets and sizes in a rule Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
      [PATCH 3.12 27/88] netfilter: x_tables: don't move to non-existent next rule Jiri Slaby <jslaby@suse.cz> - 2016-07-14 10:50 +0200
    Re: [PATCH 3.12 00/88] 3.12.62-stable review Guenter Roeck <linux@roeck-us.net> - 2016-07-14 22:30 +0200
      Re: [PATCH 3.12 00/88] 3.12.62-stable review Jiri Slaby <jslaby@suse.cz> - 2016-07-15 09:40 +0200
    Re: [PATCH 3.12 00/88] 3.12.62-stable review Shuah Khan <shuahkh@osg.samsung.com> - 2016-07-14 23:50 +0200

Page 3 of 5 — ← Prev page 1 2 [3] 4 5  Next page →


#1443216 — [PATCH 3.12 77/88] EDAC: Remove arbitrary limit on number of channels

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:30 +0200
Subject[PATCH 3.12 77/88] EDAC: Remove arbitrary limit on number of channels
Message-ID<rUKbX-7dQ-133@gated-at.bofh.it>
In reply to#1443166
From: Tony Luck <tony.luck@intel.com>

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

===============

commit c44696fff04ff62f65441afe9ea244b47653dd6d upstream.

Currently set to "6", but the reset of the code will dynamically
allocate as needed.  We need to go to "8" today, but drop the check
completely to save doing this again when we need even larger numbers.

Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Aristeu Rozanski <aris@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/edac/edac_mc_sysfs.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index e5fde4382552..252e2fc83e8e 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -305,8 +305,6 @@ static struct device_type csrow_attr_type = {
  *
  */
 
-#define EDAC_NR_CHANNELS	6
-
 DEVICE_CHANNEL(ch0_dimm_label, S_IRUGO | S_IWUSR,
 	channel_dimm_label_show, channel_dimm_label_store, 0);
 DEVICE_CHANNEL(ch1_dimm_label, S_IRUGO | S_IWUSR,
@@ -370,9 +368,6 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
 {
 	int err, chan;
 
-	if (csrow->nr_channels >= EDAC_NR_CHANNELS)
-		return -ENODEV;
-
 	csrow->dev.type = &csrow_attr_type;
 	csrow->dev.bus = mci->bus;
 	device_initialize(&csrow->dev);
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443217 — [PATCH 3.12 59/88] kprobes/x86: Clear TF bit in fault on single-stepping

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:30 +0200
Subject[PATCH 3.12 59/88] kprobes/x86: Clear TF bit in fault on single-stepping
Message-ID<rUKbX-7dQ-135@gated-at.bofh.it>
In reply to#1443166
From: Masami Hiramatsu <mhiramat@kernel.org>

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

===============

commit dcfc47248d3f7d28df6f531e6426b933de94370d upstream.

Fix kprobe_fault_handler() to clear the TF (trap flag) bit of
the flags register in the case of a fault fixup on single-stepping.

If we put a kprobe on the instruction which caused a
page fault (e.g. actual mov instructions in copy_user_*),
that fault happens on the single-stepping buffer. In this
case, kprobes resets running instance so that the CPU can
retry execution on the original ip address.

However, current code forgets to reset the TF bit. Since this
fault happens with TF bit set for enabling single-stepping,
when it retries, it causes a debug exception and kprobes
can not handle it because it already reset itself.

On the most of x86-64 platform, it can be easily reproduced
by using kprobe tracer. E.g.

  # cd /sys/kernel/debug/tracing
  # echo p copy_user_enhanced_fast_string+5 > kprobe_events
  # echo 1 > events/kprobes/enable

And you'll see a kernel panic on do_debug(), since the debug
trap is not handled by kprobes.

To fix this problem, we just need to clear the TF bit when
resetting running kprobe.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: systemtap@sourceware.org
Link: http://lkml.kernel.org/r/20160611140648.25885.37482.stgit@devbox
[ Updated the comments. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 arch/x86/kernel/kprobes/core.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 490fee15fea5..6cd32acb376f 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -911,7 +911,19 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 		 * normal page fault.
 		 */
 		regs->ip = (unsigned long)cur->addr;
+		/*
+		 * Trap flag (TF) has been set here because this fault
+		 * happened where the single stepping will be done.
+		 * So clear it by resetting the current kprobe:
+		 */
+		regs->flags &= ~X86_EFLAGS_TF;
+
+		/*
+		 * If the TF flag was set before the kprobe hit,
+		 * don't touch it:
+		 */
 		regs->flags |= kcb->kprobe_old_flags;
+
 		if (kcb->kprobe_status == KPROBE_REENTER)
 			restore_previous_kprobe(kcb);
 		else
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443218 — [PATCH 3.12 55/88] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:30 +0200
Subject[PATCH 3.12 55/88] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism
Message-ID<rUKbY-7dQ-137@gated-at.bofh.it>
In reply to#1443166
From: "Guilherme G. Piccoli" <gpiccoli@linux.vnet.ibm.com>

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

===============

commit 8445a87f7092bc8336ea1305be9306f26b846d93 upstream.

Commit 39baadbf36ce ("powerpc/eeh: Remove eeh information from pci_dn")
changed the pci_dn struct by removing its EEH-related members.
As part of this clean-up, DDW mechanism was modified to read the device
configuration address from eeh_dev struct.

As a consequence, now if we disable EEH mechanism on kernel command-line
for example, the DDW mechanism will fail, generating a kernel oops by
dereferencing a NULL pointer (which turns to be the eeh_dev pointer).

This patch just changes the configuration address calculation on DDW
functions to a manual calculation based on pci_dn members instead of
using eeh_dev-based address.

No functional changes were made. This was tested on pSeries, both
in PHyp and qemu guest.

Fixes: 39baadbf36ce ("powerpc/eeh: Remove eeh information from pci_dn")
Reviewed-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 arch/powerpc/platforms/pseries/iommu.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 261c5095d5d3..88cbecbdbd6f 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -861,7 +861,8 @@ machine_arch_initcall(pseries, find_existing_ddw_windows);
 static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 			struct ddw_query_response *query)
 {
-	struct eeh_dev *edev;
+	struct device_node *dn;
+	struct pci_dn *pdn;
 	u32 cfg_addr;
 	u64 buid;
 	int ret;
@@ -872,11 +873,10 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 	 * Retrieve them from the pci device, not the node with the
 	 * dma-window property
 	 */
-	edev = pci_dev_to_eeh_dev(dev);
-	cfg_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		cfg_addr = edev->pe_config_addr;
-	buid = edev->phb->buid;
+	dn = pci_device_to_OF_node(dev);
+	pdn = PCI_DN(dn);
+	buid = pdn->phb->buid;
+	cfg_addr = (pdn->busno << 8) | pdn->devfn;
 
 	ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
 		  cfg_addr, BUID_HI(buid), BUID_LO(buid));
@@ -890,7 +890,8 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 			struct ddw_create_response *create, int page_shift,
 			int window_shift)
 {
-	struct eeh_dev *edev;
+	struct device_node *dn;
+	struct pci_dn *pdn;
 	u32 cfg_addr;
 	u64 buid;
 	int ret;
@@ -901,11 +902,10 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 	 * Retrieve them from the pci device, not the node with the
 	 * dma-window property
 	 */
-	edev = pci_dev_to_eeh_dev(dev);
-	cfg_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		cfg_addr = edev->pe_config_addr;
-	buid = edev->phb->buid;
+	dn = pci_device_to_OF_node(dev);
+	pdn = PCI_DN(dn);
+	buid = pdn->phb->buid;
+	cfg_addr = (pdn->busno << 8) | pdn->devfn;
 
 	do {
 		/* extra outputs are LIOBN and dma-addr (hi, lo) */
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443220 — [PATCH 3.12 66/88] scsi: remove scsi_end_request

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:30 +0200
Subject[PATCH 3.12 66/88] scsi: remove scsi_end_request
Message-ID<rUKbY-7dQ-145@gated-at.bofh.it>
In reply to#1443166
From: Christoph Hellwig <hch@lst.de>

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

===============

commit bc85dc500f9df9b2eec15077e5046672c46adeaa upstream.

By folding scsi_end_request into its only caller we can significantly clean
up the completion logic.  We can use simple goto labels now to only have
a single place to finish or requeue command there instead of the previous
convoluted logic.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Nicholas Bellinger <nab@linux-iscsi.org>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Reviewed-by: Hannes Reinecke <hare@suse.de>
[jwang: backport to 3.12]
Signed-off-by: Jack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/scsi/scsi_lib.c | 113 +++++++++++++-----------------------------------
 1 file changed, 31 insertions(+), 82 deletions(-)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 2b01c88ad416..4b7893364c7a 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -540,66 +540,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
 
 static void __scsi_release_buffers(struct scsi_cmnd *, int);
 
-/*
- * Function:    scsi_end_request()
- *
- * Purpose:     Post-processing of completed commands (usually invoked at end
- *		of upper level post-processing and scsi_io_completion).
- *
- * Arguments:   cmd	 - command that is complete.
- *              error    - 0 if I/O indicates success, < 0 for I/O error.
- *              bytes    - number of bytes of completed I/O
- *		requeue  - indicates whether we should requeue leftovers.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns:     cmd if requeue required, NULL otherwise.
- *
- * Notes:       This is called for block device requests in order to
- *              mark some number of sectors as complete.
- * 
- *		We are guaranteeing that the request queue will be goosed
- *		at some point during this call.
- * Notes:	If cmd was requeued, upon return it will be a stale pointer.
- */
-static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
-					  int bytes, int requeue)
-{
-	struct request_queue *q = cmd->device->request_queue;
-	struct request *req = cmd->request;
-
-	/*
-	 * If there are blocks left over at the end, set up the command
-	 * to queue the remainder of them.
-	 */
-	if (blk_end_request(req, error, bytes)) {
-		/* kill remainder if no retrys */
-		if (error && scsi_noretry_cmd(cmd))
-			blk_end_request_all(req, error);
-		else {
-			if (requeue) {
-				/*
-				 * Bleah.  Leftovers again.  Stick the
-				 * leftovers in the front of the
-				 * queue, and goose the queue again.
-				 */
-				scsi_release_buffers(cmd);
-				scsi_requeue_command(q, cmd);
-				cmd = NULL;
-			}
-			return cmd;
-		}
-	}
-
-	/*
-	 * This will goose the queue request function at the end, so we don't
-	 * need to worry about launching another command.
-	 */
-	__scsi_release_buffers(cmd, 0);
-	scsi_next_command(cmd);
-	return NULL;
-}
-
 static inline unsigned int scsi_sgtable_index(unsigned short nents)
 {
 	unsigned int index;
@@ -751,16 +691,9 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
  *
  * Returns:     Nothing
  *
- * Notes:       This function is matched in terms of capabilities to
- *              the function that created the scatter-gather list.
- *              In other words, if there are no bounce buffers
- *              (the normal case for most drivers), we don't need
- *              the logic to deal with cleaning up afterwards.
- *
- *		We must call scsi_end_request().  This will finish off
- *		the specified number of sectors.  If we are done, the
- *		command block will be released and the queue function
- *		will be goosed.  If we are not done then we have to
+ * Notes:       We will finish off the specified number of sectors.  If we
+ *		are done, the command block will be released and the queue
+ *		function will be goosed.  If we are not done then we have to
  *		figure out what to do next:
  *
  *		a) We can call scsi_requeue_command().  The request
@@ -769,7 +702,7 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
  *		   be used if we made forward progress, or if we want
  *		   to switch from READ(10) to READ(6) for example.
  *
- *		b) We can call scsi_queue_insert().  The request will
+ *		b) We can call __scsi_queue_insert().  The request will
  *		   be put back on the queue and retried using the same
  *		   command as before, possibly after a delay.
  *
@@ -873,12 +806,25 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 	}
 
 	/*
-	 * A number of bytes were successfully read.  If there
-	 * are leftovers and there is some kind of error
-	 * (result != 0), retry the rest.
+	 * If we finished all bytes in the request we are done now.
 	 */
-	if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
-		return;
+	if (!blk_end_request(req, error, good_bytes))
+		goto next_command;
+
+	/*
+	 * Kill remainder if no retrys.
+	 */
+	if (error && scsi_noretry_cmd(cmd)) {
+		blk_end_request_all(req, error);
+		goto next_command;
+	}
+
+	/*
+	 * If there had been no error, but we have leftover bytes in the
+	 * requeues just queue the command up again.
+	 */
+	if (result == 0)
+		goto requeue;
 
 	error = __scsi_error_from_host_byte(cmd, result);
 
@@ -1000,7 +946,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 	switch (action) {
 	case ACTION_FAIL:
 		/* Give up and fail the remainder of the request */
-		scsi_release_buffers(cmd);
 		if (!(req->cmd_flags & REQ_QUIET)) {
 			if (description)
 				scmd_printk(KERN_INFO, cmd, "%s\n",
@@ -1010,12 +955,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 				scsi_print_sense("", cmd);
 			scsi_print_command(cmd);
 		}
-		if (blk_end_request_err(req, error))
-			scsi_requeue_command(q, cmd);
-		else
-			scsi_next_command(cmd);
-		break;
+		if (!blk_end_request_err(req, error))
+			goto next_command;
+		/*FALLTHRU*/
 	case ACTION_REPREP:
+	requeue:
 		/* Unprep the request and put it back at the head of the queue.
 		 * A new command will be prepared and issued.
 		 */
@@ -1031,6 +975,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 		__scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY, 0);
 		break;
 	}
+	return;
+
+next_command:
+	__scsi_release_buffers(cmd, 0);
+	scsi_next_command(cmd);
 }
 
 static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443230 — [PATCH 3.12 37/88] netfilter: arp_tables: simplify translate_compat_table args

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 37/88] netfilter: arp_tables: simplify translate_compat_table args
Message-ID<rUKlA-7jX-21@gated-at.bofh.it>
In reply to#1443166
From: Florian Westphal <fw@strlen.de>

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

===============

commit 8dddd32756f6fe8e4e82a63361119b7e2384e02f upstream.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 net/ipv4/netfilter/arp_tables.c | 82 ++++++++++++++++++-----------------------
 1 file changed, 36 insertions(+), 46 deletions(-)

diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 37550a103f88..cf6aa304a4f5 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1200,6 +1200,18 @@ static int do_add_counters(struct net *net, const void __user *user,
 }
 
 #ifdef CONFIG_COMPAT
+struct compat_arpt_replace {
+	char				name[XT_TABLE_MAXNAMELEN];
+	u32				valid_hooks;
+	u32				num_entries;
+	u32				size;
+	u32				hook_entry[NF_ARP_NUMHOOKS];
+	u32				underflow[NF_ARP_NUMHOOKS];
+	u32				num_counters;
+	compat_uptr_t			counters;
+	struct compat_arpt_entry	entries[0];
+};
+
 static inline void compat_release_entry(struct compat_arpt_entry *e)
 {
 	struct xt_entry_target *t;
@@ -1215,8 +1227,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
 				  const unsigned char *base,
 				  const unsigned char *limit,
 				  const unsigned int *hook_entries,
-				  const unsigned int *underflows,
-				  const char *name)
+				  const unsigned int *underflows)
 {
 	struct xt_entry_target *t;
 	struct xt_target *target;
@@ -1287,7 +1298,7 @@ out:
 
 static int
 compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
-			    unsigned int *size, const char *name,
+			    unsigned int *size,
 			    struct xt_table_info *newinfo, unsigned char *base)
 {
 	struct xt_entry_target *t;
@@ -1320,14 +1331,9 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
 	return ret;
 }
 
-static int translate_compat_table(const char *name,
-				  unsigned int valid_hooks,
-				  struct xt_table_info **pinfo,
+static int translate_compat_table(struct xt_table_info **pinfo,
 				  void **pentry0,
-				  unsigned int total_size,
-				  unsigned int number,
-				  unsigned int *hook_entries,
-				  unsigned int *underflows)
+				  const struct compat_arpt_replace *compatr)
 {
 	unsigned int i, j;
 	struct xt_table_info *newinfo, *info;
@@ -1339,8 +1345,8 @@ static int translate_compat_table(const char *name,
 
 	info = *pinfo;
 	entry0 = *pentry0;
-	size = total_size;
-	info->number = number;
+	size = compatr->size;
+	info->number = compatr->num_entries;
 
 	/* Init all hooks to impossible value. */
 	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
@@ -1351,40 +1357,39 @@ static int translate_compat_table(const char *name,
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(NFPROTO_ARP);
-	xt_compat_init_offsets(NFPROTO_ARP, number);
+	xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries);
 	/* Walk through entries, checking offsets. */
-	xt_entry_foreach(iter0, entry0, total_size) {
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
 							entry0,
-							entry0 + total_size,
-							hook_entries,
-							underflows,
-							name);
+							entry0 + compatr->size,
+							compatr->hook_entry,
+							compatr->underflow);
 		if (ret != 0)
 			goto out_unlock;
 		++j;
 	}
 
 	ret = -EINVAL;
-	if (j != number) {
+	if (j != compatr->num_entries) {
 		duprintf("translate_compat_table: %u not %u entries\n",
-			 j, number);
+			 j, compatr->num_entries);
 		goto out_unlock;
 	}
 
 	/* Check hooks all assigned */
 	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
 		/* Only hooks which are valid */
-		if (!(valid_hooks & (1 << i)))
+		if (!(compatr->valid_hooks & (1 << i)))
 			continue;
 		if (info->hook_entry[i] == 0xFFFFFFFF) {
 			duprintf("Invalid hook entry %u %u\n",
-				 i, hook_entries[i]);
+				 i, info->hook_entry[i]);
 			goto out_unlock;
 		}
 		if (info->underflow[i] == 0xFFFFFFFF) {
 			duprintf("Invalid underflow %u %u\n",
-				 i, underflows[i]);
+				 i, info->underflow[i]);
 			goto out_unlock;
 		}
 	}
@@ -1394,17 +1399,17 @@ static int translate_compat_table(const char *name,
 	if (!newinfo)
 		goto out_unlock;
 
-	newinfo->number = number;
+	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
 		newinfo->hook_entry[i] = info->hook_entry[i];
 		newinfo->underflow[i] = info->underflow[i];
 	}
 	entry1 = newinfo->entries[raw_smp_processor_id()];
 	pos = entry1;
-	size = total_size;
-	xt_entry_foreach(iter0, entry0, total_size) {
+	size = compatr->size;
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		ret = compat_copy_entry_from_user(iter0, &pos, &size,
-						  name, newinfo, entry1);
+						  newinfo, entry1);
 		if (ret != 0)
 			break;
 	}
@@ -1414,12 +1419,12 @@ static int translate_compat_table(const char *name,
 		goto free_newinfo;
 
 	ret = -ELOOP;
-	if (!mark_source_chains(newinfo, valid_hooks, entry1))
+	if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
 		goto free_newinfo;
 
 	i = 0;
 	xt_entry_foreach(iter1, entry1, newinfo->size) {
-		ret = check_target(iter1, name);
+		ret = check_target(iter1, compatr->name);
 		if (ret != 0)
 			break;
 		++i;
@@ -1464,7 +1469,7 @@ static int translate_compat_table(const char *name,
 free_newinfo:
 	xt_free_table_info(newinfo);
 out:
-	xt_entry_foreach(iter0, entry0, total_size) {
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		if (j-- == 0)
 			break;
 		compat_release_entry(iter0);
@@ -1476,18 +1481,6 @@ out_unlock:
 	goto out;
 }
 
-struct compat_arpt_replace {
-	char				name[XT_TABLE_MAXNAMELEN];
-	u32				valid_hooks;
-	u32				num_entries;
-	u32				size;
-	u32				hook_entry[NF_ARP_NUMHOOKS];
-	u32				underflow[NF_ARP_NUMHOOKS];
-	u32				num_counters;
-	compat_uptr_t			counters;
-	struct compat_arpt_entry	entries[0];
-};
-
 static int compat_do_replace(struct net *net, void __user *user,
 			     unsigned int len)
 {
@@ -1518,10 +1511,7 @@ static int compat_do_replace(struct net *net, void __user *user,
 		goto free_newinfo;
 	}
 
-	ret = translate_compat_table(tmp.name, tmp.valid_hooks,
-				     &newinfo, &loc_cpu_entry, tmp.size,
-				     tmp.num_entries, tmp.hook_entry,
-				     tmp.underflow);
+	ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
 	if (ret != 0)
 		goto free_newinfo;
 
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443231 — [PATCH 3.12 51/88] usb: musb: Ensure rx reinit occurs for shared_fifo endpoints

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 51/88] usb: musb: Ensure rx reinit occurs for shared_fifo endpoints
Message-ID<rUKlA-7jX-29@gated-at.bofh.it>
In reply to#1443166
From: Andrew Goodbody <andrew.goodbody@cambrionix.com>

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

===============

commit f3eec0cf784e0d6c47822ca6b66df3d5812af7e6 upstream.

shared_fifo endpoints would only get a previous tx state cleared
out, the rx state was only cleared for non shared_fifo endpoints
Change this so that the rx state is cleared for all endpoints.
This addresses an issue that resulted in rx packets being dropped
silently.

Signed-off-by: Andrew Goodbody <andrew.goodbody@cambrionix.com>
Signed-off-by: Bin Liu <b-liu@ti.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/usb/musb/musb_host.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 7a149719d495..7be2ad0a10f4 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -584,14 +584,13 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
 		musb_writew(ep->regs, MUSB_TXCSR, 0);
 
 	/* scrub all previous state, clearing toggle */
-	} else {
-		csr = musb_readw(ep->regs, MUSB_RXCSR);
-		if (csr & MUSB_RXCSR_RXPKTRDY)
-			WARNING("rx%d, packet/%d ready?\n", ep->epnum,
-				musb_readw(ep->regs, MUSB_RXCOUNT));
-
-		musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
 	}
+	csr = musb_readw(ep->regs, MUSB_RXCSR);
+	if (csr & MUSB_RXCSR_RXPKTRDY)
+		WARNING("rx%d, packet/%d ready?\n", ep->epnum,
+			musb_readw(ep->regs, MUSB_RXCOUNT));
+
+	musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
 
 	/* target addr and (for multipoint) hub addr/port */
 	if (musb->is_multipoint) {
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443232 — [PATCH 3.12 45/88] crypto: ux500 - memmove the right size

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 45/88] crypto: ux500 - memmove the right size
Message-ID<rUKlA-7jX-31@gated-at.bofh.it>
In reply to#1443166
From: Linus Walleij <linus.walleij@linaro.org>

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

===============

commit 19ced623db2fe91604d69f7d86b03144c5107739 upstream.

The hash buffer is really HASH_BLOCK_SIZE bytes, someone
must have thought that memmove takes n*u32 words by mistake.
Tests work as good/bad as before after this patch.

Cc: Joakim Bech <joakim.bech@linaro.org>
Reported-by: David Binderman <linuxdev.baldrick@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/crypto/ux500/hash/hash_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 8e5e0187506f..3ff21c3e9ab2 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -797,7 +797,7 @@ static int hash_process_data(struct hash_device_data *device_data,
 						&device_data->state);
 				memmove(req_ctx->state.buffer,
 					device_data->state.buffer,
-					HASH_BLOCK_SIZE / sizeof(u32));
+					HASH_BLOCK_SIZE);
 				if (ret) {
 					dev_err(device_data->dev,
 						"%s: hash_resume_state() failed!\n",
@@ -848,7 +848,7 @@ static int hash_process_data(struct hash_device_data *device_data,
 
 			memmove(device_data->state.buffer,
 				req_ctx->state.buffer,
-				HASH_BLOCK_SIZE / sizeof(u32));
+				HASH_BLOCK_SIZE);
 			if (ret) {
 				dev_err(device_data->dev, "%s: hash_save_state() failed!\n",
 					__func__);
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443234 — [PATCH 3.12 43/88] Revert "netfilter: ensure number of counters is >0 in do_replace()"

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 43/88] Revert "netfilter: ensure number of counters is >0 in do_replace()"
Message-ID<rUKlA-7jX-25@gated-at.bofh.it>
In reply to#1443166
From: Bernhard Thaler <bernhard.thaler@wvnet.at>

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

===============

commit d26e2c9ffa385dd1b646f43c1397ba12af9ed431 upstream.

This partially reverts commit 1086bbe97a07 ("netfilter: ensure number of
counters is >0 in do_replace()") in net/bridge/netfilter/ebtables.c.

Setting rules with ebtables does not work any more with 1086bbe97a07 place.

There is an error message and no rules set in the end.

e.g.

~# ebtables -t nat -A POSTROUTING --src 12:34:56:78:9a:bc -j DROP
Unable to update the kernel. Two possible causes:
1. Multiple ebtables programs were executing simultaneously. The ebtables
   userspace tool doesn't by default support multiple ebtables programs
running

Reverting the ebtables part of 1086bbe97a07 makes this work again.

Signed-off-by: Bernhard Thaler <bernhard.thaler@wvnet.at>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 net/bridge/netfilter/ebtables.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index fbfa24b19127..b166fc2ec4b9 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1105,8 +1105,6 @@ static int do_replace(struct net *net, const void __user *user,
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
 		return -ENOMEM;
-	if (tmp.num_counters == 0)
-		return -EINVAL;
 
 	tmp.name[sizeof(tmp.name) - 1] = 0;
 
@@ -2152,8 +2150,6 @@ static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
 		return -ENOMEM;
-	if (tmp.num_counters == 0)
-		return -EINVAL;
 
 	memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
 
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443236 — [PATCH 3.12 48/88] net: alx: Work around the DMA RX overflow issue

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 48/88] net: alx: Work around the DMA RX overflow issue
Message-ID<rUKlA-7jX-37@gated-at.bofh.it>
In reply to#1443166
From: Feng Tang <feng.tang@intel.com>

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

===============

[ Upstream commit 881d0327db37ad917a367c77aff1afa1ee41e0a9 ]

Note: This is a verified backported patch for stable 4.4 kernel, and it
could also be applied to 4.3/4.2/4.1/3.18/3.16

There is a problem with alx devices, that the network link will be
lost in 1-5 minutes after the device is up.

>From debugging without datasheet, we found the error always
happen when the DMA RX address is set to 0x....fc0, which is very
likely to be a HW/silicon problem.

This patch will apply rx skb with 64 bytes longer space, and if the
allocated skb has a 0x...fc0 address, it will use skb_resever(skb, 64)
to advance the address, so that the RX overflow can be avoided.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=70761
Signed-off-by: Feng Tang <feng.tang@intel.com>
Suggested-by: Eric Dumazet <edumazet@google.com>
Tested-by: Ole Lukoie <olelukoie@mail.ru>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/net/ethernet/atheros/alx/main.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 754ac8ef2484..4736df41f062 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -86,9 +86,14 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
 	while (!cur_buf->skb && next != rxq->read_idx) {
 		struct alx_rfd *rfd = &rxq->rfd[cur];
 
-		skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
+		skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size + 64, gfp);
 		if (!skb)
 			break;
+
+		/* Workround for the HW RX DMA overflow issue */
+		if (((unsigned long)skb->data & 0xfff) == 0xfc0)
+			skb_reserve(skb, 64);
+
 		dma = dma_map_single(&alx->hw.pdev->dev,
 				     skb->data, alx->rxbuf_size,
 				     DMA_FROM_DEVICE);
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443237 — [PATCH 3.12 47/88] ipmr/ip6mr: Initialize the last assert time of mfc entries.

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 47/88] ipmr/ip6mr: Initialize the last assert time of mfc entries.
Message-ID<rUKlA-7jX-39@gated-at.bofh.it>
In reply to#1443166
From: Tom Goff <thomas.goff@ll.mit.edu>

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

===============

[ Upstream commit 70a0dec45174c976c64b4c8c1d0898581f759948 ]

This fixes wrong-interface signaling on 32-bit platforms for entries
created when jiffies > 2^31 + MFC_ASSERT_THRESH.

Signed-off-by: Tom Goff <thomas.goff@ll.mit.edu>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 net/ipv4/ipmr.c  | 4 +++-
 net/ipv6/ip6mr.c | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 2f8de5f9c032..dccda72bac62 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -881,8 +881,10 @@ static struct mfc_cache *ipmr_cache_alloc(void)
 {
 	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
 
-	if (c)
+	if (c) {
+		c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
 		c->mfc_un.res.minvif = MAXVIFS;
+	}
 	return c;
 }
 
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 8b61288e5746..86d30e60242a 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1076,6 +1076,7 @@ static struct mfc6_cache *ip6mr_cache_alloc(void)
 	struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
 	if (c == NULL)
 		return NULL;
+	c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
 	c->mfc_un.res.minvif = MAXMIFS;
 	return c;
 }
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443241 — [PATCH 3.12 44/88] netfilter: x_tables: introduce and use xt_copy_counters_from_user

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 44/88] netfilter: x_tables: introduce and use xt_copy_counters_from_user
Message-ID<rUKlA-7jX-45@gated-at.bofh.it>
In reply to#1443166
From: Florian Westphal <fw@strlen.de>

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

===============

commit d7591f0c41ce3e67600a982bab6989ef0f07b3ce upstream

The three variants use same copy&pasted code, condense this into a
helper and use that.

Make sure info.name is 0-terminated.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 include/linux/netfilter/x_tables.h |  3 ++
 net/ipv4/netfilter/arp_tables.c    | 48 +++----------------------
 net/ipv4/netfilter/ip_tables.c     | 48 +++----------------------
 net/ipv6/netfilter/ip6_tables.c    | 49 +++----------------------
 net/netfilter/x_tables.c           | 74 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 92 insertions(+), 130 deletions(-)

diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index fb4ea1578552..1d24aa71f773 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -248,6 +248,9 @@ extern int xt_check_match(struct xt_mtchk_param *,
 extern int xt_check_target(struct xt_tgchk_param *,
 			   unsigned int size, u_int8_t proto, bool inv_proto);
 
+void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
+				 struct xt_counters_info *info, bool compat);
+
 extern struct xt_table *xt_register_table(struct net *net,
 					  const struct xt_table *table,
 					  struct xt_table_info *bootstrap,
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index b7f3b31a3cc3..3f58cf8e2fd2 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1120,56 +1120,18 @@ static int do_add_counters(struct net *net, const void __user *user,
 	unsigned int i, curcpu;
 	struct xt_counters_info tmp;
 	struct xt_counters *paddc;
-	unsigned int num_counters;
-	const char *name;
-	int size;
-	void *ptmp;
 	struct xt_table *t;
 	const struct xt_table_info *private;
 	int ret = 0;
 	void *loc_cpu_entry;
 	struct arpt_entry *iter;
 	unsigned int addend;
-#ifdef CONFIG_COMPAT
-	struct compat_xt_counters_info compat_tmp;
-
-	if (compat) {
-		ptmp = &compat_tmp;
-		size = sizeof(struct compat_xt_counters_info);
-	} else
-#endif
-	{
-		ptmp = &tmp;
-		size = sizeof(struct xt_counters_info);
-	}
 
-	if (copy_from_user(ptmp, user, size) != 0)
-		return -EFAULT;
-
-#ifdef CONFIG_COMPAT
-	if (compat) {
-		num_counters = compat_tmp.num_counters;
-		name = compat_tmp.name;
-	} else
-#endif
-	{
-		num_counters = tmp.num_counters;
-		name = tmp.name;
-	}
-
-	if (len != size + num_counters * sizeof(struct xt_counters))
-		return -EINVAL;
-
-	paddc = vmalloc(len - size);
-	if (!paddc)
-		return -ENOMEM;
-
-	if (copy_from_user(paddc, user + size, len - size) != 0) {
-		ret = -EFAULT;
-		goto free;
-	}
+	paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+	if (IS_ERR(paddc))
+		return PTR_ERR(paddc);
 
-	t = xt_find_table_lock(net, NFPROTO_ARP, name);
+	t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name);
 	if (IS_ERR_OR_NULL(t)) {
 		ret = t ? PTR_ERR(t) : -ENOENT;
 		goto free;
@@ -1177,7 +1139,7 @@ static int do_add_counters(struct net *net, const void __user *user,
 
 	local_bh_disable();
 	private = t->private;
-	if (private->number != num_counters) {
+	if (private->number != tmp.num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 19878c0ba0fc..9363a37729a8 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1307,56 +1307,18 @@ do_add_counters(struct net *net, const void __user *user,
 	unsigned int i, curcpu;
 	struct xt_counters_info tmp;
 	struct xt_counters *paddc;
-	unsigned int num_counters;
-	const char *name;
-	int size;
-	void *ptmp;
 	struct xt_table *t;
 	const struct xt_table_info *private;
 	int ret = 0;
 	void *loc_cpu_entry;
 	struct ipt_entry *iter;
 	unsigned int addend;
-#ifdef CONFIG_COMPAT
-	struct compat_xt_counters_info compat_tmp;
-
-	if (compat) {
-		ptmp = &compat_tmp;
-		size = sizeof(struct compat_xt_counters_info);
-	} else
-#endif
-	{
-		ptmp = &tmp;
-		size = sizeof(struct xt_counters_info);
-	}
 
-	if (copy_from_user(ptmp, user, size) != 0)
-		return -EFAULT;
-
-#ifdef CONFIG_COMPAT
-	if (compat) {
-		num_counters = compat_tmp.num_counters;
-		name = compat_tmp.name;
-	} else
-#endif
-	{
-		num_counters = tmp.num_counters;
-		name = tmp.name;
-	}
-
-	if (len != size + num_counters * sizeof(struct xt_counters))
-		return -EINVAL;
-
-	paddc = vmalloc(len - size);
-	if (!paddc)
-		return -ENOMEM;
-
-	if (copy_from_user(paddc, user + size, len - size) != 0) {
-		ret = -EFAULT;
-		goto free;
-	}
+	paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+	if (IS_ERR(paddc))
+		return PTR_ERR(paddc);
 
-	t = xt_find_table_lock(net, AF_INET, name);
+	t = xt_find_table_lock(net, AF_INET, tmp.name);
 	if (IS_ERR_OR_NULL(t)) {
 		ret = t ? PTR_ERR(t) : -ENOENT;
 		goto free;
@@ -1364,7 +1326,7 @@ do_add_counters(struct net *net, const void __user *user,
 
 	local_bh_disable();
 	private = t->private;
-	if (private->number != num_counters) {
+	if (private->number != tmp.num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 59a8cc791966..a7d644e62a3e 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1317,56 +1317,17 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
 	unsigned int i, curcpu;
 	struct xt_counters_info tmp;
 	struct xt_counters *paddc;
-	unsigned int num_counters;
-	char *name;
-	int size;
-	void *ptmp;
 	struct xt_table *t;
 	const struct xt_table_info *private;
 	int ret = 0;
 	const void *loc_cpu_entry;
 	struct ip6t_entry *iter;
 	unsigned int addend;
-#ifdef CONFIG_COMPAT
-	struct compat_xt_counters_info compat_tmp;
-
-	if (compat) {
-		ptmp = &compat_tmp;
-		size = sizeof(struct compat_xt_counters_info);
-	} else
-#endif
-	{
-		ptmp = &tmp;
-		size = sizeof(struct xt_counters_info);
-	}
-
-	if (copy_from_user(ptmp, user, size) != 0)
-		return -EFAULT;
-
-#ifdef CONFIG_COMPAT
-	if (compat) {
-		num_counters = compat_tmp.num_counters;
-		name = compat_tmp.name;
-	} else
-#endif
-	{
-		num_counters = tmp.num_counters;
-		name = tmp.name;
-	}
-
-	if (len != size + num_counters * sizeof(struct xt_counters))
-		return -EINVAL;
-
-	paddc = vmalloc(len - size);
-	if (!paddc)
-		return -ENOMEM;
-
-	if (copy_from_user(paddc, user + size, len - size) != 0) {
-		ret = -EFAULT;
-		goto free;
-	}
 
-	t = xt_find_table_lock(net, AF_INET6, name);
+	paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+	if (IS_ERR(paddc))
+		return PTR_ERR(paddc);
+	t = xt_find_table_lock(net, AF_INET6, tmp.name);
 	if (IS_ERR_OR_NULL(t)) {
 		ret = t ? PTR_ERR(t) : -ENOENT;
 		goto free;
@@ -1375,7 +1336,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
 
 	local_bh_disable();
 	private = t->private;
-	if (private->number != num_counters) {
+	if (private->number != tmp.num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index da11978eff5d..51c141b09dba 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -771,6 +771,80 @@ int xt_check_target(struct xt_tgchk_param *par,
 }
 EXPORT_SYMBOL_GPL(xt_check_target);
 
+/**
+ * xt_copy_counters_from_user - copy counters and metadata from userspace
+ *
+ * @user: src pointer to userspace memory
+ * @len: alleged size of userspace memory
+ * @info: where to store the xt_counters_info metadata
+ * @compat: true if we setsockopt call is done by 32bit task on 64bit kernel
+ *
+ * Copies counter meta data from @user and stores it in @info.
+ *
+ * vmallocs memory to hold the counters, then copies the counter data
+ * from @user to the new memory and returns a pointer to it.
+ *
+ * If @compat is true, @info gets converted automatically to the 64bit
+ * representation.
+ *
+ * The metadata associated with the counters is stored in @info.
+ *
+ * Return: returns pointer that caller has to test via IS_ERR().
+ * If IS_ERR is false, caller has to vfree the pointer.
+ */
+void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
+				 struct xt_counters_info *info, bool compat)
+{
+	void *mem;
+	u64 size;
+
+#ifdef CONFIG_COMPAT
+	if (compat) {
+		/* structures only differ in size due to alignment */
+		struct compat_xt_counters_info compat_tmp;
+
+		if (len <= sizeof(compat_tmp))
+			return ERR_PTR(-EINVAL);
+
+		len -= sizeof(compat_tmp);
+		if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0)
+			return ERR_PTR(-EFAULT);
+
+		strlcpy(info->name, compat_tmp.name, sizeof(info->name));
+		info->num_counters = compat_tmp.num_counters;
+		user += sizeof(compat_tmp);
+	} else
+#endif
+	{
+		if (len <= sizeof(*info))
+			return ERR_PTR(-EINVAL);
+
+		len -= sizeof(*info);
+		if (copy_from_user(info, user, sizeof(*info)) != 0)
+			return ERR_PTR(-EFAULT);
+
+		info->name[sizeof(info->name) - 1] = '\0';
+		user += sizeof(*info);
+	}
+
+	size = sizeof(struct xt_counters);
+	size *= info->num_counters;
+
+	if (size != (u64)len)
+		return ERR_PTR(-EINVAL);
+
+	mem = vmalloc(len);
+	if (!mem)
+		return ERR_PTR(-ENOMEM);
+
+	if (copy_from_user(mem, user, len) == 0)
+		return mem;
+
+	vfree(mem);
+	return ERR_PTR(-EFAULT);
+}
+EXPORT_SYMBOL_GPL(xt_copy_counters_from_user);
+
 #ifdef CONFIG_COMPAT
 int xt_compat_target_offset(const struct xt_target *target)
 {
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443242 — [PATCH 3.12 46/88] sit: correct IP protocol used in ipip6_err

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 46/88] sit: correct IP protocol used in ipip6_err
Message-ID<rUKlB-7jX-63@gated-at.bofh.it>
In reply to#1443166
From: Simon Horman <simon.horman@netronome.com>

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

===============

[ Upstream commit d5d8760b78d0cfafe292f965f599988138b06a70 ]

Since 32b8a8e59c9c ("sit: add IPv4 over IPv4 support")
ipip6_err() may be called for packets whose IP protocol is
IPPROTO_IPIP as well as those whose IP protocol is IPPROTO_IPV6.

In the case of IPPROTO_IPIP packets the correct protocol value is not
passed to ipv4_update_pmtu() or ipv4_redirect().

This patch resolves this problem by using the IP protocol of the packet
rather than a hard-coded value. This appears to be consistent
with the usage of the protocol of a packet by icmp_socket_deliver()
the caller of ipip6_err().

I was able to exercise the redirect case by using a setup where an ICMP
redirect was received for the destination of the encapsulated packet.
However, it appears that although incorrect the protocol field is not used
in this case and thus no problem manifests.  On inspection it does not
appear that a problem will manifest in the fragmentation needed/update pmtu
case either.

In short I believe this is a cosmetic fix. None the less, the use of
IPPROTO_IPV6 seems wrong and confusing.

Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 net/ipv6/sit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index eb1fe0759752..a883776bcec8 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -529,13 +529,13 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
 
 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
-				 t->parms.link, 0, IPPROTO_IPV6, 0);
+				 t->parms.link, 0, iph->protocol, 0);
 		err = 0;
 		goto out;
 	}
 	if (type == ICMP_REDIRECT) {
 		ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
-			      IPPROTO_IPV6, 0);
+			      iph->protocol, 0);
 		err = 0;
 		goto out;
 	}
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443247 — [PATCH 3.12 41/88] netfilter: ensure number of counters is >0 in do_replace()

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 41/88] netfilter: ensure number of counters is >0 in do_replace()
Message-ID<rUKlB-7jX-61@gated-at.bofh.it>
In reply to#1443166
From: Dave Jones <davej@codemonkey.org.uk>

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

===============

commit 1086bbe97a074844188c6c988fa0b1a98c3ccbb9 upstream.

After improving setsockopt() coverage in trinity, I started triggering
vmalloc failures pretty reliably from this code path:

warn_alloc_failed+0xe9/0x140
__vmalloc_node_range+0x1be/0x270
vzalloc+0x4b/0x50
__do_replace+0x52/0x260 [ip_tables]
do_ipt_set_ctl+0x15d/0x1d0 [ip_tables]
nf_setsockopt+0x65/0x90
ip_setsockopt+0x61/0xa0
raw_setsockopt+0x16/0x60
sock_common_setsockopt+0x14/0x20
SyS_setsockopt+0x71/0xd0

It turns out we don't validate that the num_counters field in the
struct we pass in from userspace is initialized.

The same problem also exists in ebtables, arptables, ipv6, and the
compat variants.

Signed-off-by: Dave Jones <davej@codemonkey.org.uk>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 net/bridge/netfilter/ebtables.c | 4 ++++
 net/ipv4/netfilter/arp_tables.c | 6 ++++++
 net/ipv4/netfilter/ip_tables.c  | 6 ++++++
 net/ipv6/netfilter/ip6_tables.c | 6 ++++++
 4 files changed, 22 insertions(+)

diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index b166fc2ec4b9..fbfa24b19127 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1105,6 +1105,8 @@ static int do_replace(struct net *net, const void __user *user,
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
 		return -ENOMEM;
+	if (tmp.num_counters == 0)
+		return -EINVAL;
 
 	tmp.name[sizeof(tmp.name) - 1] = 0;
 
@@ -2150,6 +2152,8 @@ static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
 		return -ENOMEM;
+	if (tmp.num_counters == 0)
+		return -EINVAL;
 
 	memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 819a5d2b618f..020b0e97c206 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1077,6 +1077,9 @@ static int do_replace(struct net *net, const void __user *user,
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	if (tmp.num_counters == 0)
+		return -EINVAL;
+
 	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
@@ -1491,6 +1494,9 @@ static int compat_do_replace(struct net *net, void __user *user,
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	if (tmp.num_counters == 0)
+		return -EINVAL;
+
 	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index b296da45a7bd..a207d2befc75 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1263,6 +1263,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	if (tmp.num_counters == 0)
+		return -EINVAL;
+
 	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
@@ -1798,6 +1801,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	if (tmp.num_counters == 0)
+		return -EINVAL;
+
 	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 2b345f642978..b87f35b6c742 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1273,6 +1273,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	if (tmp.num_counters == 0)
+		return -EINVAL;
+
 	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
@@ -1807,6 +1810,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	if (tmp.num_counters == 0)
+		return -EINVAL;
+
 	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443249 — [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table
Message-ID<rUKlB-7jX-59@gated-at.bofh.it>
In reply to#1443166
From: Florian Westphal <fw@strlen.de>

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

===============

commit 09d9686047dbbe1cf4faa558d3ecc4aae2046054 upstream.

This looks like refactoring, but its also a bug fix.

Problem is that the compat path (32bit iptables, 64bit kernel) lacks a few
sanity tests that are done in the normal path.

For example, we do not check for underflows and the base chain policies.

While its possible to also add such checks to the compat path, its more
copy&pastry, for instance we cannot reuse check_underflow() helper as
e->target_offset differs in the compat case.

Other problem is that it makes auditing for validation errors harder; two
places need to be checked and kept in sync.

At a high level 32 bit compat works like this:
1- initial pass over blob:
   validate match/entry offsets, bounds checking
   lookup all matches and targets
   do bookkeeping wrt. size delta of 32/64bit structures
   assign match/target.u.kernel pointer (points at kernel
   implementation, needed to access ->compatsize etc.)

2- allocate memory according to the total bookkeeping size to
   contain the translated ruleset

3- second pass over original blob:
   for each entry, copy the 32bit representation to the newly allocated
   memory.  This also does any special match translations (e.g.
   adjust 32bit to 64bit longs, etc).

4- check if ruleset is free of loops (chase all jumps)

5-first pass over translated blob:
   call the checkentry function of all matches and targets.

The alternative implemented by this patch is to drop steps 3&4 from the
compat process, the translation is changed into an intermediate step
rather than a full 1:1 translate_table replacement.

In the 2nd pass (step #3), change the 64bit ruleset back to a kernel
representation, i.e. put() the kernel pointer and restore ->u.user.name .

This gets us a 64bit ruleset that is in the format generated by a 64bit
iptables userspace -- we can then use translate_table() to get the
'native' sanity checks.

This has two drawbacks:

1. we re-validate all the match and target entry structure sizes even
though compat translation is supposed to never generate bogus offsets.
2. we put and then re-lookup each match and target.

THe upside is that we get all sanity tests and ruleset validations
provided by the normal path and can remove some duplicated compat code.

iptables-restore time of autogenerated ruleset with 300k chains of form
-A CHAIN0001 -m limit --limit 1/s -j CHAIN0002
-A CHAIN0002 -m limit --limit 1/s -j CHAIN0003

shows no noticeable differences in restore times:
old:   0m30.796s
new:   0m31.521s
64bit: 0m25.674s

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 net/ipv4/netfilter/arp_tables.c | 109 ++++++-----------------------
 net/ipv4/netfilter/ip_tables.c  | 151 ++++++++--------------------------------
 net/ipv6/netfilter/ip6_tables.c | 145 ++++++--------------------------------
 net/netfilter/x_tables.c        |   8 +++
 4 files changed, 80 insertions(+), 333 deletions(-)

diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 020b0e97c206..b7f3b31a3cc3 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1223,19 +1223,17 @@ static inline void compat_release_entry(struct compat_arpt_entry *e)
 	module_put(t->u.kernel.target->me);
 }
 
-static inline int
+static int
 check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
 				  struct xt_table_info *newinfo,
 				  unsigned int *size,
 				  const unsigned char *base,
-				  const unsigned char *limit,
-				  const unsigned int *hook_entries,
-				  const unsigned int *underflows)
+				  const unsigned char *limit)
 {
 	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
-	int ret, off, h;
+	int ret, off;
 
 	duprintf("check_compat_entry_size_and_hooks %p\n", e);
 	if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 ||
@@ -1280,17 +1278,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
 	if (ret)
 		goto release_target;
 
-	/* Check hooks & underflows */
-	for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
-		if ((unsigned char *)e - base == hook_entries[h])
-			newinfo->hook_entry[h] = hook_entries[h];
-		if ((unsigned char *)e - base == underflows[h])
-			newinfo->underflow[h] = underflows[h];
-	}
-
-	/* Clear counters and comefrom */
-	memset(&e->counters, 0, sizeof(e->counters));
-	e->comefrom = 0;
 	return 0;
 
 release_target:
@@ -1340,7 +1327,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
 	struct xt_table_info *newinfo, *info;
 	void *pos, *entry0, *entry1;
 	struct compat_arpt_entry *iter0;
-	struct arpt_entry *iter1;
+	struct arpt_replace repl;
 	unsigned int size;
 	int ret = 0;
 
@@ -1349,12 +1336,6 @@ static int translate_compat_table(struct xt_table_info **pinfo,
 	size = compatr->size;
 	info->number = compatr->num_entries;
 
-	/* Init all hooks to impossible value. */
-	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
-		info->hook_entry[i] = 0xFFFFFFFF;
-		info->underflow[i] = 0xFFFFFFFF;
-	}
-
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(NFPROTO_ARP);
@@ -1363,9 +1344,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
 	xt_entry_foreach(iter0, entry0, compatr->size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
 							entry0,
-							entry0 + compatr->size,
-							compatr->hook_entry,
-							compatr->underflow);
+							entry0 + compatr->size);
 		if (ret != 0)
 			goto out_unlock;
 		++j;
@@ -1378,23 +1357,6 @@ static int translate_compat_table(struct xt_table_info **pinfo,
 		goto out_unlock;
 	}
 
-	/* Check hooks all assigned */
-	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
-		/* Only hooks which are valid */
-		if (!(compatr->valid_hooks & (1 << i)))
-			continue;
-		if (info->hook_entry[i] == 0xFFFFFFFF) {
-			duprintf("Invalid hook entry %u %u\n",
-				 i, info->hook_entry[i]);
-			goto out_unlock;
-		}
-		if (info->underflow[i] == 0xFFFFFFFF) {
-			duprintf("Invalid underflow %u %u\n",
-				 i, info->underflow[i]);
-			goto out_unlock;
-		}
-	}
-
 	ret = -ENOMEM;
 	newinfo = xt_alloc_table_info(size);
 	if (!newinfo)
@@ -1411,51 +1373,25 @@ static int translate_compat_table(struct xt_table_info **pinfo,
 	xt_entry_foreach(iter0, entry0, compatr->size)
 		compat_copy_entry_from_user(iter0, &pos, &size,
 					    newinfo, entry1);
+
+	/* all module references in entry0 are now gone */
+
 	xt_compat_flush_offsets(NFPROTO_ARP);
 	xt_compat_unlock(NFPROTO_ARP);
 
-	ret = -ELOOP;
-	if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
-		goto free_newinfo;
+	memcpy(&repl, compatr, sizeof(*compatr));
 
-	i = 0;
-	xt_entry_foreach(iter1, entry1, newinfo->size) {
-		ret = check_target(iter1, compatr->name);
-		if (ret != 0)
-			break;
-		++i;
-		if (strcmp(arpt_get_target(iter1)->u.user.name,
-		    XT_ERROR_TARGET) == 0)
-			++newinfo->stacksize;
-	}
-	if (ret) {
-		/*
-		 * The first i matches need cleanup_entry (calls ->destroy)
-		 * because they had called ->check already. The other j-i
-		 * entries need only release.
-		 */
-		int skip = i;
-		j -= i;
-		xt_entry_foreach(iter0, entry0, newinfo->size) {
-			if (skip-- > 0)
-				continue;
-			if (j-- == 0)
-				break;
-			compat_release_entry(iter0);
-		}
-		xt_entry_foreach(iter1, entry1, newinfo->size) {
-			if (i-- == 0)
-				break;
-			cleanup_entry(iter1);
-		}
-		xt_free_table_info(newinfo);
-		return ret;
+	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
+		repl.hook_entry[i] = newinfo->hook_entry[i];
+		repl.underflow[i] = newinfo->underflow[i];
 	}
 
-	/* And one copy for every other CPU */
-	for_each_possible_cpu(i)
-		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
-			memcpy(newinfo->entries[i], entry1, newinfo->size);
+	repl.num_counters = 0;
+	repl.counters = NULL;
+	repl.size = newinfo->size;
+	ret = translate_table(newinfo, entry1, &repl);
+	if (ret)
+		goto free_newinfo;
 
 	*pinfo = newinfo;
 	*pentry0 = entry1;
@@ -1464,17 +1400,16 @@ static int translate_compat_table(struct xt_table_info **pinfo,
 
 free_newinfo:
 	xt_free_table_info(newinfo);
-out:
+	return ret;
+out_unlock:
+	xt_compat_flush_offsets(NFPROTO_ARP);
+	xt_compat_unlock(NFPROTO_ARP);
 	xt_entry_foreach(iter0, entry0, compatr->size) {
 		if (j-- == 0)
 			break;
 		compat_release_entry(iter0);
 	}
 	return ret;
-out_unlock:
-	xt_compat_flush_offsets(NFPROTO_ARP);
-	xt_compat_unlock(NFPROTO_ARP);
-	goto out;
 }
 
 static int compat_do_replace(struct net *net, void __user *user,
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index a207d2befc75..19878c0ba0fc 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1478,16 +1478,14 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
 				  struct xt_table_info *newinfo,
 				  unsigned int *size,
 				  const unsigned char *base,
-				  const unsigned char *limit,
-				  const unsigned int *hook_entries,
-				  const unsigned int *underflows)
+				  const unsigned char *limit)
 {
 	struct xt_entry_match *ematch;
 	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
 	unsigned int j;
-	int ret, off, h;
+	int ret, off;
 
 	duprintf("check_compat_entry_size_and_hooks %p\n", e);
 	if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
@@ -1540,17 +1538,6 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
 	if (ret)
 		goto out;
 
-	/* Check hooks & underflows */
-	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
-		if ((unsigned char *)e - base == hook_entries[h])
-			newinfo->hook_entry[h] = hook_entries[h];
-		if ((unsigned char *)e - base == underflows[h])
-			newinfo->underflow[h] = underflows[h];
-	}
-
-	/* Clear counters and comefrom */
-	memset(&e->counters, 0, sizeof(e->counters));
-	e->comefrom = 0;
 	return 0;
 
 out:
@@ -1593,6 +1580,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
 	xt_compat_target_from_user(t, dstptr, size);
 
 	de->next_offset = e->next_offset - (origsize - *size);
+
 	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 		if ((unsigned char *)de - base < newinfo->hook_entry[h])
 			newinfo->hook_entry[h] -= origsize - *size;
@@ -1602,41 +1590,6 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
 }
 
 static int
-compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
-{
-	struct xt_entry_match *ematch;
-	struct xt_mtchk_param mtpar;
-	unsigned int j;
-	int ret = 0;
-
-	j = 0;
-	mtpar.net	= net;
-	mtpar.table     = name;
-	mtpar.entryinfo = &e->ip;
-	mtpar.hook_mask = e->comefrom;
-	mtpar.family    = NFPROTO_IPV4;
-	xt_ematch_foreach(ematch, e) {
-		ret = check_match(ematch, &mtpar);
-		if (ret != 0)
-			goto cleanup_matches;
-		++j;
-	}
-
-	ret = check_target(e, net, name);
-	if (ret)
-		goto cleanup_matches;
-	return 0;
-
- cleanup_matches:
-	xt_ematch_foreach(ematch, e) {
-		if (j-- == 0)
-			break;
-		cleanup_match(ematch, net);
-	}
-	return ret;
-}
-
-static int
 translate_compat_table(struct net *net,
 		       struct xt_table_info **pinfo,
 		       void **pentry0,
@@ -1646,7 +1599,7 @@ translate_compat_table(struct net *net,
 	struct xt_table_info *newinfo, *info;
 	void *pos, *entry0, *entry1;
 	struct compat_ipt_entry *iter0;
-	struct ipt_entry *iter1;
+	struct ipt_replace repl;
 	unsigned int size;
 	int ret;
 
@@ -1655,12 +1608,6 @@ translate_compat_table(struct net *net,
 	size = compatr->size;
 	info->number = compatr->num_entries;
 
-	/* Init all hooks to impossible value. */
-	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		info->hook_entry[i] = 0xFFFFFFFF;
-		info->underflow[i] = 0xFFFFFFFF;
-	}
-
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(AF_INET);
@@ -1669,9 +1616,7 @@ translate_compat_table(struct net *net,
 	xt_entry_foreach(iter0, entry0, compatr->size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
 							entry0,
-							entry0 + compatr->size,
-							compatr->hook_entry,
-							compatr->underflow);
+							entry0 + compatr->size);
 		if (ret != 0)
 			goto out_unlock;
 		++j;
@@ -1684,23 +1629,6 @@ translate_compat_table(struct net *net,
 		goto out_unlock;
 	}
 
-	/* Check hooks all assigned */
-	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		/* Only hooks which are valid */
-		if (!(compatr->valid_hooks & (1 << i)))
-			continue;
-		if (info->hook_entry[i] == 0xFFFFFFFF) {
-			duprintf("Invalid hook entry %u %u\n",
-				 i, info->hook_entry[i]);
-			goto out_unlock;
-		}
-		if (info->underflow[i] == 0xFFFFFFFF) {
-			duprintf("Invalid underflow %u %u\n",
-				 i, info->underflow[i]);
-			goto out_unlock;
-		}
-	}
-
 	ret = -ENOMEM;
 	newinfo = xt_alloc_table_info(size);
 	if (!newinfo)
@@ -1708,8 +1636,8 @@ translate_compat_table(struct net *net,
 
 	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		newinfo->hook_entry[i] = info->hook_entry[i];
-		newinfo->underflow[i] = info->underflow[i];
+		newinfo->hook_entry[i] = compatr->hook_entry[i];
+		newinfo->underflow[i] = compatr->underflow[i];
 	}
 	entry1 = newinfo->entries[raw_smp_processor_id()];
 	pos = entry1;
@@ -1718,51 +1646,29 @@ translate_compat_table(struct net *net,
 		compat_copy_entry_from_user(iter0, &pos, &size,
 					    newinfo, entry1);
 
+	/* all module references in entry0 are now gone.
+	 * entry1/newinfo contains a 64bit ruleset that looks exactly as
+	 * generated by 64bit userspace.
+	 *
+	 * Call standard translate_table() to validate all hook_entrys,
+	 * underflows, check for loops, etc.
+	 */
 	xt_compat_flush_offsets(AF_INET);
 	xt_compat_unlock(AF_INET);
 
-	ret = -ELOOP;
-	if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
-		goto free_newinfo;
+	memcpy(&repl, compatr, sizeof(*compatr));
 
-	i = 0;
-	xt_entry_foreach(iter1, entry1, newinfo->size) {
-		ret = compat_check_entry(iter1, net, compatr->name);
-		if (ret != 0)
-			break;
-		++i;
-		if (strcmp(ipt_get_target(iter1)->u.user.name,
-		    XT_ERROR_TARGET) == 0)
-			++newinfo->stacksize;
-	}
-	if (ret) {
-		/*
-		 * The first i matches need cleanup_entry (calls ->destroy)
-		 * because they had called ->check already. The other j-i
-		 * entries need only release.
-		 */
-		int skip = i;
-		j -= i;
-		xt_entry_foreach(iter0, entry0, newinfo->size) {
-			if (skip-- > 0)
-				continue;
-			if (j-- == 0)
-				break;
-			compat_release_entry(iter0);
-		}
-		xt_entry_foreach(iter1, entry1, newinfo->size) {
-			if (i-- == 0)
-				break;
-			cleanup_entry(iter1, net);
-		}
-		xt_free_table_info(newinfo);
-		return ret;
+	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
+		repl.hook_entry[i] = newinfo->hook_entry[i];
+		repl.underflow[i] = newinfo->underflow[i];
 	}
 
-	/* And one copy for every other CPU */
-	for_each_possible_cpu(i)
-		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
-			memcpy(newinfo->entries[i], entry1, newinfo->size);
+	repl.num_counters = 0;
+	repl.counters = NULL;
+	repl.size = newinfo->size;
+	ret = translate_table(net, newinfo, entry1, &repl);
+	if (ret)
+		goto free_newinfo;
 
 	*pinfo = newinfo;
 	*pentry0 = entry1;
@@ -1771,17 +1677,16 @@ translate_compat_table(struct net *net,
 
 free_newinfo:
 	xt_free_table_info(newinfo);
-out:
+	return ret;
+out_unlock:
+	xt_compat_flush_offsets(AF_INET);
+	xt_compat_unlock(AF_INET);
 	xt_entry_foreach(iter0, entry0, compatr->size) {
 		if (j-- == 0)
 			break;
 		compat_release_entry(iter0);
 	}
 	return ret;
-out_unlock:
-	xt_compat_flush_offsets(AF_INET);
-	xt_compat_unlock(AF_INET);
-	goto out;
 }
 
 static int
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index b87f35b6c742..59a8cc791966 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1490,16 +1490,14 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
 				  struct xt_table_info *newinfo,
 				  unsigned int *size,
 				  const unsigned char *base,
-				  const unsigned char *limit,
-				  const unsigned int *hook_entries,
-				  const unsigned int *underflows)
+				  const unsigned char *limit)
 {
 	struct xt_entry_match *ematch;
 	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
 	unsigned int j;
-	int ret, off, h;
+	int ret, off;
 
 	duprintf("check_compat_entry_size_and_hooks %p\n", e);
 	if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
@@ -1552,17 +1550,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
 	if (ret)
 		goto out;
 
-	/* Check hooks & underflows */
-	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
-		if ((unsigned char *)e - base == hook_entries[h])
-			newinfo->hook_entry[h] = hook_entries[h];
-		if ((unsigned char *)e - base == underflows[h])
-			newinfo->underflow[h] = underflows[h];
-	}
-
-	/* Clear counters and comefrom */
-	memset(&e->counters, 0, sizeof(e->counters));
-	e->comefrom = 0;
 	return 0;
 
 out:
@@ -1611,41 +1598,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
 	}
 }
 
-static int compat_check_entry(struct ip6t_entry *e, struct net *net,
-			      const char *name)
-{
-	unsigned int j;
-	int ret = 0;
-	struct xt_mtchk_param mtpar;
-	struct xt_entry_match *ematch;
-
-	j = 0;
-	mtpar.net	= net;
-	mtpar.table     = name;
-	mtpar.entryinfo = &e->ipv6;
-	mtpar.hook_mask = e->comefrom;
-	mtpar.family    = NFPROTO_IPV6;
-	xt_ematch_foreach(ematch, e) {
-		ret = check_match(ematch, &mtpar);
-		if (ret != 0)
-			goto cleanup_matches;
-		++j;
-	}
-
-	ret = check_target(e, net, name);
-	if (ret)
-		goto cleanup_matches;
-	return 0;
-
- cleanup_matches:
-	xt_ematch_foreach(ematch, e) {
-		if (j-- == 0)
-			break;
-		cleanup_match(ematch, net);
-	}
-	return ret;
-}
-
 static int
 translate_compat_table(struct net *net,
 		       struct xt_table_info **pinfo,
@@ -1656,7 +1608,7 @@ translate_compat_table(struct net *net,
 	struct xt_table_info *newinfo, *info;
 	void *pos, *entry0, *entry1;
 	struct compat_ip6t_entry *iter0;
-	struct ip6t_entry *iter1;
+	struct ip6t_replace repl;
 	unsigned int size;
 	int ret = 0;
 
@@ -1665,12 +1617,6 @@ translate_compat_table(struct net *net,
 	size = compatr->size;
 	info->number = compatr->num_entries;
 
-	/* Init all hooks to impossible value. */
-	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		info->hook_entry[i] = 0xFFFFFFFF;
-		info->underflow[i] = 0xFFFFFFFF;
-	}
-
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(AF_INET6);
@@ -1679,9 +1625,7 @@ translate_compat_table(struct net *net,
 	xt_entry_foreach(iter0, entry0, compatr->size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
 							entry0,
-							entry0 + compatr->size,
-							compatr->hook_entry,
-							compatr->underflow);
+							entry0 + compatr->size);
 		if (ret != 0)
 			goto out_unlock;
 		++j;
@@ -1694,23 +1638,6 @@ translate_compat_table(struct net *net,
 		goto out_unlock;
 	}
 
-	/* Check hooks all assigned */
-	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		/* Only hooks which are valid */
-		if (!(compatr->valid_hooks & (1 << i)))
-			continue;
-		if (info->hook_entry[i] == 0xFFFFFFFF) {
-			duprintf("Invalid hook entry %u %u\n",
-				 i, info->hook_entry[i]);
-			goto out_unlock;
-		}
-		if (info->underflow[i] == 0xFFFFFFFF) {
-			duprintf("Invalid underflow %u %u\n",
-				 i, info->underflow[i]);
-			goto out_unlock;
-		}
-	}
-
 	ret = -ENOMEM;
 	newinfo = xt_alloc_table_info(size);
 	if (!newinfo)
@@ -1718,60 +1645,33 @@ translate_compat_table(struct net *net,
 
 	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		newinfo->hook_entry[i] = info->hook_entry[i];
-		newinfo->underflow[i] = info->underflow[i];
+		newinfo->hook_entry[i] = compatr->hook_entry[i];
+		newinfo->underflow[i] = compatr->underflow[i];
 	}
 	entry1 = newinfo->entries[raw_smp_processor_id()];
 	pos = entry1;
+	size = compatr->size;
 	xt_entry_foreach(iter0, entry0, compatr->size)
 		compat_copy_entry_from_user(iter0, &pos, &size,
 					    newinfo, entry1);
 
+	/* all module references in entry0 are now gone. */
 	xt_compat_flush_offsets(AF_INET6);
 	xt_compat_unlock(AF_INET6);
 
-	ret = -ELOOP;
-	if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
-		goto free_newinfo;
+	memcpy(&repl, compatr, sizeof(*compatr));
 
-	i = 0;
-	xt_entry_foreach(iter1, entry1, newinfo->size) {
-		ret = compat_check_entry(iter1, net, compatr->name);
-		if (ret != 0)
-			break;
-		++i;
-		if (strcmp(ip6t_get_target(iter1)->u.user.name,
-		    XT_ERROR_TARGET) == 0)
-			++newinfo->stacksize;
-	}
-	if (ret) {
-		/*
-		 * The first i matches need cleanup_entry (calls ->destroy)
-		 * because they had called ->check already. The other j-i
-		 * entries need only release.
-		 */
-		int skip = i;
-		j -= i;
-		xt_entry_foreach(iter0, entry0, newinfo->size) {
-			if (skip-- > 0)
-				continue;
-			if (j-- == 0)
-				break;
-			compat_release_entry(iter0);
-		}
-		xt_entry_foreach(iter1, entry1, newinfo->size) {
-			if (i-- == 0)
-				break;
-			cleanup_entry(iter1, net);
-		}
-		xt_free_table_info(newinfo);
-		return ret;
+	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
+		repl.hook_entry[i] = newinfo->hook_entry[i];
+		repl.underflow[i] = newinfo->underflow[i];
 	}
 
-	/* And one copy for every other CPU */
-	for_each_possible_cpu(i)
-		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
-			memcpy(newinfo->entries[i], entry1, newinfo->size);
+	repl.num_counters = 0;
+	repl.counters = NULL;
+	repl.size = newinfo->size;
+	ret = translate_table(net, newinfo, entry1, &repl);
+	if (ret)
+		goto free_newinfo;
 
 	*pinfo = newinfo;
 	*pentry0 = entry1;
@@ -1780,17 +1680,16 @@ translate_compat_table(struct net *net,
 
 free_newinfo:
 	xt_free_table_info(newinfo);
-out:
+	return ret;
+out_unlock:
+	xt_compat_flush_offsets(AF_INET6);
+	xt_compat_unlock(AF_INET6);
 	xt_entry_foreach(iter0, entry0, compatr->size) {
 		if (j-- == 0)
 			break;
 		compat_release_entry(iter0);
 	}
 	return ret;
-out_unlock:
-	xt_compat_flush_offsets(AF_INET6);
-	xt_compat_unlock(AF_INET6);
-	goto out;
 }
 
 static int
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 9cf3039deac2..da11978eff5d 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -552,6 +552,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
 	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
 	int pad, off = xt_compat_match_offset(match);
 	u_int16_t msize = cm->u.user.match_size;
+	char name[sizeof(m->u.user.name)];
 
 	m = *dstptr;
 	memcpy(m, cm, sizeof(*cm));
@@ -565,6 +566,9 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
 
 	msize += off;
 	m->u.user.match_size = msize;
+	strlcpy(name, match->name, sizeof(name));
+	module_put(match->me);
+	strncpy(m->u.user.name, name, sizeof(m->u.user.name));
 
 	*size += off;
 	*dstptr += msize;
@@ -782,6 +786,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
 	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
 	int pad, off = xt_compat_target_offset(target);
 	u_int16_t tsize = ct->u.user.target_size;
+	char name[sizeof(t->u.user.name)];
 
 	t = *dstptr;
 	memcpy(t, ct, sizeof(*ct));
@@ -795,6 +800,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
 
 	tsize += off;
 	t->u.user.target_size = tsize;
+	strlcpy(name, target->name, sizeof(name));
+	module_put(target->me);
+	strncpy(t->u.user.name, name, sizeof(t->u.user.name));
 
 	*size += off;
 	*dstptr += tsize;
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1446126 — Re: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table

FromMichal Kubecek <mkubecek@suse.cz>
Date2016-07-19 09:20 +0200
SubjectRe: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table
Message-ID<rWxtT-129-1@gated-at.bofh.it>
In reply to#1443249
On Thu, Jul 14, 2016 at 10:15:34AM +0200, Jiri Slaby wrote:
> From: Florian Westphal <fw@strlen.de>
> 
> 3.12-stable review patch.  If anyone has any objections, please let me know.
> 
> ===============
> 
> commit 09d9686047dbbe1cf4faa558d3ecc4aae2046054 upstream.
> 
> This looks like refactoring, but its also a bug fix.
> 
> Problem is that the compat path (32bit iptables, 64bit kernel) lacks a few
> sanity tests that are done in the normal path.
> 
> For example, we do not check for underflows and the base chain policies.
> 
> While its possible to also add such checks to the compat path, its more
> copy&pastry, for instance we cannot reuse check_underflow() helper as
> e->target_offset differs in the compat case.
> 
> Other problem is that it makes auditing for validation errors harder; two
> places need to be checked and kept in sync.
> 
> At a high level 32 bit compat works like this:
> 1- initial pass over blob:
>    validate match/entry offsets, bounds checking
>    lookup all matches and targets
>    do bookkeeping wrt. size delta of 32/64bit structures
>    assign match/target.u.kernel pointer (points at kernel
>    implementation, needed to access ->compatsize etc.)
> 
> 2- allocate memory according to the total bookkeeping size to
>    contain the translated ruleset
> 
> 3- second pass over original blob:
>    for each entry, copy the 32bit representation to the newly allocated
>    memory.  This also does any special match translations (e.g.
>    adjust 32bit to 64bit longs, etc).
> 
> 4- check if ruleset is free of loops (chase all jumps)
> 
> 5-first pass over translated blob:
>    call the checkentry function of all matches and targets.
> 
> The alternative implemented by this patch is to drop steps 3&4 from the
> compat process, the translation is changed into an intermediate step
> rather than a full 1:1 translate_table replacement.
> 
> In the 2nd pass (step #3), change the 64bit ruleset back to a kernel
> representation, i.e. put() the kernel pointer and restore ->u.user.name .
> 
> This gets us a 64bit ruleset that is in the format generated by a 64bit
> iptables userspace -- we can then use translate_table() to get the
> 'native' sanity checks.
> 
> This has two drawbacks:
> 
> 1. we re-validate all the match and target entry structure sizes even
> though compat translation is supposed to never generate bogus offsets.
> 2. we put and then re-lookup each match and target.
> 
> THe upside is that we get all sanity tests and ruleset validations
> provided by the normal path and can remove some duplicated compat code.
> 
> iptables-restore time of autogenerated ruleset with 300k chains of form
> -A CHAIN0001 -m limit --limit 1/s -j CHAIN0002
> -A CHAIN0002 -m limit --limit 1/s -j CHAIN0003
> 
> shows no noticeable differences in restore times:
> old:   0m30.796s
> new:   0m31.521s
> 64bit: 0m25.674s
> 
> Signed-off-by: Florian Westphal <fw@strlen.de>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> ---
>  net/ipv4/netfilter/arp_tables.c | 109 ++++++-----------------------
>  net/ipv4/netfilter/ip_tables.c  | 151 ++++++++--------------------------------
>  net/ipv6/netfilter/ip6_tables.c | 145 ++++++--------------------------------
>  net/netfilter/x_tables.c        |   8 +++
>  4 files changed, 80 insertions(+), 333 deletions(-)
> 
> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> index 020b0e97c206..b7f3b31a3cc3 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -1223,19 +1223,17 @@ static inline void compat_release_entry(struct compat_arpt_entry *e)
>  	module_put(t->u.kernel.target->me);
>  }
>  
> -static inline int
> +static int
>  check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
>  				  struct xt_table_info *newinfo,
>  				  unsigned int *size,
>  				  const unsigned char *base,
> -				  const unsigned char *limit,
> -				  const unsigned int *hook_entries,
> -				  const unsigned int *underflows)
> +				  const unsigned char *limit)
>  {
>  	struct xt_entry_target *t;
>  	struct xt_target *target;
>  	unsigned int entry_offset;
> -	int ret, off, h;
> +	int ret, off;
>  
>  	duprintf("check_compat_entry_size_and_hooks %p\n", e);
>  	if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 ||
> @@ -1280,17 +1278,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
>  	if (ret)
>  		goto release_target;
>  
> -	/* Check hooks & underflows */
> -	for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
> -		if ((unsigned char *)e - base == hook_entries[h])
> -			newinfo->hook_entry[h] = hook_entries[h];
> -		if ((unsigned char *)e - base == underflows[h])
> -			newinfo->underflow[h] = underflows[h];
> -	}
> -
> -	/* Clear counters and comefrom */
> -	memset(&e->counters, 0, sizeof(e->counters));
> -	e->comefrom = 0;
>  	return 0;
>  
>  release_target:
> @@ -1340,7 +1327,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
>  	struct xt_table_info *newinfo, *info;
>  	void *pos, *entry0, *entry1;
>  	struct compat_arpt_entry *iter0;
> -	struct arpt_entry *iter1;
> +	struct arpt_replace repl;
>  	unsigned int size;
>  	int ret = 0;
>  
> @@ -1349,12 +1336,6 @@ static int translate_compat_table(struct xt_table_info **pinfo,
>  	size = compatr->size;
>  	info->number = compatr->num_entries;
>  
> -	/* Init all hooks to impossible value. */
> -	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
> -		info->hook_entry[i] = 0xFFFFFFFF;
> -		info->underflow[i] = 0xFFFFFFFF;
> -	}
> -
>  	duprintf("translate_compat_table: size %u\n", info->size);
>  	j = 0;
>  	xt_compat_lock(NFPROTO_ARP);
> @@ -1363,9 +1344,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
>  	xt_entry_foreach(iter0, entry0, compatr->size) {
>  		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
>  							entry0,
> -							entry0 + compatr->size,
> -							compatr->hook_entry,
> -							compatr->underflow);
> +							entry0 + compatr->size);
>  		if (ret != 0)
>  			goto out_unlock;
>  		++j;
> @@ -1378,23 +1357,6 @@ static int translate_compat_table(struct xt_table_info **pinfo,
>  		goto out_unlock;
>  	}
>  
> -	/* Check hooks all assigned */
> -	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
> -		/* Only hooks which are valid */
> -		if (!(compatr->valid_hooks & (1 << i)))
> -			continue;
> -		if (info->hook_entry[i] == 0xFFFFFFFF) {
> -			duprintf("Invalid hook entry %u %u\n",
> -				 i, info->hook_entry[i]);
> -			goto out_unlock;
> -		}
> -		if (info->underflow[i] == 0xFFFFFFFF) {
> -			duprintf("Invalid underflow %u %u\n",
> -				 i, info->underflow[i]);
> -			goto out_unlock;
> -		}
> -	}
> -
>  	ret = -ENOMEM;
>  	newinfo = xt_alloc_table_info(size);
>  	if (!newinfo)
> @@ -1411,51 +1373,25 @@ static int translate_compat_table(struct xt_table_info **pinfo,
>  	xt_entry_foreach(iter0, entry0, compatr->size)
>  		compat_copy_entry_from_user(iter0, &pos, &size,
>  					    newinfo, entry1);
> +
> +	/* all module references in entry0 are now gone */
> +
>  	xt_compat_flush_offsets(NFPROTO_ARP);
>  	xt_compat_unlock(NFPROTO_ARP);
>  
> -	ret = -ELOOP;
> -	if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
> -		goto free_newinfo;
> +	memcpy(&repl, compatr, sizeof(*compatr));
>  
> -	i = 0;
> -	xt_entry_foreach(iter1, entry1, newinfo->size) {
> -		ret = check_target(iter1, compatr->name);
> -		if (ret != 0)
> -			break;
> -		++i;
> -		if (strcmp(arpt_get_target(iter1)->u.user.name,
> -		    XT_ERROR_TARGET) == 0)
> -			++newinfo->stacksize;
> -	}
> -	if (ret) {
> -		/*
> -		 * The first i matches need cleanup_entry (calls ->destroy)
> -		 * because they had called ->check already. The other j-i
> -		 * entries need only release.
> -		 */
> -		int skip = i;
> -		j -= i;
> -		xt_entry_foreach(iter0, entry0, newinfo->size) {
> -			if (skip-- > 0)
> -				continue;
> -			if (j-- == 0)
> -				break;
> -			compat_release_entry(iter0);
> -		}
> -		xt_entry_foreach(iter1, entry1, newinfo->size) {
> -			if (i-- == 0)
> -				break;
> -			cleanup_entry(iter1);
> -		}
> -		xt_free_table_info(newinfo);
> -		return ret;
> +	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
> +		repl.hook_entry[i] = newinfo->hook_entry[i];
> +		repl.underflow[i] = newinfo->underflow[i];
>  	}
>  
> -	/* And one copy for every other CPU */
> -	for_each_possible_cpu(i)
> -		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
> -			memcpy(newinfo->entries[i], entry1, newinfo->size);

These four lines should be preserved, IMHO, as 3.12 doesn't have commit
482cfc318559 ("netfilter: xtables: avoid percpu ruleset duplication")
(introduced in 4.2) which removed the need for per-cpu copies.

The same applies to the other two instances of translate_compat_table()
in net/ipv4/netfilter/ip_tables.c and net/ipv6/netfilter/ip6_tables.c

Florian, do you agree?

Michal Kubecek

[toc] | [prev] | [next] | [standalone]


#1446252 — Re: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table

FromFlorian Westphal <fw@strlen.de>
Date2016-07-19 10:50 +0200
SubjectRe: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table
Message-ID<rWySZ-1Ms-15@gated-at.bofh.it>
In reply to#1446126
Michal Kubecek <mkubecek@suse.cz> wrote:
> > -	/* And one copy for every other CPU */
> > -	for_each_possible_cpu(i)
> > -		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
> > -			memcpy(newinfo->entries[i], entry1, newinfo->size);
> 
> These four lines should be preserved, IMHO, as 3.12 doesn't have commit
> 482cfc318559 ("netfilter: xtables: avoid percpu ruleset duplication")
> (introduced in 4.2) which removed the need for per-cpu copies.
> 
> The same applies to the other two instances of translate_compat_table()
> in net/ipv4/netfilter/ip_tables.c and net/ipv6/netfilter/ip6_tables.c
> 
> Florian, do you agree?

Sorry, I have to look at this in more detail.
The patches change the compat translation version into a preprocessing
step rather than a 1:1 replacement of translate_table.

From first glance the removal is thus ok.
I will review this later today.

Also, please be aware of this bug:
http://patchwork.ozlabs.org/patch/648446/

If possible this patchset should not be pushed to all -stable
kernels yet.

[toc] | [prev] | [next] | [standalone]


#1446276 — Re: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table

FromFlorian Westphal <fw@strlen.de>
Date2016-07-19 11:20 +0200
SubjectRe: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table
Message-ID<rWzm2-2aY-19@gated-at.bofh.it>
In reply to#1446252
Florian Westphal <fw@strlen.de> wrote:
> Michal Kubecek <mkubecek@suse.cz> wrote:
> > > -	/* And one copy for every other CPU */
> > > -	for_each_possible_cpu(i)
> > > -		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
> > > -			memcpy(newinfo->entries[i], entry1, newinfo->size);
> > 
> > These four lines should be preserved, IMHO, as 3.12 doesn't have commit
> > 482cfc318559 ("netfilter: xtables: avoid percpu ruleset duplication")
> > (introduced in 4.2) which removed the need for per-cpu copies.
> > 
> > The same applies to the other two instances of translate_compat_table()
> > in net/ipv4/netfilter/ip_tables.c and net/ipv6/netfilter/ip6_tables.c
> > 
> > Florian, do you agree?
> 
> Sorry, I have to look at this in more detail.
> The patches change the compat translation version into a preprocessing
> step rather than a 1:1 replacement of translate_table.
> 
> From first glance the removal is thus ok.

Removal is correct, the expanded ruleset is passed to
translate_table() which will do the percpu duplication as last step.

[ I looked at 3.14.y tree which also dropped these lines in the backport ]

[toc] | [prev] | [next] | [standalone]


#1446296 — Re: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table

FromMichal Kubecek <mkubecek@suse.cz>
Date2016-07-19 11:50 +0200
SubjectRe: [PATCH 3.12 42/88] netfilter: x_tables: do compat validation via translate_table
Message-ID<rWzP3-2ko-9@gated-at.bofh.it>
In reply to#1446276
On Tue, Jul 19, 2016 at 11:13:12AM +0200, Florian Westphal wrote:
> Florian Westphal <fw@strlen.de> wrote:
> > Michal Kubecek <mkubecek@suse.cz> wrote:
> > > > -	/* And one copy for every other CPU */
> > > > -	for_each_possible_cpu(i)
> > > > -		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
> > > > -			memcpy(newinfo->entries[i], entry1, newinfo->size);
> > > 
> > > These four lines should be preserved, IMHO, as 3.12 doesn't have commit
> > > 482cfc318559 ("netfilter: xtables: avoid percpu ruleset duplication")
> > > (introduced in 4.2) which removed the need for per-cpu copies.
> > > 
> > > The same applies to the other two instances of translate_compat_table()
> > > in net/ipv4/netfilter/ip_tables.c and net/ipv6/netfilter/ip6_tables.c
> > > 
> > > Florian, do you agree?
> > 
> > Sorry, I have to look at this in more detail.
> > The patches change the compat translation version into a preprocessing
> > step rather than a 1:1 replacement of translate_table.
> > 
> > From first glance the removal is thus ok.
> 
> Removal is correct, the expanded ruleset is passed to
> translate_table() which will do the percpu duplication as last step.
> 
> [ I looked at 3.14.y tree which also dropped these lines in the backport ]

You are right, I didn't notice that. Thanks for the clarification.
I'll send v2 of the patch for 4.1 stable in a moment.

Michal Kubecek

[toc] | [prev] | [next] | [standalone]


#1443251 — [PATCH 3.12 49/88] usb: quirks: Add no-lpm quirk for Acer C120 LED Projector

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:40 +0200
Subject[PATCH 3.12 49/88] usb: quirks: Add no-lpm quirk for Acer C120 LED Projector
Message-ID<rUKlB-7jX-79@gated-at.bofh.it>
In reply to#1443166
From: Hans de Goede <hdegoede@redhat.com>

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

===============

commit 32cb0b37098f4beeff5ad9e325f11b42a6ede56c upstream.

The Acer C120 LED Projector is a USB-3 connected pico projector which
takes both its power and video data from USB-3.

In combination with some hubs this device does not play well with
lpm, so disable lpm for it.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/usb/core/quirks.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 9596d4f3e71a..ba39d978583c 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -225,6 +225,9 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = {
 	/* Logitech Optical Mouse M90/M100 */
 	{ USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Acer C120 LED Projector */
+	{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },
+
 	/* Blackmagic Design Intensity Shuttle */
 	{ USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM },
 
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


#1443261 — [PATCH 3.12 19/88] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS

FromJiri Slaby <jslaby@suse.cz>
Date2016-07-14 10:50 +0200
Subject[PATCH 3.12 19/88] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS
Message-ID<rUKvf-7nE-1@gated-at.bofh.it>
In reply to#1443166
From: Paolo Bonzini <pbonzini@redhat.com>

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

===============

commit d14bdb553f9196169f003058ae1cdabe514470e6 upstream.

MOV to DR6 or DR7 causes a #GP if an attempt is made to write a 1 to
any of bits 63:32.  However, this is not detected at KVM_SET_DEBUGREGS
time, and the next KVM_RUN oopses:

   general protection fault: 0000 [#1] SMP
   CPU: 2 PID: 14987 Comm: a.out Not tainted 4.4.9-300.fc23.x86_64 #1
   Hardware name: LENOVO 2325F51/2325F51, BIOS G2ET32WW (1.12 ) 05/30/2012
   [...]
   Call Trace:
    [<ffffffffa072c93d>] kvm_arch_vcpu_ioctl_run+0x141d/0x14e0 [kvm]
    [<ffffffffa071405d>] kvm_vcpu_ioctl+0x33d/0x620 [kvm]
    [<ffffffff81241648>] do_vfs_ioctl+0x298/0x480
    [<ffffffff812418a9>] SyS_ioctl+0x79/0x90
    [<ffffffff817a0f2e>] entry_SYSCALL_64_fastpath+0x12/0x71
   Code: 55 83 ff 07 48 89 e5 77 27 89 ff ff 24 fd 90 87 80 81 0f 23 fe 5d c3 0f 23 c6 5d c3 0f 23 ce 5d c3 0f 23 d6 5d c3 0f 23 de 5d c3 <0f> 23 f6 5d c3 0f 0b 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
   RIP  [<ffffffff810639eb>] native_set_debugreg+0x2b/0x40
    RSP <ffff88005836bd50>

Testcase (beautified/reduced from syzkaller output):

    #include <unistd.h>
    #include <sys/syscall.h>
    #include <string.h>
    #include <stdint.h>
    #include <linux/kvm.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>

    long r[8];

    int main()
    {
        struct kvm_debugregs dr = { 0 };

        r[2] = open("/dev/kvm", O_RDONLY);
        r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
        r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);

        memcpy(&dr,
               "\x5d\x6a\x6b\xe8\x57\x3b\x4b\x7e\xcf\x0d\xa1\x72"
               "\xa3\x4a\x29\x0c\xfc\x6d\x44\x00\xa7\x52\xc7\xd8"
               "\x00\xdb\x89\x9d\x78\xb5\x54\x6b\x6b\x13\x1c\xe9"
               "\x5e\xd3\x0e\x40\x6f\xb4\x66\xf7\x5b\xe3\x36\xcb",
               48);
        r[7] = ioctl(r[4], KVM_SET_DEBUGREGS, &dr);
        r[6] = ioctl(r[4], KVM_RUN, 0);
    }

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 arch/x86/kvm/x86.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e0c859e1999a..06b37a671b12 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3009,6 +3009,11 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
 	if (dbgregs->flags)
 		return -EINVAL;
 
+	if (dbgregs->dr6 & ~0xffffffffull)
+		return -EINVAL;
+	if (dbgregs->dr7 & ~0xffffffffull)
+		return -EINVAL;
+
 	memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db));
 	vcpu->arch.dr6 = dbgregs->dr6;
 	vcpu->arch.dr7 = dbgregs->dr7;
-- 
2.9.1

[toc] | [prev] | [next] | [standalone]


Page 3 of 5 — ← Prev page 1 2 [3] 4 5  Next page →

Back to top | Article view | linux.kernel


csiph-web