* [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information
@ 2016-07-12 9:40 Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] drivers: macintosh: rack-meter: limit idle ticks to total ticks Jiri Slaby
` (50 more replies)
0 siblings, 51 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable
Cc: Javier Martinez Canillas, Michael Ellerman, Oliver Neukum,
Jiri Slaby
From: Javier Martinez Canillas <javier@osg.samsung.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit cb0eefcc3271ea1d370476dd29685918b99c5a9f upstream.
The I2C core always reports the MODALIAS uevent as "i2c:<client name"
regardless if the driver was matched using the I2C id_table or the
of_match_table. So the driver needs to export the I2C table and this
be built into the module or udev won't have the necessary information
to auto load the correct module when the device is added.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Cc: Oliver Neukum <oliver@neukum.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
drivers/macintosh/therm_windtunnel.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 3b4a157714b1..b40ed32379ec 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -408,6 +408,7 @@ static const struct i2c_device_id therm_windtunnel_id[] = {
{ "therm_adm1030", adm1030 },
{ }
};
+MODULE_DEVICE_TABLE(i2c, therm_windtunnel_id);
static int
do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] drivers: macintosh: rack-meter: limit idle ticks to total ticks
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS Jiri Slaby
` (49 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Aaro Koskinen, Michael Ellerman, Oliver Neukum, Jiri Slaby
From: Aaro Koskinen <aaro.koskinen@iki.fi>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit c796d1d97c3035cf54d4d5a9e75abd094db80e76 upstream.
Limit idle ticks to total ticks. This prevents the annoying rackmeter
leds fully ON / OFF blinking state that happens on fully idling
G5 Xserve systems.
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Cc: Oliver Neukum <oliver@neukum.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
drivers/macintosh/rack-meter.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index cad0e19b47a2..0b569da3c467 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -225,6 +225,7 @@ static void rackmeter_do_timer(struct work_struct *work)
total_idle_ticks = get_cpu_idle_time(cpu);
idle_ticks = (unsigned int) (total_idle_ticks - rcpu->prev_idle);
+ idle_ticks = min(idle_ticks, total_ticks);
rcpu->prev_idle = total_idle_ticks;
/* We do a very dumb calculation to update the LEDs for now,
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] drivers: macintosh: rack-meter: limit idle ticks to total ticks Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] ARM: fix PTRACE_SETVFPREGS on SMP systems Jiri Slaby
` (48 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Paolo Bonzini, Radim Krčmář, Jiri Slaby
From: Paolo Bonzini <pbonzini@redhat.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] ARM: fix PTRACE_SETVFPREGS on SMP systems
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] drivers: macintosh: rack-meter: limit idle ticks to total ticks Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] powerpc: Fix definition of SIAR and SDAR registers Jiri Slaby
` (47 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Russell King, Jiri Slaby
From: Russell King <rmk+kernel@armlinux.org.uk>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit e2dfb4b880146bfd4b6aa8e138c0205407cebbaf upstream.
PTRACE_SETVFPREGS fails to properly mark the VFP register set to be
reloaded, because it undoes one of the effects of vfp_flush_hwstate().
Specifically vfp_flush_hwstate() sets thread->vfpstate.hard.cpu to
an invalid CPU number, but vfp_set() overwrites this with the original
CPU number, thereby rendering the hardware state as apparently "valid",
even though the software state is more recent.
Fix this by reverting the previous change.
Fixes: 8130b9d7b9d8 ("ARM: 7308/1: vfp: flush thread hwstate before copying ptrace registers")
Acked-by: Will Deacon <will.deacon@arm.com>
Tested-by: Simon Marchi <simon.marchi@ericsson.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
arch/arm/kernel/ptrace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 0dd3b79b15c3..ec33df500f86 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target,
if (ret)
return ret;
- vfp_flush_hwstate(thread);
thread->vfpstate.hard = new_vfp;
+ vfp_flush_hwstate(thread);
return 0;
}
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] powerpc: Fix definition of SIAR and SDAR registers
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (2 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] ARM: fix PTRACE_SETVFPREGS on SMP systems Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] powerpc: Use privileged SPR number for MMCR2 Jiri Slaby
` (46 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Thomas Huth, Michael Ellerman, Jiri Slaby
From: Thomas Huth <thuth@redhat.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit d23fac2b27d94aeb7b65536a50d32bfdc21fe01e upstream.
The SIAR and SDAR registers are available twice, one time as SPRs
780 / 781 (unprivileged, but read-only), and one time as the SPRs
796 / 797 (privileged, but read and write). The Linux kernel code
currently uses the unprivileged SPRs - while this is OK for reading,
writing to that register of course does not work.
Since the KVM code tries to write to this register, too (see the mtspr
in book3s_hv_rmhandlers.S), the contents of this register sometimes get
lost for the guests, e.g. during migration of a VM.
To fix this issue, simply switch to the privileged SPR numbers instead.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Acked-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
arch/powerpc/include/asm/reg.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 3ce6b7b5ca19..ad261d56ae39 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -681,13 +681,13 @@
#define SPRN_PMC6 792
#define SPRN_PMC7 793
#define SPRN_PMC8 794
-#define SPRN_SIAR 780
-#define SPRN_SDAR 781
#define SPRN_SIER 784
#define SIER_SIPR 0x2000000 /* Sampled MSR_PR */
#define SIER_SIHV 0x1000000 /* Sampled MSR_HV */
#define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */
#define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */
+#define SPRN_SIAR 796
+#define SPRN_SDAR 797
/* When EBB is enabled, some of MMCR0/MMCR2/SIER are user accessible */
#define MMCR0_USER_MASK (MMCR0_FC | MMCR0_PMXE | MMCR0_PMAO)
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] powerpc: Use privileged SPR number for MMCR2
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (3 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] powerpc: Fix definition of SIAR and SDAR registers Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] parisc: Fix pagefault crash in unaligned __get_user() call Jiri Slaby
` (45 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Thomas Huth, Michael Ellerman, Jiri Slaby
From: Thomas Huth <thuth@redhat.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 8dd75ccb571f3c92c48014b3dabd3d51a115ab41 upstream.
We are already using the privileged versions of MMCR0, MMCR1
and MMCRA in the kernel, so for MMCR2, we should better use
the privileged versions, too, to be consistent.
Fixes: 240686c13687 ("powerpc: Initialise PMU related regs on Power8")
Suggested-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Acked-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
arch/powerpc/include/asm/reg.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index ad261d56ae39..53762dbf547c 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -647,7 +647,7 @@
#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
#define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */
#define SPRN_MMCR1 798
-#define SPRN_MMCR2 769
+#define SPRN_MMCR2 785
#define SPRN_MMCRA 0x312
#define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
#define MMCRA_SDAR_DCACHE_MISS 0x40000000UL
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] parisc: Fix pagefault crash in unaligned __get_user() call
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (4 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] powerpc: Use privileged SPR number for MMCR2 Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] ecryptfs: forbid opening files without mmap handler Jiri Slaby
` (44 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Helge Deller, Jiri Slaby
From: Helge Deller <deller@gmx.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 8b78f260887df532da529f225c49195d18fef36b upstream.
One of the debian buildd servers had this crash in the syslog without
any other information:
Unaligned handler failed, ret = -2
clock_adjtime (pid 22578): Unaligned data reference (code 28)
CPU: 1 PID: 22578 Comm: clock_adjtime Tainted: G E 4.5.0-2-parisc64-smp #1 Debian 4.5.4-1
task: 000000007d9960f8 ti: 00000001bde7c000 task.ti: 00000001bde7c000
YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
PSW: 00001000000001001111100000001111 Tainted: G E
r00-03 000000ff0804f80f 00000001bde7c2b0 00000000402d2be8 00000001bde7c2b0
r04-07 00000000409e1fd0 00000000fa6f7fff 00000001bde7c148 00000000fa6f7fff
r08-11 0000000000000000 00000000ffffffff 00000000fac9bb7b 000000000002b4d4
r12-15 000000000015241c 000000000015242c 000000000000002d 00000000fac9bb7b
r16-19 0000000000028800 0000000000000001 0000000000000070 00000001bde7c218
r20-23 0000000000000000 00000001bde7c210 0000000000000002 0000000000000000
r24-27 0000000000000000 0000000000000000 00000001bde7c148 00000000409e1fd0
r28-31 0000000000000001 00000001bde7c320 00000001bde7c350 00000001bde7c218
sr00-03 0000000001200000 0000000001200000 0000000000000000 0000000001200000
sr04-07 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IASQ: 0000000000000000 0000000000000000 IAOQ: 00000000402d2e84 00000000402d2e88
IIR: 0ca0d089 ISR: 0000000001200000 IOR: 00000000fa6f7fff
CPU: 1 CR30: 00000001bde7c000 CR31: ffffffffffffffff
ORIG_R28: 00000002369fe628
IAOQ[0]: compat_get_timex+0x2dc/0x3c0
IAOQ[1]: compat_get_timex+0x2e0/0x3c0
RP(r2): compat_get_timex+0x40/0x3c0
Backtrace:
[<00000000402d4608>] compat_SyS_clock_adjtime+0x40/0xc0
[<0000000040205024>] syscall_exit+0x0/0x14
This means the userspace program clock_adjtime called the clock_adjtime()
syscall and then crashed inside the compat_get_timex() function.
Syscalls should never crash programs, but instead return EFAULT.
The IIR register contains the executed instruction, which disassebles
into "ldw 0(sr3,r5),r9".
This load-word instruction is part of __get_user() which tried to read the word
at %r5/IOR (0xfa6f7fff). This means the unaligned handler jumped in. The
unaligned handler is able to emulate all ldw instructions, but it fails if it
fails to read the source e.g. because of page fault.
The following program reproduces the problem:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
int main(void) {
/* allocate 8k */
char *ptr = mmap(NULL, 2*4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
/* free second half (upper 4k) and make it invalid. */
munmap(ptr+4096, 4096);
/* syscall where first int is unaligned and clobbers into invalid memory region */
/* syscall should return EFAULT */
return syscall(__NR_clock_adjtime, 0, ptr+4095);
}
To fix this issue we simply need to check if the faulting instruction address
is in the exception fixup table when the unaligned handler failed. If it
is, call the fixup routine instead of crashing.
While looking at the unaligned handler I found another issue as well: The
target register should not be modified if the handler was unsuccessful.
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
arch/parisc/kernel/unaligned.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index d7c0acb35ec2..8d49614d600d 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -666,7 +666,7 @@ void handle_unaligned(struct pt_regs *regs)
break;
}
- if (modify && R1(regs->iir))
+ if (ret == 0 && modify && R1(regs->iir))
regs->gr[R1(regs->iir)] = newbase;
@@ -677,6 +677,14 @@ void handle_unaligned(struct pt_regs *regs)
if (ret)
{
+ /*
+ * The unaligned handler failed.
+ * If we were called by __get_user() or __put_user() jump
+ * to it's exception fixup handler instead of crashing.
+ */
+ if (!user_mode(regs) && fixup_exception(regs))
+ return;
+
printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
die_if_kernel("Unaligned data reference", regs, 28);
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] ecryptfs: forbid opening files without mmap handler
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (5 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] parisc: Fix pagefault crash in unaligned __get_user() call Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel Jiri Slaby
` (43 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Jann Horn, Linus Torvalds, Jiri Slaby
From: Jann Horn <jannh@google.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 2f36db71009304b3f0b95afacd8eba1f9f046b87 upstream.
This prevents users from triggering a stack overflow through a recursive
invocation of pagefault handling that involves mapping procfs files into
virtual memory.
Signed-off-by: Jann Horn <jannh@google.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
fs/ecryptfs/kthread.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
index f1ea610362c6..9b661a4ccee7 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/mount.h>
+#include <linux/file.h>
#include "ecryptfs_kernel.h"
struct ecryptfs_open_req {
@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
(*lower_file) = dentry_open(&req.path, flags, cred);
if (!IS_ERR(*lower_file))
- goto out;
+ goto have_file;
if ((flags & O_ACCMODE) == O_RDONLY) {
rc = PTR_ERR((*lower_file));
goto out;
@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file **lower_file,
mutex_unlock(&ecryptfs_kthread_ctl.mux);
wake_up(&ecryptfs_kthread_ctl.wait);
wait_for_completion(&req.done);
- if (IS_ERR(*lower_file))
+ if (IS_ERR(*lower_file)) {
rc = PTR_ERR(*lower_file);
+ goto out;
+ }
+have_file:
+ if ((*lower_file)->f_op->mmap == NULL) {
+ fput(*lower_file);
+ *lower_file = NULL;
+ rc = -EMEDIUMTYPE;
+ }
out:
return rc;
}
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (6 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] ecryptfs: forbid opening files without mmap handler Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] fix d_walk()/non-delayed __d_free() race Jiri Slaby
` (42 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Prasun Maiti, Ujjal Roy, Johannes Berg, Jiri Slaby
From: Prasun Maiti <prasunmaiti87@gmail.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 3d5fdff46c4b2b9534fa2f9fc78e90a48e0ff724 upstream.
iwpriv app uses iw_point structure to send data to Kernel. The iw_point
structure holds a pointer. For compatibility Kernel converts the pointer
as required for WEXT IOCTLs (SIOCIWFIRST to SIOCIWLAST). Some drivers
may use iw_handler_def.private_args to populate iwpriv commands instead
of iw_handler_def.private. For those case, the IOCTLs from
SIOCIWFIRSTPRIV to SIOCIWLASTPRIV will follow the path ndo_do_ioctl().
Accordingly when the filled up iw_point structure comes from 32 bit
iwpriv to 64 bit Kernel, Kernel will not convert the pointer and sends
it to driver. So, the driver may get the invalid data.
The pointer conversion for the IOCTLs (SIOCIWFIRSTPRIV to
SIOCIWLASTPRIV), which follow the path ndo_do_ioctl(), is mandatory.
This patch adds pointer conversion from 32 bit to 64 bit and vice versa,
if the ioctl comes from 32 bit iwpriv to 64 bit Kernel.
Signed-off-by: Prasun Maiti <prasunmaiti87@gmail.com>
Signed-off-by: Ujjal Roy <royujjal@gmail.com>
Tested-by: Dibyajyoti Ghosh <dibyajyotig@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
net/wireless/wext-core.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index 87dd619fb2e9..1c9a505b7019 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -954,8 +954,29 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
return private(dev, iwr, cmd, info, handler);
}
/* Old driver API : call driver ioctl handler */
- if (dev->netdev_ops->ndo_do_ioctl)
- return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+ if (dev->netdev_ops->ndo_do_ioctl) {
+#ifdef CONFIG_COMPAT
+ if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+ int ret = 0;
+ struct iwreq iwr_lcl;
+ struct compat_iw_point *iwp_compat = (void *) &iwr->u.data;
+
+ memcpy(&iwr_lcl, iwr, sizeof(struct iwreq));
+ iwr_lcl.u.data.pointer = compat_ptr(iwp_compat->pointer);
+ iwr_lcl.u.data.length = iwp_compat->length;
+ iwr_lcl.u.data.flags = iwp_compat->flags;
+
+ ret = dev->netdev_ops->ndo_do_ioctl(dev, (void *) &iwr_lcl, cmd);
+
+ iwp_compat->pointer = ptr_to_compat(iwr_lcl.u.data.pointer);
+ iwp_compat->length = iwr_lcl.u.data.length;
+ iwp_compat->flags = iwr_lcl.u.data.flags;
+
+ return ret;
+ } else
+#endif
+ return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+ }
return -EOPNOTSUPP;
}
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] fix d_walk()/non-delayed __d_free() race
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (7 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: don't move to non-existent next rule Jiri Slaby
` (41 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Al Viro, Jiri Slaby
From: Al Viro <viro@zeniv.linux.org.uk>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 3d56c25e3bb0726a5c5e16fc2d9e38f8ed763085 upstream.
Ascend-to-parent logics in d_walk() depends on all encountered child
dentries not getting freed without an RCU delay. Unfortunately, in
quite a few cases it is not true, with hard-to-hit oopsable race as
the result.
Fortunately, the fix is simiple; right now the rule is "if it ever
been hashed, freeing must be delayed" and changing it to "if it
ever had a parent, freeing must be delayed" closes that hole and
covers all cases the old rule used to cover. Moreover, pipes and
sockets remain _not_ covered, so we do not introduce RCU delay in
the cases which are the reason for having that delay conditional
in the first place.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
fs/dcache.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index 40bf046884b1..9befdcea22fa 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1529,7 +1529,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
struct dentry *dentry = __d_alloc(parent->d_sb, name);
if (!dentry)
return NULL;
-
+ dentry->d_flags |= DCACHE_RCUACCESS;
spin_lock(&parent->d_lock);
/*
* don't need child lock because it is not subject
@@ -2319,7 +2319,6 @@ static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
{
BUG_ON(!d_unhashed(entry));
hlist_bl_lock(b);
- entry->d_flags |= DCACHE_RCUACCESS;
hlist_bl_add_head_rcu(&entry->d_hash, b);
hlist_bl_unlock(b);
}
@@ -2503,6 +2502,7 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
/* ... and switch the parents */
if (IS_ROOT(dentry)) {
+ dentry->d_flags |= DCACHE_RCUACCESS;
dentry->d_parent = target->d_parent;
target->d_parent = target;
INIT_LIST_HEAD(&target->d_child);
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: don't move to non-existent next rule
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (8 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] fix d_walk()/non-delayed __d_free() race Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: validate targets of jumps Jiri Slaby
` (40 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit f24e230d257af1ad7476c6e81a8dc3127a74204e upstream.
Ben Hawkes says:
In the mark_source_chains function (net/ipv4/netfilter/ip_tables.c) it
is possible for a user-supplied ipt_entry structure to have a large
next_offset field. This field is not bounds checked prior to writing a
counter value at the supplied offset.
Base chains enforce absolute verdict.
User defined chains are supposed to end with an unconditional return,
xtables userspace adds them automatically.
But if such return is missing we will move to non-existent next rule.
Reported-by: Ben Hawkes <hawkes@google.com>
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 | 8 +++++---
net/ipv4/netfilter/ip_tables.c | 4 ++++
net/ipv6/netfilter/ip6_tables.c | 4 ++++
3 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 456fc6efe05d..7460b7bef3ab 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -430,6 +430,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
size = e->next_offset;
e = (struct arpt_entry *)
(entry0 + pos + size);
+ if (pos + size >= newinfo->size)
+ return 0;
e->counters.pcnt = pos;
pos += size;
} else {
@@ -452,6 +454,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
+ if (newpos >= newinfo->size)
+ return 0;
}
e = (struct arpt_entry *)
(entry0 + newpos);
@@ -675,10 +679,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
}
}
- if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) {
- duprintf("Looping hook\n");
+ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
return -ELOOP;
- }
/* Finally, each sanity check must pass */
i = 0;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index a5bd3c8eee84..8fc22eed9603 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -511,6 +511,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
size = e->next_offset;
e = (struct ipt_entry *)
(entry0 + pos + size);
+ if (pos + size >= newinfo->size)
+ return 0;
e->counters.pcnt = pos;
pos += size;
} else {
@@ -532,6 +534,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
+ if (newpos >= newinfo->size)
+ return 0;
}
e = (struct ipt_entry *)
(entry0 + newpos);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index fb8a146abed8..63f7876c4f29 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -521,6 +521,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
size = e->next_offset;
e = (struct ip6t_entry *)
(entry0 + pos + size);
+ if (pos + size >= newinfo->size)
+ return 0;
e->counters.pcnt = pos;
pos += size;
} else {
@@ -542,6 +544,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
+ if (newpos >= newinfo->size)
+ return 0;
}
e = (struct ip6t_entry *)
(entry0 + newpos);
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: validate targets of jumps
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (9 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: don't move to non-existent next rule Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: add and use xt_check_entry_offsets Jiri Slaby
` (39 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 36472341017529e2b12573093cc0f68719300997 upstream.
When we see a jump also check that the offset gets us to beginning of
a rule (an ipt_entry).
The extra overhead is negible, even with absurd cases.
300k custom rules, 300k jumps to 'next' user chain:
[ plus one jump from INPUT to first userchain ]:
Before:
real 0m24.874s
user 0m7.532s
sys 0m16.076s
After:
real 0m27.464s
user 0m7.436s
sys 0m18.840s
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 | 17 +++++++++++++++++
net/ipv4/netfilter/ip_tables.c | 17 +++++++++++++++++
net/ipv6/netfilter/ip6_tables.c | 17 +++++++++++++++++
3 files changed, 51 insertions(+)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 7460b7bef3ab..473ec559ce7b 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -358,6 +358,19 @@ static inline bool unconditional(const struct arpt_entry *e)
memcmp(&e->arp, &uncond, sizeof(uncond)) == 0;
}
+static bool find_jump_target(const struct xt_table_info *t,
+ const void *entry0,
+ const struct arpt_entry *target)
+{
+ struct arpt_entry *iter;
+
+ xt_entry_foreach(iter, entry0, t->size) {
+ if (iter == target)
+ return true;
+ }
+ return false;
+}
+
/* Figures out from what hook each rule can be called: returns 0 if
* there are loops. Puts hook bitmask in comefrom.
*/
@@ -451,6 +464,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
+ e = (struct arpt_entry *)
+ (entry0 + newpos);
+ if (!find_jump_target(newinfo, entry0, e))
+ return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 8fc22eed9603..dba9d8070d07 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -434,6 +434,19 @@ ipt_do_table(struct sk_buff *skb,
#endif
}
+static bool find_jump_target(const struct xt_table_info *t,
+ const void *entry0,
+ const struct ipt_entry *target)
+{
+ struct ipt_entry *iter;
+
+ xt_entry_foreach(iter, entry0, t->size) {
+ if (iter == target)
+ return true;
+ }
+ return false;
+}
+
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
@@ -531,6 +544,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
+ e = (struct ipt_entry *)
+ (entry0 + newpos);
+ if (!find_jump_target(newinfo, entry0, e))
+ return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 63f7876c4f29..97a8d2525c26 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -444,6 +444,19 @@ ip6t_do_table(struct sk_buff *skb,
#endif
}
+static bool find_jump_target(const struct xt_table_info *t,
+ const void *entry0,
+ const struct ip6t_entry *target)
+{
+ struct ip6t_entry *iter;
+
+ xt_entry_foreach(iter, entry0, t->size) {
+ if (iter == target)
+ return true;
+ }
+ return false;
+}
+
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
@@ -541,6 +554,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
+ e = (struct ip6t_entry *)
+ (entry0 + newpos);
+ if (!find_jump_target(newinfo, entry0, e))
+ return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: add and use xt_check_entry_offsets
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (10 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: validate targets of jumps Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: kill check_entry helper Jiri Slaby
` (38 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 7d35812c3214afa5b37a675113555259cfd67b98 upstream.
Currently arp/ip and ip6tables each implement a short helper to check that
the target offset is large enough to hold one xt_entry_target struct and
that t->u.target_size fits within the current rule.
Unfortunately these checks are not sufficient.
To avoid adding new tests to all of ip/ip6/arptables move the current
checks into a helper, then extend this helper in followup patches.
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 | 4 ++++
net/ipv4/netfilter/arp_tables.c | 11 +----------
net/ipv4/netfilter/ip_tables.c | 12 +-----------
net/ipv6/netfilter/ip6_tables.c | 12 +-----------
net/netfilter/x_tables.c | 34 ++++++++++++++++++++++++++++++++++
5 files changed, 41 insertions(+), 32 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index dd49566315c6..20ced1191c50 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -239,6 +239,10 @@ extern void xt_unregister_match(struct xt_match *target);
extern int xt_register_matches(struct xt_match *match, unsigned int n);
extern void xt_unregister_matches(struct xt_match *match, unsigned int n);
+int xt_check_entry_offsets(const void *base,
+ unsigned int target_offset,
+ unsigned int next_offset);
+
extern int xt_check_match(struct xt_mtchk_param *,
unsigned int size, u_int8_t proto, bool inv_proto);
extern int xt_check_target(struct xt_tgchk_param *,
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 473ec559ce7b..7232b8301ea9 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -488,19 +488,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
static inline int check_entry(const struct arpt_entry *e)
{
- const struct xt_entry_target *t;
-
if (!arp_checkentry(&e->arp))
return -EINVAL;
- if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset)
- return -EINVAL;
-
- t = arpt_get_target_c(e);
- if (e->target_offset + t->u.target_size > e->next_offset)
- return -EINVAL;
-
- return 0;
+ return xt_check_entry_offsets(e, e->target_offset, e->next_offset);
}
static inline int check_target(struct arpt_entry *e, const char *name)
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index dba9d8070d07..ce2ba7365434 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -582,20 +582,10 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net)
static int
check_entry(const struct ipt_entry *e)
{
- const struct xt_entry_target *t;
-
if (!ip_checkentry(&e->ip))
return -EINVAL;
- if (e->target_offset + sizeof(struct xt_entry_target) >
- e->next_offset)
- return -EINVAL;
-
- t = ipt_get_target_c(e);
- if (e->target_offset + t->u.target_size > e->next_offset)
- return -EINVAL;
-
- return 0;
+ return xt_check_entry_offsets(e, e->target_offset, e->next_offset);
}
static int
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 97a8d2525c26..ac061d40f920 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -592,20 +592,10 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net)
static int
check_entry(const struct ip6t_entry *e)
{
- const struct xt_entry_target *t;
-
if (!ip6_checkentry(&e->ipv6))
return -EINVAL;
- if (e->target_offset + sizeof(struct xt_entry_target) >
- e->next_offset)
- return -EINVAL;
-
- t = ip6t_get_target_c(e);
- if (e->target_offset + t->u.target_size > e->next_offset)
- return -EINVAL;
-
- return 0;
+ return xt_check_entry_offsets(e, e->target_offset, e->next_offset);
}
static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8b03028cca69..55b1e0ccb0e2 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -560,6 +560,40 @@ int xt_compat_match_to_user(const struct xt_entry_match *m,
EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
#endif /* CONFIG_COMPAT */
+/**
+ * xt_check_entry_offsets - validate arp/ip/ip6t_entry
+ *
+ * @base: pointer to arp/ip/ip6t_entry
+ * @target_offset: the arp/ip/ip6_t->target_offset
+ * @next_offset: the arp/ip/ip6_t->next_offset
+ *
+ * validates that target_offset and next_offset are sane.
+ *
+ * The arp/ip/ip6t_entry structure @base must have passed following tests:
+ * - it must point to a valid memory location
+ * - base to base + next_offset must be accessible, i.e. not exceed allocated
+ * length.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int xt_check_entry_offsets(const void *base,
+ unsigned int target_offset,
+ unsigned int next_offset)
+{
+ const struct xt_entry_target *t;
+ const char *e = base;
+
+ if (target_offset + sizeof(*t) > next_offset)
+ return -EINVAL;
+
+ t = (void *)(e + target_offset);
+ if (target_offset + t->u.target_size > next_offset)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(xt_check_entry_offsets);
+
int xt_check_target(struct xt_tgchk_param *par,
unsigned int size, u_int8_t proto, bool inv_proto)
{
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: kill check_entry helper
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (11 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: add and use xt_check_entry_offsets Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: assert minimum target size Jiri Slaby
` (37 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit aa412ba225dd3bc36d404c28cdc3d674850d80d0 upstream.
Once we add more sanity testing to xt_check_entry_offsets it
becomes relvant if we're expecting a 32bit 'config_compat' blob
or a normal one.
Since we already have a lot of similar-named functions (check_entry,
compat_check_entry, find_and_check_entry, etc.) and the current
incarnation is short just fold its contents into the callers.
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 | 19 ++++++++-----------
net/ipv4/netfilter/ip_tables.c | 20 ++++++++------------
net/ipv6/netfilter/ip6_tables.c | 20 ++++++++------------
3 files changed, 24 insertions(+), 35 deletions(-)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 7232b8301ea9..99b28387ef6f 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -486,14 +486,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
return 1;
}
-static inline int check_entry(const struct arpt_entry *e)
-{
- if (!arp_checkentry(&e->arp))
- return -EINVAL;
-
- return xt_check_entry_offsets(e, e->target_offset, e->next_offset);
-}
-
static inline int check_target(struct arpt_entry *e, const char *name)
{
struct xt_entry_target *t = arpt_get_target(e);
@@ -583,7 +575,10 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
return -EINVAL;
}
- err = check_entry(e);
+ if (!arp_checkentry(&e->arp))
+ return -EINVAL;
+
+ err = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
if (err)
return err;
@@ -1242,8 +1237,10 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
return -EINVAL;
}
- /* For purposes of check_entry casting the compat entry is fine */
- ret = check_entry((struct arpt_entry *)e);
+ if (!arp_checkentry(&e->arp))
+ return -EINVAL;
+
+ ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
if (ret)
return ret;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index ce2ba7365434..f5fe7e66610b 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -580,15 +580,6 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net)
}
static int
-check_entry(const struct ipt_entry *e)
-{
- if (!ip_checkentry(&e->ip))
- return -EINVAL;
-
- return xt_check_entry_offsets(e, e->target_offset, e->next_offset);
-}
-
-static int
check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
{
const struct ipt_ip *ip = par->entryinfo;
@@ -744,7 +735,10 @@ check_entry_size_and_hooks(struct ipt_entry *e,
return -EINVAL;
}
- err = check_entry(e);
+ if (!ip_checkentry(&e->ip))
+ return -EINVAL;
+
+ err = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
if (err)
return err;
@@ -1508,8 +1502,10 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
return -EINVAL;
}
- /* For purposes of check_entry casting the compat entry is fine */
- ret = check_entry((struct ipt_entry *)e);
+ if (!ip_checkentry(&e->ip))
+ return -EINVAL;
+
+ ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
if (ret)
return ret;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index ac061d40f920..e9ee3feba843 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -589,15 +589,6 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net)
module_put(par.match->me);
}
-static int
-check_entry(const struct ip6t_entry *e)
-{
- if (!ip6_checkentry(&e->ipv6))
- return -EINVAL;
-
- return xt_check_entry_offsets(e, e->target_offset, e->next_offset);
-}
-
static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
{
const struct ip6t_ip6 *ipv6 = par->entryinfo;
@@ -755,7 +746,10 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
return -EINVAL;
}
- err = check_entry(e);
+ if (!ip6_checkentry(&e->ipv6))
+ return -EINVAL;
+
+ err = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
if (err)
return err;
@@ -1520,8 +1514,10 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
return -EINVAL;
}
- /* For purposes of check_entry casting the compat entry is fine */
- ret = check_entry((struct ip6t_entry *)e);
+ if (!ip6_checkentry(&e->ipv6))
+ return -EINVAL;
+
+ ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
if (ret)
return ret;
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: assert minimum target size
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (12 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: kill check_entry helper Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: add compat version of xt_check_entry_offsets Jiri Slaby
` (36 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit a08e4e190b866579896c09af59b3bdca821da2cd upstream.
The target size includes the size of the xt_entry_target struct.
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/netfilter/x_tables.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 55b1e0ccb0e2..cc34bb38c814 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -587,6 +587,9 @@ int xt_check_entry_offsets(const void *base,
return -EINVAL;
t = (void *)(e + target_offset);
+ if (t->u.target_size < sizeof(*t))
+ return -EINVAL;
+
if (target_offset + t->u.target_size > next_offset)
return -EINVAL;
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: add compat version of xt_check_entry_offsets
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (13 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: assert minimum target size Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: check standard target size too Jiri Slaby
` (35 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit fc1221b3a163d1386d1052184202d5dc50d302d1 upstream.
32bit rulesets have different layout and alignment requirements, so once
more integrity checks get added to xt_check_entry_offsets it will reject
well-formed 32bit rulesets.
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 | 3 ++-
net/ipv4/netfilter/ip_tables.c | 3 ++-
net/ipv6/netfilter/ip6_tables.c | 3 ++-
net/netfilter/x_tables.c | 22 ++++++++++++++++++++++
5 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 20ced1191c50..958a5132e46b 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -437,6 +437,9 @@ extern void xt_compat_target_from_user(struct xt_entry_target *t,
void **dstptr, unsigned int *size);
extern int xt_compat_target_to_user(const struct xt_entry_target *t,
void __user **dstptr, unsigned int *size);
+int xt_compat_check_entry_offsets(const void *base,
+ unsigned int target_offset,
+ unsigned int next_offset);
#endif /* CONFIG_COMPAT */
#endif /* _X_TABLES_H */
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 99b28387ef6f..788ddb05dd3d 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1240,7 +1240,8 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
if (!arp_checkentry(&e->arp))
return -EINVAL;
- ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
+ ret = xt_compat_check_entry_offsets(e, e->target_offset,
+ e->next_offset);
if (ret)
return ret;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index f5fe7e66610b..65325bd2180f 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1505,7 +1505,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
if (!ip_checkentry(&e->ip))
return -EINVAL;
- ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
+ ret = xt_compat_check_entry_offsets(e,
+ e->target_offset, e->next_offset);
if (ret)
return ret;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index e9ee3feba843..c54cfa235a1d 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1517,7 +1517,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
if (!ip6_checkentry(&e->ipv6))
return -EINVAL;
- ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
+ ret = xt_compat_check_entry_offsets(e,
+ e->target_offset, e->next_offset);
if (ret)
return ret;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index cc34bb38c814..eeb4edc750cd 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -558,6 +558,27 @@ int xt_compat_match_to_user(const struct xt_entry_match *m,
return 0;
}
EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
+
+int xt_compat_check_entry_offsets(const void *base,
+ unsigned int target_offset,
+ unsigned int next_offset)
+{
+ const struct compat_xt_entry_target *t;
+ const char *e = base;
+
+ if (target_offset + sizeof(*t) > next_offset)
+ return -EINVAL;
+
+ t = (void *)(e + target_offset);
+ if (t->u.target_size < sizeof(*t))
+ return -EINVAL;
+
+ if (target_offset + t->u.target_size > next_offset)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(xt_compat_check_entry_offsets);
#endif /* CONFIG_COMPAT */
/**
@@ -568,6 +589,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
* @next_offset: the arp/ip/ip6_t->next_offset
*
* validates that target_offset and next_offset are sane.
+ * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
*
* The arp/ip/ip6t_entry structure @base must have passed following tests:
* - it must point to a valid memory location
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: check standard target size too
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (14 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: add compat version of xt_check_entry_offsets Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: check for bogus target offset Jiri Slaby
` (34 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 7ed2abddd20cf8f6bd27f65bd218f26fa5bf7f44 upstream.
We have targets and standard targets -- the latter carries a verdict.
The ip/ip6tables validation functions will access t->verdict for the
standard targets to fetch the jump offset or verdict for chainloop
detection, but this happens before the targets get checked/validated.
Thus we also need to check for verdict presence here, else t->verdict
can point right after a blob.
Spotted with UBSAN while testing malformed blobs.
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/netfilter/x_tables.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index eeb4edc750cd..37f7eda8ad19 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -559,6 +559,13 @@ int xt_compat_match_to_user(const struct xt_entry_match *m,
}
EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
+/* non-compat version may have padding after verdict */
+struct compat_xt_standard_target {
+ struct compat_xt_entry_target t;
+ compat_uint_t verdict;
+};
+
+/* see xt_check_entry_offsets */
int xt_compat_check_entry_offsets(const void *base,
unsigned int target_offset,
unsigned int next_offset)
@@ -576,6 +583,10 @@ int xt_compat_check_entry_offsets(const void *base,
if (target_offset + t->u.target_size > next_offset)
return -EINVAL;
+ if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
+ target_offset + sizeof(struct compat_xt_standard_target) != next_offset)
+ return -EINVAL;
+
return 0;
}
EXPORT_SYMBOL(xt_compat_check_entry_offsets);
@@ -615,6 +626,10 @@ int xt_check_entry_offsets(const void *base,
if (target_offset + t->u.target_size > next_offset)
return -EINVAL;
+ if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
+ target_offset + sizeof(struct xt_standard_target) != next_offset)
+ return -EINVAL;
+
return 0;
}
EXPORT_SYMBOL(xt_check_entry_offsets);
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: check for bogus target offset
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (15 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: check standard target size too Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: validate all offsets and sizes in a rule Jiri Slaby
` (33 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit ce683e5f9d045e5d67d1312a42b359cb2ab2a13c upstream.
We're currently asserting that targetoff + targetsize <= nextoff.
Extend it to also check that targetoff is >= sizeof(xt_entry).
Since this is generic code, add an argument pointing to the start of the
match/target, we can then derive the base structure size from the delta.
We also need the e->elems pointer in a followup change to validate matches.
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 | 4 ++--
net/ipv4/netfilter/arp_tables.c | 5 +++--
net/ipv4/netfilter/ip_tables.c | 5 +++--
net/ipv6/netfilter/ip6_tables.c | 5 +++--
net/netfilter/x_tables.c | 17 +++++++++++++++--
5 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 958a5132e46b..ef93201a7c0e 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -239,7 +239,7 @@ extern void xt_unregister_match(struct xt_match *target);
extern int xt_register_matches(struct xt_match *match, unsigned int n);
extern void xt_unregister_matches(struct xt_match *match, unsigned int n);
-int xt_check_entry_offsets(const void *base,
+int xt_check_entry_offsets(const void *base, const char *elems,
unsigned int target_offset,
unsigned int next_offset);
@@ -437,7 +437,7 @@ extern void xt_compat_target_from_user(struct xt_entry_target *t,
void **dstptr, unsigned int *size);
extern int xt_compat_target_to_user(const struct xt_entry_target *t,
void __user **dstptr, unsigned int *size);
-int xt_compat_check_entry_offsets(const void *base,
+int xt_compat_check_entry_offsets(const void *base, const char *elems,
unsigned int target_offset,
unsigned int next_offset);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 788ddb05dd3d..37550a103f88 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -578,7 +578,8 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
if (!arp_checkentry(&e->arp))
return -EINVAL;
- err = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
+ err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+ e->next_offset);
if (err)
return err;
@@ -1240,7 +1241,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
if (!arp_checkentry(&e->arp))
return -EINVAL;
- ret = xt_compat_check_entry_offsets(e, e->target_offset,
+ ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset,
e->next_offset);
if (ret)
return ret;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 65325bd2180f..cd8a5186a6a6 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -738,7 +738,8 @@ check_entry_size_and_hooks(struct ipt_entry *e,
if (!ip_checkentry(&e->ip))
return -EINVAL;
- err = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
+ err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+ e->next_offset);
if (err)
return err;
@@ -1505,7 +1506,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
if (!ip_checkentry(&e->ip))
return -EINVAL;
- ret = xt_compat_check_entry_offsets(e,
+ ret = xt_compat_check_entry_offsets(e, e->elems,
e->target_offset, e->next_offset);
if (ret)
return ret;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index c54cfa235a1d..60c71ad180f0 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -749,7 +749,8 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
if (!ip6_checkentry(&e->ipv6))
return -EINVAL;
- err = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
+ err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+ e->next_offset);
if (err)
return err;
@@ -1517,7 +1518,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
if (!ip6_checkentry(&e->ipv6))
return -EINVAL;
- ret = xt_compat_check_entry_offsets(e,
+ ret = xt_compat_check_entry_offsets(e, e->elems,
e->target_offset, e->next_offset);
if (ret)
return ret;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 37f7eda8ad19..ea147468df9c 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -565,14 +565,17 @@ struct compat_xt_standard_target {
compat_uint_t verdict;
};
-/* see xt_check_entry_offsets */
-int xt_compat_check_entry_offsets(const void *base,
+int xt_compat_check_entry_offsets(const void *base, const char *elems,
unsigned int target_offset,
unsigned int next_offset)
{
+ long size_of_base_struct = elems - (const char *)base;
const struct compat_xt_entry_target *t;
const char *e = base;
+ if (target_offset < size_of_base_struct)
+ return -EINVAL;
+
if (target_offset + sizeof(*t) > next_offset)
return -EINVAL;
@@ -596,12 +599,16 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets);
* xt_check_entry_offsets - validate arp/ip/ip6t_entry
*
* @base: pointer to arp/ip/ip6t_entry
+ * @elems: pointer to first xt_entry_match, i.e. ip(6)t_entry->elems
* @target_offset: the arp/ip/ip6_t->target_offset
* @next_offset: the arp/ip/ip6_t->next_offset
*
* validates that target_offset and next_offset are sane.
* Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
*
+ * This function does not validate the targets or matches themselves, it
+ * only tests that all the offsets and sizes are correct.
+ *
* The arp/ip/ip6t_entry structure @base must have passed following tests:
* - it must point to a valid memory location
* - base to base + next_offset must be accessible, i.e. not exceed allocated
@@ -610,12 +617,18 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets);
* Return: 0 on success, negative errno on failure.
*/
int xt_check_entry_offsets(const void *base,
+ const char *elems,
unsigned int target_offset,
unsigned int next_offset)
{
+ long size_of_base_struct = elems - (const char *)base;
const struct xt_entry_target *t;
const char *e = base;
+ /* target start is within the ip/ip6/arpt_entry struct */
+ if (target_offset < size_of_base_struct)
+ return -EINVAL;
+
if (target_offset + sizeof(*t) > next_offset)
return -EINVAL;
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: validate all offsets and sizes in a rule
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (16 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: check for bogus target offset Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: don't reject valid target size on some architectures Jiri Slaby
` (32 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 13631bfc604161a9d69cd68991dff8603edd66f9 upstream.
Validate that all matches (if any) add up to the beginning of
the target and that each match covers at least the base structure size.
The compat path should be able to safely re-use the function
as the structures only differ in alignment; added a
BUILD_BUG_ON just in case we have an arch that adds padding as well.
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/netfilter/x_tables.c | 81 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 76 insertions(+), 5 deletions(-)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index ea147468df9c..c4826337866b 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -435,6 +435,47 @@ int xt_check_match(struct xt_mtchk_param *par,
}
EXPORT_SYMBOL_GPL(xt_check_match);
+/** xt_check_entry_match - check that matches end before start of target
+ *
+ * @match: beginning of xt_entry_match
+ * @target: beginning of this rules target (alleged end of matches)
+ * @alignment: alignment requirement of match structures
+ *
+ * Validates that all matches add up to the beginning of the target,
+ * and that each match covers at least the base structure size.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+static int xt_check_entry_match(const char *match, const char *target,
+ const size_t alignment)
+{
+ const struct xt_entry_match *pos;
+ int length = target - match;
+
+ if (length == 0) /* no matches */
+ return 0;
+
+ pos = (struct xt_entry_match *)match;
+ do {
+ if ((unsigned long)pos % alignment)
+ return -EINVAL;
+
+ if (length < (int)sizeof(struct xt_entry_match))
+ return -EINVAL;
+
+ if (pos->u.match_size < sizeof(struct xt_entry_match))
+ return -EINVAL;
+
+ if (pos->u.match_size > length)
+ return -EINVAL;
+
+ length -= pos->u.match_size;
+ pos = ((void *)((char *)(pos) + (pos)->u.match_size));
+ } while (length > 0);
+
+ return 0;
+}
+
#ifdef CONFIG_COMPAT
int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta)
{
@@ -590,7 +631,14 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
target_offset + sizeof(struct compat_xt_standard_target) != next_offset)
return -EINVAL;
- return 0;
+ /* compat_xt_entry match has less strict aligment requirements,
+ * otherwise they are identical. In case of padding differences
+ * we need to add compat version of xt_check_entry_match.
+ */
+ BUILD_BUG_ON(sizeof(struct compat_xt_entry_match) != sizeof(struct xt_entry_match));
+
+ return xt_check_entry_match(elems, base + target_offset,
+ __alignof__(struct compat_xt_entry_match));
}
EXPORT_SYMBOL(xt_compat_check_entry_offsets);
#endif /* CONFIG_COMPAT */
@@ -603,17 +651,39 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets);
* @target_offset: the arp/ip/ip6_t->target_offset
* @next_offset: the arp/ip/ip6_t->next_offset
*
- * validates that target_offset and next_offset are sane.
- * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
+ * validates that target_offset and next_offset are sane and that all
+ * match sizes (if any) align with the target offset.
*
* This function does not validate the targets or matches themselves, it
- * only tests that all the offsets and sizes are correct.
+ * only tests that all the offsets and sizes are correct, that all
+ * match structures are aligned, and that the last structure ends where
+ * the target structure begins.
+ *
+ * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
*
* The arp/ip/ip6t_entry structure @base must have passed following tests:
* - it must point to a valid memory location
* - base to base + next_offset must be accessible, i.e. not exceed allocated
* length.
*
+ * A well-formed entry looks like this:
+ *
+ * ip(6)t_entry match [mtdata] match [mtdata] target [tgdata] ip(6)t_entry
+ * e->elems[]-----' | |
+ * matchsize | |
+ * matchsize | |
+ * | |
+ * target_offset---------------------------------' |
+ * next_offset---------------------------------------------------'
+ *
+ * elems[]: flexible array member at end of ip(6)/arpt_entry struct.
+ * This is where matches (if any) and the target reside.
+ * target_offset: beginning of target.
+ * next_offset: start of the next rule; also: size of this rule.
+ * Since targets have a minimum size, target_offset + minlen <= next_offset.
+ *
+ * Every match stores its size, sum of sizes must not exceed target_offset.
+ *
* Return: 0 on success, negative errno on failure.
*/
int xt_check_entry_offsets(const void *base,
@@ -643,7 +713,8 @@ int xt_check_entry_offsets(const void *base,
target_offset + sizeof(struct xt_standard_target) != next_offset)
return -EINVAL;
- return 0;
+ return xt_check_entry_match(elems, base + target_offset,
+ __alignof__(struct xt_entry_match));
}
EXPORT_SYMBOL(xt_check_entry_offsets);
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: don't reject valid target size on some architectures
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (17 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: validate all offsets and sizes in a rule Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: arp_tables: simplify translate_compat_table args Jiri Slaby
` (31 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 7b7eba0f3515fca3296b8881d583f7c1042f5226 upstream.
Quoting John Stultz:
In updating a 32bit arm device from 4.6 to Linus' current HEAD, I
noticed I was having some trouble with networking, and realized that
/proc/net/ip_tables_names was suddenly empty.
Digging through the registration process, it seems we're catching on the:
if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
target_offset + sizeof(struct xt_standard_target) != next_offset)
return -EINVAL;
Where next_offset seems to be 4 bytes larger then the
offset + standard_target struct size.
next_offset needs to be aligned via XT_ALIGN (so we can access all members
of ip(6)t_entry struct).
This problem didn't show up on i686 as it only needs 4-byte alignment for
u64, but iptables userspace on other 32bit arches does insert extra padding.
Reported-by: John Stultz <john.stultz@linaro.org>
Tested-by: John Stultz <john.stultz@linaro.org>
Fixes: 7ed2abddd20cf ("netfilter: x_tables: check standard target size too")
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/netfilter/x_tables.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index c4826337866b..6ac9fb4f42fc 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -628,7 +628,7 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
return -EINVAL;
if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
- target_offset + sizeof(struct compat_xt_standard_target) != next_offset)
+ COMPAT_XT_ALIGN(target_offset + sizeof(struct compat_xt_standard_target)) != next_offset)
return -EINVAL;
/* compat_xt_entry match has less strict aligment requirements,
@@ -710,7 +710,7 @@ int xt_check_entry_offsets(const void *base,
return -EINVAL;
if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
- target_offset + sizeof(struct xt_standard_target) != next_offset)
+ XT_ALIGN(target_offset + sizeof(struct xt_standard_target)) != next_offset)
return -EINVAL;
return xt_check_entry_match(elems, base + target_offset,
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: arp_tables: simplify translate_compat_table args
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (18 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: don't reject valid target size on some architectures Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: ip_tables: " Jiri Slaby
` (30 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: ip_tables: simplify translate_compat_table args
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (19 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: arp_tables: simplify translate_compat_table args Jiri Slaby
@ 2016-07-12 9:40 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: ip6_tables: " Jiri Slaby
` (29 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:40 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 7d3f843eed29222254c9feab481f55175a1afcc9 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/ip_tables.c | 61 +++++++++++++++++-------------------------
1 file changed, 25 insertions(+), 36 deletions(-)
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index cd8a5186a6a6..a7d5f29e6c1c 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1440,7 +1440,6 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
static int
compat_find_calc_match(struct xt_entry_match *m,
- const char *name,
const struct ipt_ip *ip,
unsigned int hookmask,
int *size)
@@ -1478,8 +1477,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_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_match *ematch;
struct xt_entry_target *t;
@@ -1515,8 +1513,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
entry_offset = (void *)e - (void *)base;
j = 0;
xt_ematch_foreach(ematch, e) {
- ret = compat_find_calc_match(ematch, name,
- &e->ip, e->comefrom, &off);
+ ret = compat_find_calc_match(ematch, &e->ip, e->comefrom,
+ &off);
if (ret != 0)
goto release_matches;
++j;
@@ -1565,7 +1563,7 @@ release_matches:
static int
compat_copy_entry_from_user(struct compat_ipt_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;
@@ -1641,14 +1639,9 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
static int
translate_compat_table(struct net *net,
- const char *name,
- unsigned int valid_hooks,
struct xt_table_info **pinfo,
void **pentry0,
- unsigned int total_size,
- unsigned int number,
- unsigned int *hook_entries,
- unsigned int *underflows)
+ const struct compat_ipt_replace *compatr)
{
unsigned int i, j;
struct xt_table_info *newinfo, *info;
@@ -1660,8 +1653,8 @@ translate_compat_table(struct net *net,
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_INET_NUMHOOKS; i++) {
@@ -1672,40 +1665,39 @@ translate_compat_table(struct net *net,
duprintf("translate_compat_table: size %u\n", info->size);
j = 0;
xt_compat_lock(AF_INET);
- xt_compat_init_offsets(AF_INET, number);
+ xt_compat_init_offsets(AF_INET, 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_INET_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;
}
}
@@ -1715,17 +1707,17 @@ translate_compat_table(struct net *net,
if (!newinfo)
goto out_unlock;
- newinfo->number = number;
+ 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];
}
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;
}
@@ -1735,12 +1727,12 @@ translate_compat_table(struct net *net,
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 = compat_check_entry(iter1, net, name);
+ ret = compat_check_entry(iter1, net, compatr->name);
if (ret != 0)
break;
++i;
@@ -1785,7 +1777,7 @@ translate_compat_table(struct net *net,
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);
@@ -1828,10 +1820,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
goto free_newinfo;
}
- ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
- &newinfo, &loc_cpu_entry, tmp.size,
- tmp.num_entries, tmp.hook_entry,
- tmp.underflow);
+ ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
if (ret != 0)
goto free_newinfo;
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: ip6_tables: simplify translate_compat_table args
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (20 preceding siblings ...)
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: ip_tables: " Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: xt_compat_match_from_user doesn't need a retval Jiri Slaby
` (28 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 329a0807124f12fe1c8032f95d8a8eb47047fb0e 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/ipv6/netfilter/ip6_tables.c | 61 +++++++++++++++++------------------------
1 file changed, 25 insertions(+), 36 deletions(-)
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 60c71ad180f0..a8e605de16dd 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1452,7 +1452,6 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
static int
compat_find_calc_match(struct xt_entry_match *m,
- const char *name,
const struct ip6t_ip6 *ipv6,
unsigned int hookmask,
int *size)
@@ -1490,8 +1489,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_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_match *ematch;
struct xt_entry_target *t;
@@ -1527,8 +1525,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
entry_offset = (void *)e - (void *)base;
j = 0;
xt_ematch_foreach(ematch, e) {
- ret = compat_find_calc_match(ematch, name,
- &e->ipv6, e->comefrom, &off);
+ ret = compat_find_calc_match(ematch, &e->ipv6, e->comefrom,
+ &off);
if (ret != 0)
goto release_matches;
++j;
@@ -1577,7 +1575,7 @@ release_matches:
static int
compat_copy_entry_from_user(struct compat_ip6t_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;
@@ -1651,14 +1649,9 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
static int
translate_compat_table(struct net *net,
- const char *name,
- unsigned int valid_hooks,
struct xt_table_info **pinfo,
void **pentry0,
- unsigned int total_size,
- unsigned int number,
- unsigned int *hook_entries,
- unsigned int *underflows)
+ const struct compat_ip6t_replace *compatr)
{
unsigned int i, j;
struct xt_table_info *newinfo, *info;
@@ -1670,8 +1663,8 @@ translate_compat_table(struct net *net,
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_INET_NUMHOOKS; i++) {
@@ -1682,40 +1675,39 @@ translate_compat_table(struct net *net,
duprintf("translate_compat_table: size %u\n", info->size);
j = 0;
xt_compat_lock(AF_INET6);
- xt_compat_init_offsets(AF_INET6, number);
+ xt_compat_init_offsets(AF_INET6, 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_INET_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;
}
}
@@ -1725,17 +1717,17 @@ translate_compat_table(struct net *net,
if (!newinfo)
goto out_unlock;
- newinfo->number = number;
+ 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];
}
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;
}
@@ -1745,12 +1737,12 @@ translate_compat_table(struct net *net,
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 = compat_check_entry(iter1, net, name);
+ ret = compat_check_entry(iter1, net, compatr->name);
if (ret != 0)
break;
++i;
@@ -1795,7 +1787,7 @@ translate_compat_table(struct net *net,
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);
@@ -1838,10 +1830,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
goto free_newinfo;
}
- ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
- &newinfo, &loc_cpu_entry, tmp.size,
- tmp.num_entries, tmp.hook_entry,
- tmp.underflow);
+ ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
if (ret != 0)
goto free_newinfo;
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: xt_compat_match_from_user doesn't need a retval
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (21 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: ip6_tables: " Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: ensure number of counters is >0 in do_replace() Jiri Slaby
` (27 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 0188346f21e6546498c2a0f84888797ad4063fc5 upstream.
Always returned 0.
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 | 2 +-
net/ipv4/netfilter/arp_tables.c | 17 +++++------------
net/ipv4/netfilter/ip_tables.c | 26 +++++++++-----------------
net/ipv6/netfilter/ip6_tables.c | 27 +++++++++------------------
net/netfilter/x_tables.c | 5 ++---
5 files changed, 26 insertions(+), 51 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index ef93201a7c0e..fb4ea1578552 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -427,7 +427,7 @@ extern void xt_compat_init_offsets(u_int8_t af, unsigned int number);
extern int xt_compat_calc_jump(u_int8_t af, unsigned int offset);
extern int xt_compat_match_offset(const struct xt_match *match);
-extern int xt_compat_match_from_user(struct xt_entry_match *m,
+extern void xt_compat_match_from_user(struct xt_entry_match *m,
void **dstptr, unsigned int *size);
extern int xt_compat_match_to_user(const struct xt_entry_match *m,
void __user **dstptr, unsigned int *size);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index cf6aa304a4f5..819a5d2b618f 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1296,7 +1296,7 @@ out:
return ret;
}
-static int
+static void
compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
unsigned int *size,
struct xt_table_info *newinfo, unsigned char *base)
@@ -1305,9 +1305,8 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
struct xt_target *target;
struct arpt_entry *de;
unsigned int origsize;
- int ret, h;
+ int h;
- ret = 0;
origsize = *size;
de = (struct arpt_entry *)*dstptr;
memcpy(de, e, sizeof(struct arpt_entry));
@@ -1328,7 +1327,6 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
if ((unsigned char *)de - base < newinfo->underflow[h])
newinfo->underflow[h] -= origsize - *size;
}
- return ret;
}
static int translate_compat_table(struct xt_table_info **pinfo,
@@ -1407,16 +1405,11 @@ static int translate_compat_table(struct xt_table_info **pinfo,
entry1 = newinfo->entries[raw_smp_processor_id()];
pos = entry1;
size = compatr->size;
- xt_entry_foreach(iter0, entry0, compatr->size) {
- ret = compat_copy_entry_from_user(iter0, &pos, &size,
- newinfo, entry1);
- if (ret != 0)
- break;
- }
+ xt_entry_foreach(iter0, entry0, compatr->size)
+ compat_copy_entry_from_user(iter0, &pos, &size,
+ newinfo, entry1);
xt_compat_flush_offsets(NFPROTO_ARP);
xt_compat_unlock(NFPROTO_ARP);
- if (ret)
- goto free_newinfo;
ret = -ELOOP;
if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index a7d5f29e6c1c..b296da45a7bd 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1561,7 +1561,7 @@ release_matches:
return ret;
}
-static int
+static void
compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
unsigned int *size,
struct xt_table_info *newinfo, unsigned char *base)
@@ -1570,10 +1570,9 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
struct xt_target *target;
struct ipt_entry *de;
unsigned int origsize;
- int ret, h;
+ int h;
struct xt_entry_match *ematch;
- ret = 0;
origsize = *size;
de = (struct ipt_entry *)*dstptr;
memcpy(de, e, sizeof(struct ipt_entry));
@@ -1582,11 +1581,9 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
*dstptr += sizeof(struct ipt_entry);
*size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
- xt_ematch_foreach(ematch, e) {
- ret = xt_compat_match_from_user(ematch, dstptr, size);
- if (ret != 0)
- return ret;
- }
+ xt_ematch_foreach(ematch, e)
+ xt_compat_match_from_user(ematch, dstptr, size);
+
de->target_offset = e->target_offset - (origsize - *size);
t = compat_ipt_get_target(e);
target = t->u.kernel.target;
@@ -1599,7 +1596,6 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
if ((unsigned char *)de - base < newinfo->underflow[h])
newinfo->underflow[h] -= origsize - *size;
}
- return ret;
}
static int
@@ -1715,16 +1711,12 @@ translate_compat_table(struct net *net,
entry1 = newinfo->entries[raw_smp_processor_id()];
pos = entry1;
size = compatr->size;
- xt_entry_foreach(iter0, entry0, compatr->size) {
- ret = compat_copy_entry_from_user(iter0, &pos, &size,
- newinfo, entry1);
- if (ret != 0)
- break;
- }
+ xt_entry_foreach(iter0, entry0, compatr->size)
+ compat_copy_entry_from_user(iter0, &pos, &size,
+ newinfo, entry1);
+
xt_compat_flush_offsets(AF_INET);
xt_compat_unlock(AF_INET);
- if (ret)
- goto free_newinfo;
ret = -ELOOP;
if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index a8e605de16dd..2b345f642978 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1573,7 +1573,7 @@ release_matches:
return ret;
}
-static int
+static void
compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
unsigned int *size,
struct xt_table_info *newinfo, unsigned char *base)
@@ -1581,10 +1581,9 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
struct xt_entry_target *t;
struct ip6t_entry *de;
unsigned int origsize;
- int ret, h;
+ int h;
struct xt_entry_match *ematch;
- ret = 0;
origsize = *size;
de = (struct ip6t_entry *)*dstptr;
memcpy(de, e, sizeof(struct ip6t_entry));
@@ -1593,11 +1592,9 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
*dstptr += sizeof(struct ip6t_entry);
*size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
- xt_ematch_foreach(ematch, e) {
- ret = xt_compat_match_from_user(ematch, dstptr, size);
- if (ret != 0)
- return ret;
- }
+ xt_ematch_foreach(ematch, e)
+ xt_compat_match_from_user(ematch, dstptr, size);
+
de->target_offset = e->target_offset - (origsize - *size);
t = compat_ip6t_get_target(e);
xt_compat_target_from_user(t, dstptr, size);
@@ -1609,7 +1606,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
if ((unsigned char *)de - base < newinfo->underflow[h])
newinfo->underflow[h] -= origsize - *size;
}
- return ret;
}
static int compat_check_entry(struct ip6t_entry *e, struct net *net,
@@ -1724,17 +1720,12 @@ translate_compat_table(struct net *net,
}
entry1 = newinfo->entries[raw_smp_processor_id()];
pos = entry1;
- size = compatr->size;
- xt_entry_foreach(iter0, entry0, compatr->size) {
- ret = compat_copy_entry_from_user(iter0, &pos, &size,
- newinfo, entry1);
- if (ret != 0)
- break;
- }
+ xt_entry_foreach(iter0, entry0, compatr->size)
+ compat_copy_entry_from_user(iter0, &pos, &size,
+ newinfo, entry1);
+
xt_compat_flush_offsets(AF_INET6);
xt_compat_unlock(AF_INET6);
- if (ret)
- goto free_newinfo;
ret = -ELOOP;
if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 6ac9fb4f42fc..9cf3039deac2 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -545,8 +545,8 @@ int xt_compat_match_offset(const struct xt_match *match)
}
EXPORT_SYMBOL_GPL(xt_compat_match_offset);
-int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
- unsigned int *size)
+void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+ unsigned int *size)
{
const struct xt_match *match = m->u.kernel.match;
struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
@@ -568,7 +568,6 @@ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
*size += off;
*dstptr += msize;
- return 0;
}
EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: ensure number of counters is >0 in do_replace()
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (22 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: xt_compat_match_from_user doesn't need a retval Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: do compat validation via translate_table Jiri Slaby
` (26 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Dave Jones, Pablo Neira Ayuso, Jiri Slaby
From: Dave Jones <davej@codemonkey.org.uk>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: do compat validation via translate_table
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (23 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: ensure number of counters is >0 in do_replace() Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] Revert "netfilter: ensure number of counters is >0 in do_replace()" Jiri Slaby
` (25 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] Revert "netfilter: ensure number of counters is >0 in do_replace()"
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (24 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: do compat validation via translate_table Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: introduce and use xt_copy_counters_from_user Jiri Slaby
` (24 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Bernhard Thaler, Pablo Neira Ayuso, Jiri Slaby
From: Bernhard Thaler <bernhard.thaler@wvnet.at>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] netfilter: x_tables: introduce and use xt_copy_counters_from_user
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (25 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] Revert "netfilter: ensure number of counters is >0 in do_replace()" Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] crypto: ux500 - memmove the right size Jiri Slaby
` (23 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Florian Westphal, Pablo Neira Ayuso, Jiri Slaby
From: Florian Westphal <fw@strlen.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] crypto: ux500 - memmove the right size
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (26 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: introduce and use xt_copy_counters_from_user Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] sit: correct IP protocol used in ipip6_err Jiri Slaby
` (22 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Linus Walleij, Joakim Bech, Herbert Xu, Jiri Slaby
From: Linus Walleij <linus.walleij@linaro.org>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] sit: correct IP protocol used in ipip6_err
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (27 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] crypto: ux500 - memmove the right size Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] ipmr/ip6mr: Initialize the last assert time of mfc entries Jiri Slaby
` (21 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Simon Horman, David S . Miller, Jiri Slaby
From: Simon Horman <simon.horman@netronome.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] ipmr/ip6mr: Initialize the last assert time of mfc entries.
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (28 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] sit: correct IP protocol used in ipip6_err Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] net: alx: Work around the DMA RX overflow issue Jiri Slaby
` (20 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Tom Goff, David S . Miller, Jiri Slaby
From: Tom Goff <thomas.goff@ll.mit.edu>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] net: alx: Work around the DMA RX overflow issue
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (29 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] ipmr/ip6mr: Initialize the last assert time of mfc entries Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: quirks: Add no-lpm quirk for Acer C120 LED Projector Jiri Slaby
` (19 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Feng Tang, Jiri Slaby
From: Feng Tang <feng.tang@intel.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] usb: quirks: Add no-lpm quirk for Acer C120 LED Projector
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (30 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] net: alx: Work around the DMA RX overflow issue Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: musb: Stop bulk endpoint while queue is rotated Jiri Slaby
` (18 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Hans de Goede, Jiri Slaby
From: Hans de Goede <hdegoede@redhat.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] usb: musb: Stop bulk endpoint while queue is rotated
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (31 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: quirks: Add no-lpm quirk for Acer C120 LED Projector Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: musb: Ensure rx reinit occurs for shared_fifo endpoints Jiri Slaby
` (17 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Andrew Goodbody, Bin Liu, Jiri Slaby
From: Andrew Goodbody <andrew.goodbody@cambrionix.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 7b2c17f829545df27a910e8d82e133c21c9a8c9c upstream.
Ensure that the endpoint is stopped by clearing REQPKT before
clearing DATAERR_NAKTIMEOUT before rotating the queue on the
dedicated bulk endpoint.
This addresses an issue where a race could result in the endpoint
receiving data before it was reprogrammed resulting in a warning
about such data from musb_rx_reinit before it was thrown away.
The data thrown away was a valid packet that had been correctly
ACKed which meant the host and device got out of sync.
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 | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index d73cda3591aa..7a149719d495 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -951,9 +951,15 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep,
if (is_in) {
dma = is_dma_capable() ? ep->rx_channel : NULL;
- /* clear nak timeout bit */
+ /*
+ * Need to stop the transaction by clearing REQPKT first
+ * then the NAK Timeout bit ref MUSBMHDRC USB 2.0 HIGH-SPEED
+ * DUAL-ROLE CONTROLLER Programmer's Guide, section 9.2.2
+ */
rx_csr = musb_readw(epio, MUSB_RXCSR);
rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+ rx_csr &= ~MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR, rx_csr);
rx_csr &= ~MUSB_RXCSR_DATAERROR;
musb_writew(epio, MUSB_RXCSR, rx_csr);
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] usb: musb: Ensure rx reinit occurs for shared_fifo endpoints
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (32 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: musb: Stop bulk endpoint while queue is rotated Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] mac80211: mesh: flush mesh paths unconditionally Jiri Slaby
` (16 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Andrew Goodbody, Bin Liu, Jiri Slaby
From: Andrew Goodbody <andrew.goodbody@cambrionix.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] mac80211: mesh: flush mesh paths unconditionally
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (33 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: musb: Ensure rx reinit occurs for shared_fifo endpoints Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] mac80211_hwsim: Add missing check for HWSIM_ATTR_SIGNAL Jiri Slaby
` (15 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Bob Copeland, Johannes Berg, Jiri Slaby
From: Bob Copeland <me@bobcopeland.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit fe7a7c57629e8dcbc0e297363a9b2366d67a6dc5 upstream.
Currently, the mesh paths associated with a nexthop station are cleaned
up in the following code path:
__sta_info_destroy_part1
synchronize_net()
__sta_info_destroy_part2
-> cleanup_single_sta
-> mesh_sta_cleanup
-> mesh_plink_deactivate
-> mesh_path_flush_by_nexthop
However, there are a couple of problems here:
1) the paths aren't flushed at all if the MPM is running in userspace
(e.g. when using wpa_supplicant or authsae)
2) there is no synchronize_rcu between removing the path and readers
accessing the nexthop, which means the following race is possible:
CPU0 CPU1
~~~~ ~~~~
sta_info_destroy_part1()
synchronize_net()
rcu_read_lock()
mesh_nexthop_resolve()
mpath = mesh_path_lookup()
[...] -> mesh_path_flush_by_nexthop()
sta = rcu_dereference(
mpath->next_hop)
kfree(sta)
access sta <-- CRASH
Fix both of these by unconditionally flushing paths before destroying
the sta, and by adding a synchronize_net() after path flush to ensure
no active readers can still dereference the sta.
Fixes this crash:
[ 348.529295] BUG: unable to handle kernel paging request at 00020040
[ 348.530014] IP: [<f929245d>] ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211]
[ 348.530014] *pde = 00000000
[ 348.530014] Oops: 0000 [#1] PREEMPT
[ 348.530014] Modules linked in: drbg ansi_cprng ctr ccm ppp_generic slhc ipt_MASQUERADE nf_nat_masquerade_ipv4 8021q ]
[ 348.530014] CPU: 0 PID: 20597 Comm: wget Tainted: G O 4.6.0-rc5-wt=V1 #1
[ 348.530014] Hardware name: To Be Filled By O.E.M./To be filled by O.E.M., BIOS 080016 11/07/2014
[ 348.530014] task: f64fa280 ti: f4f9c000 task.ti: f4f9c000
[ 348.530014] EIP: 0060:[<f929245d>] EFLAGS: 00010246 CPU: 0
[ 348.530014] EIP is at ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211]
[ 348.530014] EAX: f4ce63e0 EBX: 00000088 ECX: f3788416 EDX: 00020008
[ 348.530014] ESI: 00000000 EDI: 00000088 EBP: f6409a4c ESP: f6409a40
[ 348.530014] DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
[ 348.530014] CR0: 80050033 CR2: 00020040 CR3: 33190000 CR4: 00000690
[ 348.530014] Stack:
[ 348.530014] 00000000 f4ce63e0 f5f9bd80 f6409a64 f9291d80 0000ce67 f5d51e00 f4ce63e0
[ 348.530014] f3788416 f6409a80 f9291dc1 f4ce8320 f4ce63e0 f5d51e00 f4ce63e0 f4ce8320
[ 348.530014] f6409a98 f9277f6f 00000000 00000000 0000007c 00000000 f6409b2c f9278dd1
[ 348.530014] Call Trace:
[ 348.530014] [<f9291d80>] mesh_nexthop_lookup+0xbb/0xc8 [mac80211]
[ 348.530014] [<f9291dc1>] mesh_nexthop_resolve+0x34/0xd8 [mac80211]
[ 348.530014] [<f9277f6f>] ieee80211_xmit+0x92/0xc1 [mac80211]
[ 348.530014] [<f9278dd1>] __ieee80211_subif_start_xmit+0x807/0x83c [mac80211]
[ 348.530014] [<c04df012>] ? sch_direct_xmit+0xd7/0x1b3
[ 348.530014] [<c022a8c6>] ? __local_bh_enable_ip+0x5d/0x7b
[ 348.530014] [<f956870c>] ? nf_nat_ipv4_out+0x4c/0xd0 [nf_nat_ipv4]
[ 348.530014] [<f957e036>] ? iptable_nat_ipv4_fn+0xf/0xf [iptable_nat]
[ 348.530014] [<c04c6f45>] ? netif_skb_features+0x14d/0x30a
[ 348.530014] [<f9278e10>] ieee80211_subif_start_xmit+0xa/0xe [mac80211]
[ 348.530014] [<c04c769c>] dev_hard_start_xmit+0x1f8/0x267
[ 348.530014] [<c04c7261>] ? validate_xmit_skb.isra.120.part.121+0x10/0x253
[ 348.530014] [<c04defc6>] sch_direct_xmit+0x8b/0x1b3
[ 348.530014] [<c04c7a9c>] __dev_queue_xmit+0x2c8/0x513
[ 348.530014] [<c04c7cfb>] dev_queue_xmit+0xa/0xc
[ 348.530014] [<f91bfc7a>] batadv_send_skb_packet+0xd6/0xec [batman_adv]
[ 348.530014] [<f91bfdc4>] batadv_send_unicast_skb+0x15/0x4a [batman_adv]
[ 348.530014] [<f91b5938>] batadv_dat_send_data+0x27e/0x310 [batman_adv]
[ 348.530014] [<f91c30b5>] ? batadv_tt_global_hash_find.isra.11+0x8/0xa [batman_adv]
[ 348.530014] [<f91b63f3>] batadv_dat_snoop_outgoing_arp_request+0x208/0x23d [batman_adv]
[ 348.530014] [<f91c0cd9>] batadv_interface_tx+0x206/0x385 [batman_adv]
[ 348.530014] [<c04c769c>] dev_hard_start_xmit+0x1f8/0x267
[ 348.530014] [<c04c7261>] ? validate_xmit_skb.isra.120.part.121+0x10/0x253
[ 348.530014] [<c04defc6>] sch_direct_xmit+0x8b/0x1b3
[ 348.530014] [<c04c7a9c>] __dev_queue_xmit+0x2c8/0x513
[ 348.530014] [<f80cbd2a>] ? igb_xmit_frame+0x57/0x72 [igb]
[ 348.530014] [<c04c7cfb>] dev_queue_xmit+0xa/0xc
[ 348.530014] [<f843a326>] br_dev_queue_push_xmit+0xeb/0xfb [bridge]
[ 348.530014] [<f843a35f>] br_forward_finish+0x29/0x74 [bridge]
[ 348.530014] [<f843a23b>] ? deliver_clone+0x3b/0x3b [bridge]
[ 348.530014] [<f843a714>] __br_forward+0x89/0xe7 [bridge]
[ 348.530014] [<f843a336>] ? br_dev_queue_push_xmit+0xfb/0xfb [bridge]
[ 348.530014] [<f843a234>] deliver_clone+0x34/0x3b [bridge]
[ 348.530014] [<f843a68b>] ? br_flood+0x95/0x95 [bridge]
[ 348.530014] [<f843a66d>] br_flood+0x77/0x95 [bridge]
[ 348.530014] [<f843a809>] br_flood_forward+0x13/0x1a [bridge]
[ 348.530014] [<f843a68b>] ? br_flood+0x95/0x95 [bridge]
[ 348.530014] [<f843b877>] br_handle_frame_finish+0x392/0x3db [bridge]
[ 348.530014] [<c04e9b2b>] ? nf_iterate+0x2b/0x6b
[ 348.530014] [<f843baa6>] br_handle_frame+0x1e6/0x240 [bridge]
[ 348.530014] [<f843b4e5>] ? br_handle_local_finish+0x6a/0x6a [bridge]
[ 348.530014] [<c04c4ba0>] __netif_receive_skb_core+0x43a/0x66b
[ 348.530014] [<f843b8c0>] ? br_handle_frame_finish+0x3db/0x3db [bridge]
[ 348.530014] [<c023cea4>] ? resched_curr+0x19/0x37
[ 348.530014] [<c0240707>] ? check_preempt_wakeup+0xbf/0xfe
[ 348.530014] [<c0255dec>] ? ktime_get_with_offset+0x5c/0xfc
[ 348.530014] [<c04c4fc1>] __netif_receive_skb+0x47/0x55
[ 348.530014] [<c04c57ba>] netif_receive_skb_internal+0x40/0x5a
[ 348.530014] [<c04c61ef>] napi_gro_receive+0x3a/0x94
[ 348.530014] [<f80ce8d5>] igb_poll+0x6fd/0x9ad [igb]
[ 348.530014] [<c0242bd8>] ? swake_up_locked+0x14/0x26
[ 348.530014] [<c04c5d29>] net_rx_action+0xde/0x250
[ 348.530014] [<c022a743>] __do_softirq+0x8a/0x163
[ 348.530014] [<c022a6b9>] ? __hrtimer_tasklet_trampoline+0x19/0x19
[ 348.530014] [<c021100f>] do_softirq_own_stack+0x26/0x2c
[ 348.530014] <IRQ>
[ 348.530014] [<c022a957>] irq_exit+0x31/0x6f
[ 348.530014] [<c0210eb2>] do_IRQ+0x8d/0xa0
[ 348.530014] [<c058152c>] common_interrupt+0x2c/0x40
[ 348.530014] Code: e7 8c 00 66 81 ff 88 00 75 12 85 d2 75 0e b2 c3 b8 83 e9 29 f9 e8 a7 5f f9 c6 eb 74 66 81 e3 8c 005
[ 348.530014] EIP: [<f929245d>] ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211] SS:ESP 0068:f6409a40
[ 348.530014] CR2: 0000000000020040
[ 348.530014] ---[ end trace 48556ac26779732e ]---
[ 348.530014] Kernel panic - not syncing: Fatal exception in interrupt
[ 348.530014] Kernel Offset: disabled
Reported-by: Fred Veldini <fred.veldini@gmail.com>
Tested-by: Fred Veldini <fred.veldini@gmail.com>
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
net/mac80211/mesh.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 707ac61d63e5..67559f7a7832 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -160,6 +160,10 @@ void mesh_sta_cleanup(struct sta_info *sta)
del_timer_sync(&sta->plink_timer);
}
+ /* make sure no readers can access nexthop sta from here on */
+ mesh_path_flush_by_nexthop(sta);
+ synchronize_net();
+
if (changed)
ieee80211_mbss_info_change_notify(sdata, changed);
}
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] mac80211_hwsim: Add missing check for HWSIM_ATTR_SIGNAL
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (34 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] mac80211: mesh: flush mesh paths unconditionally Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] IB/mlx4: Properly initialize GRH TClass and FlowLabel in AHs Jiri Slaby
` (14 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Martin Willi, Johannes Berg, Jiri Slaby
From: Martin Willi <martin@strongswan.org>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 62397da50bb20a6b812c949ef465d7e69fe54bb6 upstream.
A wmediumd that does not send this attribute causes a NULL pointer
dereference, as the attribute is accessed even if it does not exist.
The attribute was required but never checked ever since userspace frame
forwarding has been introduced. The issue gets more problematic once we
allow wmediumd registration from user namespaces.
Fixes: 7882513bacb1 ("mac80211_hwsim driver support userspace frame tx/rx")
Signed-off-by: Martin Willi <martin@strongswan.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
drivers/net/wireless/mac80211_hwsim.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 38b8b7139ba3..38fa31d56ef9 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1932,6 +1932,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
!info->attrs[HWSIM_ATTR_FLAGS] ||
!info->attrs[HWSIM_ATTR_COOKIE] ||
+ !info->attrs[HWSIM_ATTR_SIGNAL] ||
!info->attrs[HWSIM_ATTR_TX_INFO])
goto out;
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] IB/mlx4: Properly initialize GRH TClass and FlowLabel in AHs
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (35 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] mac80211_hwsim: Add missing check for HWSIM_ATTR_SIGNAL Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism Jiri Slaby
` (13 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Jason Gunthorpe, Doug Ledford, Jiri Slaby
From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 8c5122e45a10a9262f872b53f151a592e870f905 upstream.
When this code was reworked for IBoE support the order of assignments
for the sl_tclass_flowlabel got flipped around resulting in
TClass & FlowLabel being permanently set to 0 in the packet headers.
This breaks IB routers that rely on these headers, but only affects
kernel users - libmlx4 does this properly for user space.
Fixes: fa417f7b520e ("IB/mlx4: Add support for IBoE")
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
drivers/infiniband/hw/mlx4/ah.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
index 890c23b3d714..f55d69500a5f 100644
--- a/drivers/infiniband/hw/mlx4/ah.c
+++ b/drivers/infiniband/hw/mlx4/ah.c
@@ -65,6 +65,7 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
ah->av.ib.g_slid = ah_attr->src_path_bits;
+ ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
if (ah_attr->ah_flags & IB_AH_GRH) {
ah->av.ib.g_slid |= 0x80;
ah->av.ib.gid_index = ah_attr->grh.sgid_index;
@@ -82,7 +83,6 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
!(1 << ah->av.ib.stat_rate & dev->caps.stat_rate_support))
--ah->av.ib.stat_rate;
}
- ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
return &ah->ibah;
}
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (36 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] IB/mlx4: Properly initialize GRH TClass and FlowLabel in AHs Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 12:35 ` Guilherme G. Piccoli
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/pseries: Fix PCI config address for DDW Jiri Slaby
` (12 subsequent siblings)
50 siblings, 1 reply; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Guilherme G. Piccoli, Michael Ellerman, Jiri Slaby
From: "Guilherme G. Piccoli" <gpiccoli@linux.vnet.ibm.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] powerpc/pseries: Fix PCI config address for DDW
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (37 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/tm: Always reclaim in start_thread() for exec() class syscalls Jiri Slaby
` (11 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Gavin Shan, Michael Ellerman, Jiri Slaby
From: Gavin Shan <gwshan@linux.vnet.ibm.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 8a934efe94347eee843aeea65bdec8077a79e259 upstream.
In commit 8445a87f7092 "powerpc/iommu: Remove the dependency on EEH
struct in DDW mechanism", the PE address was replaced with the PCI
config address in order to remove dependency on EEH. According to PAPR
spec, firmware (pHyp or QEMU) should accept "xxBBSSxx" format PCI config
address, not "xxxxBBSS" provided by the patch. Note that "BB" is PCI bus
number and "SS" is the combination of slot and function number.
This fixes the PCI address passed to DDW RTAS calls.
Fixes: 8445a87f7092 ("powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism")
Reported-by: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Tested-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 | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 88cbecbdbd6f..c06f9e75f8b1 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -876,7 +876,7 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
dn = pci_device_to_OF_node(dev);
pdn = PCI_DN(dn);
buid = pdn->phb->buid;
- cfg_addr = (pdn->busno << 8) | pdn->devfn;
+ cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
cfg_addr, BUID_HI(buid), BUID_LO(buid));
@@ -905,7 +905,7 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
dn = pci_device_to_OF_node(dev);
pdn = PCI_DN(dn);
buid = pdn->phb->buid;
- cfg_addr = (pdn->busno << 8) | pdn->devfn;
+ cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
do {
/* extra outputs are LIOBN and dma-addr (hi, lo) */
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] powerpc/tm: Always reclaim in start_thread() for exec() class syscalls
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (38 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/pseries: Fix PCI config address for DDW Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] USB: EHCI: declare hostpc register as zero-length array Jiri Slaby
` (10 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Cyril Bur, Michael Ellerman, Jiri Slaby
From: Cyril Bur <cyrilbur@gmail.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 8e96a87c5431c256feb65bcfc5aec92d9f7839b6 upstream.
Userspace can quite legitimately perform an exec() syscall with a
suspended transaction. exec() does not return to the old process, rather
it load a new one and starts that, the expectation therefore is that the
new process starts not in a transaction. Currently exec() is not treated
any differently to any other syscall which creates problems.
Firstly it could allow a new process to start with a suspended
transaction for a binary that no longer exists. This means that the
checkpointed state won't be valid and if the suspended transaction were
ever to be resumed and subsequently aborted (a possibility which is
exceedingly likely as exec()ing will likely doom the transaction) the
new process will jump to invalid state.
Secondly the incorrect attempt to keep the transactional state while
still zeroing state for the new process creates at least two TM Bad
Things. The first triggers on the rfid to return to userspace as
start_thread() has given the new process a 'clean' MSR but the suspend
will still be set in the hardware MSR. The second TM Bad Thing triggers
in __switch_to() as the processor is still transactionally suspended but
__switch_to() wants to zero the TM sprs for the new process.
This is an example of the outcome of calling exec() with a suspended
transaction. Note the first 700 is likely the first TM bad thing
decsribed earlier only the kernel can't report it as we've loaded
userspace registers. c000000000009980 is the rfid in
fast_exception_return()
Bad kernel stack pointer 3fffcfa1a370 at c000000000009980
Oops: Bad kernel stack pointer, sig: 6 [#1]
CPU: 0 PID: 2006 Comm: tm-execed Not tainted
NIP: c000000000009980 LR: 0000000000000000 CTR: 0000000000000000
REGS: c00000003ffefd40 TRAP: 0700 Not tainted
MSR: 8000000300201031 <SF,ME,IR,DR,LE,TM[SE]> CR: 00000000 XER: 00000000
CFAR: c0000000000098b4 SOFTE: 0
PACATMSCRATCH: b00000010000d033
GPR00: 0000000000000000 00003fffcfa1a370 0000000000000000 0000000000000000
GPR04: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
GPR08: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
GPR12: 00003fff966611c0 0000000000000000 0000000000000000 0000000000000000
NIP [c000000000009980] fast_exception_return+0xb0/0xb8
LR [0000000000000000] (null)
Call Trace:
Instruction dump:
f84d0278 e9a100d8 7c7b03a6 e84101a0 7c4ff120 e8410170 7c5a03a6 e8010070
e8410080 e8610088 e8810090 e8210078 <4c000024> 48000000 e8610178 88ed023b
Kernel BUG at c000000000043e80 [verbose debug info unavailable]
Unexpected TM Bad Thing exception at c000000000043e80 (msr 0x201033)
Oops: Unrecoverable exception, sig: 6 [#2]
CPU: 0 PID: 2006 Comm: tm-execed Tainted: G D
task: c0000000fbea6d80 ti: c00000003ffec000 task.ti: c0000000fb7ec000
NIP: c000000000043e80 LR: c000000000015a24 CTR: 0000000000000000
REGS: c00000003ffef7e0 TRAP: 0700 Tainted: G D
MSR: 8000000300201033 <SF,ME,IR,DR,RI,LE,TM[SE]> CR: 28002828 XER: 00000000
CFAR: c000000000015a20 SOFTE: 0
PACATMSCRATCH: b00000010000d033
GPR00: 0000000000000000 c00000003ffefa60 c000000000db5500 c0000000fbead000
GPR04: 8000000300001033 2222222222222222 2222222222222222 00000000ff160000
GPR08: 0000000000000000 800000010000d033 c0000000fb7e3ea0 c00000000fe00004
GPR12: 0000000000002200 c00000000fe00000 0000000000000000 0000000000000000
GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
GPR20: 0000000000000000 0000000000000000 c0000000fbea7410 00000000ff160000
GPR24: c0000000ffe1f600 c0000000fbea8700 c0000000fbea8700 c0000000fbead000
GPR28: c000000000e20198 c0000000fbea6d80 c0000000fbeab680 c0000000fbea6d80
NIP [c000000000043e80] tm_restore_sprs+0xc/0x1c
LR [c000000000015a24] __switch_to+0x1f4/0x420
Call Trace:
Instruction dump:
7c800164 4e800020 7c0022a6 f80304a8 7c0222a6 f80304b0 7c0122a6 f80304b8
4e800020 e80304a8 7c0023a6 e80304b0 <7c0223a6> e80304b8 7c0123a6 4e800020
This fixes CVE-2016-5828.
Fixes: bc2a9408fa65 ("powerpc: Hook in new transactional memory code")
Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
arch/powerpc/kernel/process.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index f1106103634b..f0856450ffe0 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1094,6 +1094,16 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
current->thread.regs = regs - 1;
}
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ /*
+ * Clear any transactional state, we're exec()ing. The cause is
+ * not important as there will never be a recheckpoint so it's not
+ * user visible.
+ */
+ if (MSR_TM_SUSPENDED(mfmsr()))
+ tm_reclaim_current(0);
+#endif
+
memset(regs->gpr, 0, sizeof(regs->gpr));
regs->ctr = 0;
regs->link = 0;
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] USB: EHCI: declare hostpc register as zero-length array
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (39 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/tm: Always reclaim in start_thread() for exec() class syscalls Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] x86, build: copy ldlinux.c32 to image.iso Jiri Slaby
` (9 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Alan Stern, Jiri Slaby
From: Alan Stern <stern@rowland.harvard.edu>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 7e8b3dfef16375dbfeb1f36a83eb9f27117c51fd upstream.
The HOSTPC extension registers found in some EHCI implementations form
a variable-length array, with one element for each port. Therefore
the hostpc field in struct ehci_regs should be declared as a
zero-length array, not a single-element array.
This fixes a problem reported by UBSAN.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-by: Wilfried Klaebe <linux-kernel@lebenslange-mailadresse.de>
Tested-by: Wilfried Klaebe <linux-kernel@lebenslange-mailadresse.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
include/linux/usb/ehci_def.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
index daec99af5d54..1c88b177cb9c 100644
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -178,11 +178,11 @@ struct ehci_regs {
* PORTSCx
*/
/* HOSTPC: offset 0x84 */
- u32 hostpc[1]; /* HOSTPC extension */
+ u32 hostpc[0]; /* HOSTPC extension */
#define HOSTPC_PHCD (1<<22) /* Phy clock disable */
#define HOSTPC_PSPD (3<<25) /* Port speed detection */
- u32 reserved5[16];
+ u32 reserved5[17];
/* USBMODE_EX: offset 0xc8 */
u32 usbmode_ex; /* USB Device mode extension */
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] x86, build: copy ldlinux.c32 to image.iso
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (40 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] USB: EHCI: declare hostpc register as zero-length array Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] kprobes/x86: Clear TF bit in fault on single-stepping Jiri Slaby
` (8 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: H. Peter Anvin, Jiri Slaby
From: "H. Peter Anvin" <hpa@zytor.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 9c77679cadb118c0aa99e6f88533d91765a131ba upstream.
For newer versions of Syslinux, we need ldlinux.c32 in addition to
isolinux.bin to reside on the boot disk, so if the latter is found,
copy it, too, to the isoimage tree.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
arch/x86/boot/Makefile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 6cf0111783d3..368f3582c93e 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -168,6 +168,9 @@ isoimage: $(obj)/bzImage
for i in lib lib64 share end ; do \
if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
+ if [ -f /usr/$$i/syslinux/ldlinux.c32 ]; then \
+ cp /usr/$$i/syslinux/ldlinux.c32 $(obj)/isoimage ; \
+ fi ; \
break ; \
fi ; \
if [ $$i = end ] ; then exit 1 ; fi ; \
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] kprobes/x86: Clear TF bit in fault on single-stepping
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (41 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] x86, build: copy ldlinux.c32 to image.iso Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] x86/amd_nb: Fix boot crash on non-AMD systems Jiri Slaby
` (7 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable
Cc: Masami Hiramatsu, Alexander Shishkin, Andy Lutomirski,
Arnaldo Carvalho de Melo, Borislav Petkov, Brian Gerst,
Denys Vlasenko, H . Peter Anvin, Jiri Olsa, Linus Torvalds,
Peter Zijlstra, Stephane Eranian, Thomas Gleixner, Vince Weaver,
systemtap, Ingo Molnar, Jiri Slaby
From: Masami Hiramatsu <mhiramat@kernel.org>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] x86/amd_nb: Fix boot crash on non-AMD systems
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (42 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] kprobes/x86: Clear TF bit in fault on single-stepping Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] make nfs_atomic_open() call d_drop() on all ->open_context() errors Jiri Slaby
` (6 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable
Cc: Borislav Petkov, Linus Torvalds, Peter Zijlstra, Thomas Gleixner,
Ingo Molnar, Jiri Slaby
From: Borislav Petkov <bp@suse.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 1ead852dd88779eda12cb09cc894a03d9abfe1ec upstream.
Fix boot crash that triggers if this driver is built into a kernel and
run on non-AMD systems.
AMD northbridges users call amd_cache_northbridges() and it returns
a negative value to signal that we weren't able to cache/detect any
northbridges on the system.
At least, it should do so as all its callers expect it to do so. But it
does return a negative value only when kmalloc() fails.
Fix it to return -ENODEV if there are no NBs cached as otherwise, amd_nb
users like amd64_edac, for example, which relies on it to know whether
it should load or not, gets loaded on systems like Intel Xeons where it
shouldn't.
Reported-and-tested-by: Tony Battersby <tonyb@cybernetics.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1466097230-5333-2-git-send-email-bp@alien8.de
Link: https://lkml.kernel.org/r/5761BEB0.9000807@cybernetics.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
arch/x86/kernel/amd_nb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 6523534671b6..29957e8e2fc5 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -69,8 +69,8 @@ int amd_cache_northbridges(void)
while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL)
i++;
- if (i == 0)
- return 0;
+ if (!i)
+ return -ENODEV;
nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL);
if (!nb)
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] make nfs_atomic_open() call d_drop() on all ->open_context() errors.
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (43 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] x86/amd_nb: Fix boot crash on non-AMD systems Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] NFS: Fix another OPEN_DOWNGRADE bug Jiri Slaby
` (5 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Al Viro, Al Viro, Trond Myklebust, Anna Schumaker, Jiri Slaby
From: Al Viro <viro@ZenIV.linux.org.uk>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit d20cb71dbf3487f24549ede1a8e2d67579b4632e upstream.
In "NFSv4: Move dentry instantiation into the NFSv4-specific atomic open code"
unconditional d_drop() after the ->open_context() had been removed. It had
been correct for success cases (there ->open_context() itself had been doing
dcache manipulations), but not for error ones. Only one of those (ENOENT)
got a compensatory d_drop() added in that commit, but in fact it should've
been done for all errors. As it is, the case of O_CREAT non-exclusive open
on a hashed negative dentry racing with e.g. symlink creation from another
client ended up with ->open_context() getting an error and proceeding to
call nfs_lookup(). On a hashed dentry, which would've instantly triggered
BUG_ON() in d_materialise_unique() (or, these days, its equivalent in
d_splice_alias()).
Tested-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
fs/nfs/dir.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index cf6ede69a2e2..b9670301d7d3 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1483,9 +1483,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
err = PTR_ERR(inode);
trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
put_nfs_open_context(ctx);
+ d_drop(dentry);
switch (err) {
case -ENOENT:
- d_drop(dentry);
d_add(dentry, NULL);
break;
case -EISDIR:
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] NFS: Fix another OPEN_DOWNGRADE bug
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (44 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] make nfs_atomic_open() call d_drop() on all ->open_context() errors Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] ARM: 8578/1: mm: ensure pmd_present only checks the valid bit Jiri Slaby
` (4 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Trond Myklebust, Anna Schumaker, Jiri Slaby
From: Trond Myklebust <trond.myklebust@primarydata.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit e547f2628327fec6afd2e03b46f113f614cca05b upstream.
Olga Kornievskaia reports that the following test fails to trigger
an OPEN_DOWNGRADE on the wire, and only triggers the final CLOSE.
fd0 = open(foo, RDRW) -- should be open on the wire for "both"
fd1 = open(foo, RDONLY) -- should be open on the wire for "read"
close(fd0) -- should trigger an open_downgrade
read(fd1)
close(fd1)
The issue is that we're missing a check for whether or not the current
state transitioned from an O_RDWR state as opposed to having transitioned
from a combination of O_RDONLY and O_WRONLY.
Reported-by: Olga Kornievskaia <aglo@umich.edu>
Fixes: cd9288ffaea4 ("NFSv4: Fix another bug in the close/open_downgrade code")
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
fs/nfs/nfs4proc.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ae85a71e5045..a94ec130003b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2569,12 +2569,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
call_close |= is_wronly;
else if (is_wronly)
calldata->arg.fmode |= FMODE_WRITE;
+ if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
+ call_close |= is_rdwr;
} else if (is_rdwr)
calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
- if (calldata->arg.fmode == 0)
- call_close |= is_rdwr;
-
if (!nfs4_valid_open_stateid(state))
call_close = 0;
spin_unlock(&state->owner->so_lock);
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] ARM: 8578/1: mm: ensure pmd_present only checks the valid bit
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (45 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] NFS: Fix another OPEN_DOWNGRADE bug Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] mm: Export migrate_page_move_mapping and migrate_page_copy Jiri Slaby
` (3 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable
Cc: Will Deacon, Russell King, Steve Capper, Catalin Marinas,
Russell King, Jiri Slaby
From: Will Deacon <will.deacon@arm.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 624531886987f0f1b5d01fb598034d039198e090 upstream.
In a subsequent patch, pmd_mknotpresent will clear the valid bit of the
pmd entry, resulting in a not-present entry from the hardware's
perspective. Unfortunately, pmd_present simply checks for a non-zero pmd
value and will therefore continue to return true even after a
pmd_mknotpresent operation. Since pmd_mknotpresent is only used for
managing huge entries, this is only an issue for the 3-level case.
This patch fixes the 3-level pmd_present implementation to take into
account the valid bit. For bisectability, the change is made before the
fix to pmd_mknotpresent.
[catalin.marinas@arm.com: comment update regarding pmd_mknotpresent patch]
Fixes: 8d9625070073 ("ARM: mm: Transparent huge page support for LPAE systems.")
Cc: Russell King <linux@armlinux.org.uk>
Cc: Steve Capper <Steve.Capper@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
arch/arm/include/asm/pgtable-2level.h | 1 +
arch/arm/include/asm/pgtable-3level.h | 1 +
arch/arm/include/asm/pgtable.h | 1 -
3 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index c98c9c89b95c..3f1b3a4150b6 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -162,6 +162,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
}
#define pmd_bad(pmd) (pmd_val(pmd) & 2)
+#define pmd_present(pmd) (pmd_val(pmd))
#define copy_pmd(pmdpd,pmdps) \
do { \
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 6a171d0afc12..8afa39f81477 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -209,6 +209,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
: !!(pmd_val(pmd) & (val)))
#define pmd_isclear(pmd, val) (!(pmd_val(pmd) & (val)))
+#define pmd_present(pmd) (pmd_isset((pmd), L_PMD_SECT_VALID))
#define pmd_young(pmd) (pmd_isset((pmd), PMD_SECT_AF))
#define __HAVE_ARCH_PMD_WRITE
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index a348bfd34f66..5bdf9864fb00 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -182,7 +182,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
#define pmd_none(pmd) (!pmd_val(pmd))
-#define pmd_present(pmd) (pmd_val(pmd))
static inline pte_t *pmd_page_vaddr(pmd_t pmd)
{
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] mm: Export migrate_page_move_mapping and migrate_page_copy
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (46 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] ARM: 8578/1: mm: ensure pmd_present only checks the valid bit Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] UBIFS: Implement ->migratepage() Jiri Slaby
` (2 subsequent siblings)
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Richard Weinberger, Jiri Slaby
From: Richard Weinberger <richard@nod.at>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 1118dce773d84f39ebd51a9fe7261f9169cb056e upstream.
Export these symbols such that UBIFS can implement
->migratepage.
Signed-off-by: Richard Weinberger <richard@nod.at>
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
mm/migrate.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mm/migrate.c b/mm/migrate.c
index 0c14c0e1bdd6..71a2533ca8f5 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -399,6 +399,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
return MIGRATEPAGE_SUCCESS;
}
+EXPORT_SYMBOL(migrate_page_move_mapping);
/*
* The expected number of remaining references is the same as that
@@ -549,6 +550,7 @@ void migrate_page_copy(struct page *newpage, struct page *page)
if (PageWriteback(newpage))
end_page_writeback(newpage);
}
+EXPORT_SYMBOL(migrate_page_copy);
/************************************************************
* Migration functions
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] UBIFS: Implement ->migratepage()
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (47 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] mm: Export migrate_page_move_mapping and migrate_page_copy Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] scsi: remove scsi_end_request Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] scsi_lib: correctly retry failed zero length REQ_TYPE_FS commands Jiri Slaby
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Kirill A. Shutemov, Richard Weinberger, Jiri Slaby
From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit 4ac1c17b2044a1b4b2fbed74451947e905fc2992 upstream.
During page migrations UBIFS might get confused
and the following assert triggers:
[ 213.480000] UBIFS assert failed in ubifs_set_page_dirty at 1451 (pid 436)
[ 213.490000] CPU: 0 PID: 436 Comm: drm-stress-test Not tainted 4.4.4-00176-geaa802524636-dirty #1008
[ 213.490000] Hardware name: Allwinner sun4i/sun5i Families
[ 213.490000] [<c0015e70>] (unwind_backtrace) from [<c0012cdc>] (show_stack+0x10/0x14)
[ 213.490000] [<c0012cdc>] (show_stack) from [<c02ad834>] (dump_stack+0x8c/0xa0)
[ 213.490000] [<c02ad834>] (dump_stack) from [<c0236ee8>] (ubifs_set_page_dirty+0x44/0x50)
[ 213.490000] [<c0236ee8>] (ubifs_set_page_dirty) from [<c00fa0bc>] (try_to_unmap_one+0x10c/0x3a8)
[ 213.490000] [<c00fa0bc>] (try_to_unmap_one) from [<c00fadb4>] (rmap_walk+0xb4/0x290)
[ 213.490000] [<c00fadb4>] (rmap_walk) from [<c00fb1bc>] (try_to_unmap+0x64/0x80)
[ 213.490000] [<c00fb1bc>] (try_to_unmap) from [<c010dc28>] (migrate_pages+0x328/0x7a0)
[ 213.490000] [<c010dc28>] (migrate_pages) from [<c00d0cb0>] (alloc_contig_range+0x168/0x2f4)
[ 213.490000] [<c00d0cb0>] (alloc_contig_range) from [<c010ec00>] (cma_alloc+0x170/0x2c0)
[ 213.490000] [<c010ec00>] (cma_alloc) from [<c001a958>] (__alloc_from_contiguous+0x38/0xd8)
[ 213.490000] [<c001a958>] (__alloc_from_contiguous) from [<c001ad44>] (__dma_alloc+0x23c/0x274)
[ 213.490000] [<c001ad44>] (__dma_alloc) from [<c001ae08>] (arm_dma_alloc+0x54/0x5c)
[ 213.490000] [<c001ae08>] (arm_dma_alloc) from [<c035cecc>] (drm_gem_cma_create+0xb8/0xf0)
[ 213.490000] [<c035cecc>] (drm_gem_cma_create) from [<c035cf20>] (drm_gem_cma_create_with_handle+0x1c/0xe8)
[ 213.490000] [<c035cf20>] (drm_gem_cma_create_with_handle) from [<c035d088>] (drm_gem_cma_dumb_create+0x3c/0x48)
[ 213.490000] [<c035d088>] (drm_gem_cma_dumb_create) from [<c0341ed8>] (drm_ioctl+0x12c/0x444)
[ 213.490000] [<c0341ed8>] (drm_ioctl) from [<c0121adc>] (do_vfs_ioctl+0x3f4/0x614)
[ 213.490000] [<c0121adc>] (do_vfs_ioctl) from [<c0121d30>] (SyS_ioctl+0x34/0x5c)
[ 213.490000] [<c0121d30>] (SyS_ioctl) from [<c000f2c0>] (ret_fast_syscall+0x0/0x34)
UBIFS is using PagePrivate() which can have different meanings across
filesystems. Therefore the generic page migration code cannot handle this
case correctly.
We have to implement our own migration function which basically does a
plain copy but also duplicates the page private flag.
UBIFS is not a block device filesystem and cannot use buffer_migrate_page().
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
[rw: Massaged changelog, build fixes, etc...]
Signed-off-by: Richard Weinberger <richard@nod.at>
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
fs/ubifs/file.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index b56eb6275744..c0d8fde3e6d9 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -54,6 +54,7 @@
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/slab.h>
+#include <linux/migrate.h>
static int read_block(struct inode *inode, void *addr, unsigned int block,
struct ubifs_data_node *dn)
@@ -1423,6 +1424,26 @@ static int ubifs_set_page_dirty(struct page *page)
return ret;
}
+#ifdef CONFIG_MIGRATION
+static int ubifs_migrate_page(struct address_space *mapping,
+ struct page *newpage, struct page *page, enum migrate_mode mode)
+{
+ int rc;
+
+ rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+ if (rc != MIGRATEPAGE_SUCCESS)
+ return rc;
+
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ SetPagePrivate(newpage);
+ }
+
+ migrate_page_copy(newpage, page);
+ return MIGRATEPAGE_SUCCESS;
+}
+#endif
+
static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
{
/*
@@ -1559,6 +1580,9 @@ const struct address_space_operations ubifs_file_address_operations = {
.write_end = ubifs_write_end,
.invalidatepage = ubifs_invalidatepage,
.set_page_dirty = ubifs_set_page_dirty,
+#ifdef CONFIG_MIGRATION
+ .migratepage = ubifs_migrate_page,
+#endif
.releasepage = ubifs_releasepage,
};
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] scsi: remove scsi_end_request
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (48 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] UBIFS: Implement ->migratepage() Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] scsi_lib: correctly retry failed zero length REQ_TYPE_FS commands Jiri Slaby
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable; +Cc: Christoph Hellwig, Jack Wang, Jiri Slaby
From: Christoph Hellwig <hch@lst.de>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us 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.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [patch added to 3.12-stable] scsi_lib: correctly retry failed zero length REQ_TYPE_FS commands
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
` (49 preceding siblings ...)
2016-07-12 9:41 ` [patch added to 3.12-stable] scsi: remove scsi_end_request Jiri Slaby
@ 2016-07-12 9:41 ` Jiri Slaby
50 siblings, 0 replies; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 9:41 UTC (permalink / raw)
To: stable
Cc: James Bottomley, James E . J . Bottomley, Martin K . Petersen,
Jack Wang, Jiri Slaby
From: James Bottomley <James.Bottomley@HansenPartnership.com>
This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.
===============
commit a621bac3044ed6f7ec5fa0326491b2d4838bfa93 upstream.
When SCSI was written, all commands coming from the filesystem
(REQ_TYPE_FS commands) had data. This meant that our signal for needing
to complete the command was the number of bytes completed being equal to
the number of bytes in the request. Unfortunately, with the advent of
flush barriers, we can now get zero length REQ_TYPE_FS commands, which
confuse this logic because they satisfy the condition every time. This
means they never get retried even for retryable conditions, like UNIT
ATTENTION because we complete them early assuming they're done. Fix
this by special casing the early completion condition to recognise zero
length commands with errors and let them drop through to the retry code.
Cc: stable@vger.kernel.org
Reported-by: Sebastian Parschauer <s.parschauer@gmx.de>
Signed-off-by: James E.J. Bottomley <jejb@linux.vnet.ibm.com>
Tested-by: Jack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
[ jwang: backport from upstream 4.7 to fix scsi resize issue ]
Signed-off-by: Jack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
drivers/scsi/scsi_lib.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 4b7893364c7a..aeff39767588 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -806,9 +806,12 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
}
/*
- * If we finished all bytes in the request we are done now.
+ * special case: failed zero length commands always need to
+ * drop down into the retry code. Otherwise, if we finished
+ * all bytes in the request we are done now.
*/
- if (!blk_end_request(req, error, good_bytes))
+ if (!(blk_rq_bytes(req) == 0 && error) &&
+ !blk_end_request(req, error, good_bytes))
goto next_command;
/*
--
2.9.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* Re: [patch added to 3.12-stable] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism Jiri Slaby
@ 2016-07-12 12:35 ` Guilherme G. Piccoli
2016-07-12 13:03 ` Jiri Slaby
0 siblings, 1 reply; 55+ messages in thread
From: Guilherme G. Piccoli @ 2016-07-12 12:35 UTC (permalink / raw)
To: Jiri Slaby, stable; +Cc: Michael Ellerman, Gavin Shan
On 07/12/2016 06:41 AM, Jiri Slaby wrote:
> From: "Guilherme G. Piccoli" <gpiccoli@linux.vnet.ibm.com>
>
> This patch has been added to the 3.12 stable tree. If you have any
> objections, please let us know.
>
Jiri, thanks for letting me know. If you added this on 3.12, you need to
add another commit (that has a fix to this one): 8a934efe9434
("powerpc/pseries: Fix PCI config address for DDW")
I'm not sure if you already added 8a934efe9434, but in any case I found
useful to warn you.
Cheers,
Guilherme
> ===============
>
> 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) */
>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [patch added to 3.12-stable] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism
2016-07-12 12:35 ` Guilherme G. Piccoli
@ 2016-07-12 13:03 ` Jiri Slaby
2016-07-12 13:20 ` Guilherme G. Piccoli
0 siblings, 1 reply; 55+ messages in thread
From: Jiri Slaby @ 2016-07-12 13:03 UTC (permalink / raw)
To: Guilherme G. Piccoli, stable; +Cc: Michael Ellerman, Gavin Shan
On 07/12/2016, 02:35 PM, Guilherme G. Piccoli wrote:
> On 07/12/2016 06:41 AM, Jiri Slaby wrote:
>> From: "Guilherme G. Piccoli" <gpiccoli@linux.vnet.ibm.com>
>>
>> This patch has been added to the 3.12 stable tree. If you have any
>> objections, please let us know.
>>
>
> Jiri, thanks for letting me know. If you added this on 3.12, you need to
> add another commit (that has a fix to this one): 8a934efe9434
> ("powerpc/pseries: Fix PCI config address for DDW")
>
> I'm not sure if you already added 8a934efe9434, but in any case I found
> useful to warn you.
Yes, 8a934efe9434 was added too. Thanks for the heads-up, it's
appreciated. Thanks.
--
js
suse labs
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [patch added to 3.12-stable] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism
2016-07-12 13:03 ` Jiri Slaby
@ 2016-07-12 13:20 ` Guilherme G. Piccoli
0 siblings, 0 replies; 55+ messages in thread
From: Guilherme G. Piccoli @ 2016-07-12 13:20 UTC (permalink / raw)
To: Jiri Slaby, stable; +Cc: Michael Ellerman, Gavin Shan
On 07/12/2016 10:03 AM, Jiri Slaby wrote:
> On 07/12/2016, 02:35 PM, Guilherme G. Piccoli wrote:
>> On 07/12/2016 06:41 AM, Jiri Slaby wrote:
>>> From: "Guilherme G. Piccoli" <gpiccoli@linux.vnet.ibm.com>
>>>
>>> This patch has been added to the 3.12 stable tree. If you have any
>>> objections, please let us know.
>>>
>>
>> Jiri, thanks for letting me know. If you added this on 3.12, you need to
>> add another commit (that has a fix to this one): 8a934efe9434
>> ("powerpc/pseries: Fix PCI config address for DDW")
>>
>> I'm not sure if you already added 8a934efe9434, but in any case I found
>> useful to warn you.
>
> Yes, 8a934efe9434 was added too. Thanks for the heads-up, it's
> appreciated. Thanks.
Thank you Jiri :)
^ permalink raw reply [flat|nested] 55+ messages in thread
end of thread, other threads:[~2016-07-12 13:20 UTC | newest]
Thread overview: 55+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-12 9:40 [patch added to 3.12-stable] macintosh/therm_windtunnel: Export I2C module alias information Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] drivers: macintosh: rack-meter: limit idle ticks to total ticks Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] ARM: fix PTRACE_SETVFPREGS on SMP systems Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] powerpc: Fix definition of SIAR and SDAR registers Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] powerpc: Use privileged SPR number for MMCR2 Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] parisc: Fix pagefault crash in unaligned __get_user() call Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] ecryptfs: forbid opening files without mmap handler Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] fix d_walk()/non-delayed __d_free() race Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: don't move to non-existent next rule Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: validate targets of jumps Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: add and use xt_check_entry_offsets Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: kill check_entry helper Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: assert minimum target size Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: add compat version of xt_check_entry_offsets Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: check standard target size too Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: check for bogus target offset Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: validate all offsets and sizes in a rule Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: x_tables: don't reject valid target size on some architectures Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: arp_tables: simplify translate_compat_table args Jiri Slaby
2016-07-12 9:40 ` [patch added to 3.12-stable] netfilter: ip_tables: " Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: ip6_tables: " Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: xt_compat_match_from_user doesn't need a retval Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: ensure number of counters is >0 in do_replace() Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: do compat validation via translate_table Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] Revert "netfilter: ensure number of counters is >0 in do_replace()" Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] netfilter: x_tables: introduce and use xt_copy_counters_from_user Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] crypto: ux500 - memmove the right size Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] sit: correct IP protocol used in ipip6_err Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] ipmr/ip6mr: Initialize the last assert time of mfc entries Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] net: alx: Work around the DMA RX overflow issue Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: quirks: Add no-lpm quirk for Acer C120 LED Projector Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: musb: Stop bulk endpoint while queue is rotated Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] usb: musb: Ensure rx reinit occurs for shared_fifo endpoints Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] mac80211: mesh: flush mesh paths unconditionally Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] mac80211_hwsim: Add missing check for HWSIM_ATTR_SIGNAL Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] IB/mlx4: Properly initialize GRH TClass and FlowLabel in AHs Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism Jiri Slaby
2016-07-12 12:35 ` Guilherme G. Piccoli
2016-07-12 13:03 ` Jiri Slaby
2016-07-12 13:20 ` Guilherme G. Piccoli
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/pseries: Fix PCI config address for DDW Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] powerpc/tm: Always reclaim in start_thread() for exec() class syscalls Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] USB: EHCI: declare hostpc register as zero-length array Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] x86, build: copy ldlinux.c32 to image.iso Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] kprobes/x86: Clear TF bit in fault on single-stepping Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] x86/amd_nb: Fix boot crash on non-AMD systems Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] make nfs_atomic_open() call d_drop() on all ->open_context() errors Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] NFS: Fix another OPEN_DOWNGRADE bug Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] ARM: 8578/1: mm: ensure pmd_present only checks the valid bit Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] mm: Export migrate_page_move_mapping and migrate_page_copy Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] UBIFS: Implement ->migratepage() Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] scsi: remove scsi_end_request Jiri Slaby
2016-07-12 9:41 ` [patch added to 3.12-stable] scsi_lib: correctly retry failed zero length REQ_TYPE_FS commands Jiri Slaby
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).