3.14.73-stable review
Greg Kroah-Hartman
maintainercover 3.14.73-stable review
This is the start of the stable review cycle for the 3.14.73 release. There are 29 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri Jun 24 22:35:07 UTC 2016. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v3.x/stable-review/patch-3.14.73-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-3.14.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 3.14.73-rc1
Florian Westphal <[email protected]>
netfilter: x_tables: don't reject valid target size on some architectures
Florian Westphal <[email protected]>
netfilter: x_tables: validate all offsets and sizes in a rule
Florian Westphal <[email protected]>
netfilter: x_tables: check for bogus target offset
Florian Westphal <[email protected]>
netfilter: x_tables: check standard target size too
Florian Westphal <[email protected]>
netfilter: x_tables: add compat version of xt_check_entry_offsets
Florian Westphal <[email protected]>
netfilter: x_tables: assert minimum target size
Florian Westphal <[email protected]>
netfilter: x_tables: kill check_entry helper
Florian Westphal <[email protected]>
netfilter: x_tables: add and use xt_check_entry_offsets
Florian Westphal <[email protected]>
netfilter: x_tables: validate targets of jumps
Florian Westphal <[email protected]>
netfilter: x_tables: don't move to non-existent next rule
Willy Tarreau <[email protected]>
pipe: limit the per-user amount of pages allocated in pipes
Greg Kroah-Hartman <[email protected]>
xfs: fix up backport error in fs/xfs/xfs_inode.c
Florian Westphal <[email protected]>
netfilter: x_tables: fix unconditional helper
Florian Westphal <[email protected]>
netfilter: x_tables: make sure e->next_offset covers remaining blob size
Florian Westphal <[email protected]>
netfilter: x_tables: validate e->target_offset early
Russell Currey <[email protected]>
powerpc/pseries/eeh: Handle RTAS delay requests in configure_bridge
Ralf Baechle <[email protected]>
MIPS: Fix 64k page support for 32 bit kernels.
Al Viro <[email protected]>
fix d_walk()/non-delayed __d_free() race
Prasun Maiti <[email protected]>
wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel
Jann Horn <[email protected]>
ecryptfs: forbid opening files without mmap handler
Helge Deller <[email protected]>
parisc: Fix pagefault crash in unaligned __get_user() call
Thomas Huth <[email protected]>
powerpc: Use privileged SPR number for MMCR2
Thomas Huth <[email protected]>
powerpc: Fix definition of SIAR and SDAR registers
Tom Lendacky <[email protected]>
crypto: ccp - Fix AES XTS error for request sizes above 4096
Russell King <[email protected]>
ARM: fix PTRACE_SETVFPREGS on SMP systems
Paolo Bonzini <[email protected]>
KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS
Yuchung Cheng <[email protected]>
tcp: record TLP and ER timer stats in v6 stats
Edward Cree <[email protected]>
sfc: on MC reset, clear PIO buffer linkage in TXQs
Herbert Xu <[email protected]>
netlink: Fix dump skb leak/double free
-------------
Diffstat:
Documentation/sysctl/fs.txt | 23 ++++ Makefile | 4 +- arch/arm/kernel/ptrace.c | 2 +- arch/mips/include/asm/processor.h | 2 +- arch/parisc/kernel/unaligned.c | 10 +- arch/powerpc/include/asm/reg.h | 6 +- arch/powerpc/platforms/pseries/eeh_pseries.c | 51 ++++++--- arch/x86/kvm/x86.c | 5 + drivers/crypto/ccp/ccp-crypto-aes-xts.c | 17 ++- drivers/net/ethernet/sfc/ef10.c | 16 +++ fs/dcache.c | 4 +- fs/ecryptfs/kthread.c | 13 ++- fs/pipe.c | 47 +++++++- fs/xfs/xfs_inode.c | 2 +- include/linux/netfilter/x_tables.h | 7 ++ include/linux/pipe_fs_i.h | 4 + include/linux/sched.h | 1 + kernel/sysctl.c | 14 +++ net/ipv4/netfilter/arp_tables.c | 87 ++++++++------- net/ipv4/netfilter/ip_tables.c | 90 ++++++++------- net/ipv6/netfilter/ip6_tables.c | 90 ++++++++------- net/ipv6/tcp_ipv6.c | 4 +- net/netfilter/x_tables.c | 158 +++++++++++++++++++++++++++ net/netlink/af_netlink.c | 7 +- net/wireless/wext-core.c | 25 ++++- 25 files changed, 528 insertions(+), 161 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/29 netlink: Fix dump skb leak/double free
3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
[ Upstream commit 92964c79b357efd980812c4de5c1fd2ec8bb5520 ]
When we free cb->skb after a dump, we do it after releasing the lock. This means that a new dump could have started in the time being and we'll end up freeing their skb instead of ours.
This patch saves the skb and module before we unlock so we free the right memory.
--- net/netlink/af_netlink.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
net/netlink/af_netlink.c +5 -2
@@ -2651,6 +2651,7 @@ static int netlink_dump(struct sock *sk)struct netlink_callback *cb;struct sk_buff *skb =NULL ;struct nlmsghdr *nlh; +struct module *module;int len, err = -ENOBUFS ;int alloc_size;
@@ -2700,9 +2701,11 @@ static int netlink_dump(struct sock *sk) cb->done (cb); nlk->cb_running = false; + module = cb->module; + skb = cb->skb;mutex_unlock (nlk->cb_mutex); -module_put (cb->module); -consume_skb (cb->skb); +module_put (module); +consume_skb (skb);return 0 ; errout_skb:
Greg Kroah-Hartman
maintainerPATCH 2/29 sfc: on MC reset, clear PIO buffer linkage in TXQs
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Cree <[email protected]>
[ Upstream commit c0795bf64cba4d1b796fdc5b74b33772841ed1bb ]
Otherwise, if we fail to allocate new PIO buffers, our TXQs will try to use the old ones, which aren't there any more.
--- drivers/net/ethernet/sfc/ef10.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
drivers/net/ethernet/sfc/ef10.c +16 -0
@@ -451,6 +451,17 @@ fail: return rc; } +static void efx_ef10_forget_old_piobufs (struct efx_nic *efx) +{ +struct efx_channel *channel; +struct efx_tx_queue *tx_queue; + +/* All our existing PIO buffers went away */ +efx_for_each_channel (channel, efx) +efx_for_each_channel_tx_queue (tx_queue, channel) + tx_queue->piobuf =NULL ; +} +#else /* !EFX_USE_PIO */ static int efx_ef10_alloc_piobufs (struct efx_nic *efx,unsigned int n)
@@ -467,6 +478,10 @@ static void efx_ef10_free_piobufs(struct { } +static void efx_ef10_forget_old_piobufs (struct efx_nic *efx) +{ +} +#endif /* EFX_USE_PIO */ static void efx_ef10_remove (struct efx_nic *efx)
@@ -698,6 +713,7 @@ static void efx_ef10_reset_mc_allocation nic_data->must_realloc_vis = true; nic_data->must_restore_filters = true; nic_data->must_restore_piobufs = true; +efx_ef10_forget_old_piobufs (efx); nic_data->rx_rss_context =EFX_EF10_RSS_CONTEXT_INVALID ; }
Greg Kroah-Hartman
maintainerPATCH 3/29 tcp: record TLP and ER timer stats in v6 stats
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuchung Cheng <[email protected]>
[ Upstream commit ce3cf4ec0305919fc69a972f6c2b2efd35d36abc ]
The v6 tcp stats scan do not provide TLP and ER timer information correctly like the v4 version . This patch fixes that.
--- net/ipv6/tcp_ipv6.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv6/tcp_ipv6.c +3 -1
@@ -1783,7 +1783,9 @@ static void get_tcp6_sock(struct seq_fil destp =ntohs (inet->inet_dport); srcp =ntohs (inet->inet_sport); -if (icsk->icsk_pending ==ICSK_TIME_RETRANS ) { +if (icsk->icsk_pending ==ICSK_TIME_RETRANS || + icsk->icsk_pending ==ICSK_TIME_EARLY_RETRANS || + icsk->icsk_pending ==ICSK_TIME_LOSS_PROBE ) { timer_active =1 ; timer_expires = icsk->icsk_timeout; }else if (icsk->icsk_pending ==ICSK_TIME_PROBE0 ) {
Greg Kroah-Hartman
maintainerPATCH 5/29 ARM: fix PTRACE_SETVFPREGS on SMP systems
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Russell King <[email protected]>
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.
--- arch/arm/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/kernel/ptrace.c +1 -1
@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *tif (ret)return ret; -vfp_flush_hwstate (thread); thread->vfpstate.hard = new_vfp; +vfp_flush_hwstate (thread);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 6/29 crypto: ccp - Fix AES XTS error for request sizes above 4096
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tom Lendacky <[email protected]>
commit ab6a11a7c8ef47f996974dd3c648c2c0b1a36ab1 upstream.
The ccp-crypto module for AES XTS support has a bug that can allow requests greater than 4096 bytes in size to be passed to the CCP hardware. The CCP hardware does not support request sizes larger than 4096, resulting in incorrect output. The request should actually be handled by the fallback mechanism instantiated by the ccp-crypto module.
Add a check to insure the request size is less than or equal to the maximum supported size and use the fallback mechanism if it is not.
--- drivers/crypto/ccp/ccp-crypto-aes-xts.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/crypto/ccp/ccp-crypto-aes-xts.c +12 -5
@@ -123,6 +123,7 @@ static int ccp_aes_xts_crypt(struct ablkstruct ccp_ctx *ctx =crypto_tfm_ctx (req->base.tfm);struct ccp_aes_req_ctx *rctx =ablkcipher_request_ctx (req);unsigned int unit; +u32 unit_size;int ret;if (!ctx->u.aes.key_len)
@@ -134,11 +135,17 @@ static int ccp_aes_xts_crypt(struct ablkif (!req->info)return -EINVAL ; -for (unit =0 ; unit <ARRAY_SIZE (unit_size_map); unit++) -if (!(req->nbytes & (unit_size_map[unit].size -1 ))) -break ; + unit_size =CCP_XTS_AES_UNIT_SIZE__LAST ; +if (req->nbytes <= unit_size_map[0 ].size) { +for (unit =0 ; unit <ARRAY_SIZE (unit_size_map); unit++) { +if (!(req->nbytes & (unit_size_map[unit].size -1 ))) { + unit_size = unit_size_map[unit].value; +break ; + } + } + } -if ((unit_size_map[unit].value ==CCP_XTS_AES_UNIT_SIZE__LAST ) || +if ((unit_size ==CCP_XTS_AES_UNIT_SIZE__LAST ) || (ctx->u.aes.key_len !=AES_KEYSIZE_128 )) {/* Use the fallback to process the request for any * unsupported unit sizes or key sizes
@@ -159,7 +166,7 @@ static int ccp_aes_xts_crypt(struct ablk rctx->cmd.engine =CCP_ENGINE_XTS_AES_128 ; rctx->cmd.u.xts.action = (encrypt) ?CCP_AES_ACTION_ENCRYPT :CCP_AES_ACTION_DECRYPT ; - rctx->cmd.u.xts.unit_size = unit_size_map[unit].value; + rctx->cmd.u.xts.unit_size = unit_size; rctx->cmd.u.xts.key = &ctx->u.aes.key_sg; rctx->cmd.u.xts.key_len = ctx->u.aes.key_len; rctx->cmd.u.xts.iv = &rctx->iv_sg;
Greg Kroah-Hartman
maintainerPATCH 7/29 powerpc: Fix definition of SIAR and SDAR registers
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Huth <[email protected]>
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.
--- arch/powerpc/include/asm/reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/include/asm/reg.h +2 -2
@@ -715,13 +715,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#define SPRN_TACR 888#define SPRN_TCSCR 889#define SPRN_CSIGR 890
Greg Kroah-Hartman
maintainerPATCH 8/29 powerpc: Use privileged SPR number for MMCR2
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Huth <[email protected]>
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.
--- arch/powerpc/include/asm/reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/include/asm/reg.h +1 -1
@@ -680,7 +680,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
Greg Kroah-Hartman
maintainerPATCH 9/29 parisc: Fix pagefault crash in unaligned __get_user() call
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Helge Deller <[email protected]>
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.
--- arch/parisc/kernel/unaligned.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
arch/parisc/kernel/unaligned.c +9 -1
@@ -666,7 +666,7 @@ void handle_unaligned(struct pt_regs *rebreak ; } -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 *reif (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 );
Greg Kroah-Hartman
maintainerPATCH 10/29 ecryptfs: forbid opening files without mmap handler
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn <[email protected]>
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.
--- fs/ecryptfs/kthread.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
fs/ecryptfs/kthread.c +11 -2
@@ -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 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 filemutex_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; }
Greg Kroah-Hartman
maintainerPATCH 11/29 wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Prasun Maiti <[email protected]>
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.
--- net/wireless/wext-core.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
net/wireless/wext-core.c +23 -2
@@ -954,8 +954,29 @@ static int wireless_process_ioctl(structreturn 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 ; }
Greg Kroah-Hartman
maintainerPATCH 12/29 fix d_walk()/non-delayed __d_free() race
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
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.
--- fs/dcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/dcache.c +2 -2
@@ -1500,7 +1500,7 @@ struct dentry *d_alloc(struct dentry * pstruct 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
@@ -2352,7 +2352,6 @@ static void __d_rehash(struct dentry * e {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); }
@@ -2536,6 +2535,7 @@ static void __d_move(struct dentry * den/* ... 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);
Greg Kroah-Hartman
maintainerPATCH 13/29 MIPS: Fix 64k page support for 32 bit kernels.
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ralf Baechle <[email protected]>
commit d7de413475f443957a0c1d256e405d19b3a2cb22 upstream.
TASK_SIZE was defined as 0x7fff8000UL which for 64k pages is not a multiple of the page size. Somewhere further down the math fails such that executing an ELF binary fails.
--- arch/mips/include/asm/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/include/asm/processor.h +1 -1
@@ -51,7 +51,7 @@ extern unsigned int vced_count, vcei_cou* User space process size: 2GB. This is hardcoded into a few places, * so don't change it unless you know what you are doing. */ -#define TASK_SIZE 0x7fff8000UL +#define TASK_SIZE 0x80000000UL#endif #ifdef __KERNEL__
Greg Kroah-Hartman
maintainerPATCH 14/29 powerpc/pseries/eeh: Handle RTAS delay requests in configure_bridge
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Russell Currey <[email protected]>
commit 871e178e0f2c4fa788f694721a10b4758d494ce1 upstream.
In the "ibm,configure-pe" and "ibm,configure-bridge" RTAS calls, the spec states that values of 9900-9905 can be returned, indicating that software should delay for 10^x (where x is the last digit, i.e. 990x) milliseconds and attempt the call again. Currently, the kernel doesn't know about this, and respecting it fixes some PCI failures when the hypervisor is busy.
The delay is capped at 0.2 seconds.
--- arch/powerpc/platforms/pseries/eeh_pseries.c | 51 +++++++++++++++++++-------- 1 file changed, 36 insertions(+), 15 deletions(-)
arch/powerpc/platforms/pseries/eeh_pseries.c +36 -15
@@ -615,29 +615,50 @@ static int pseries_eeh_configure_bridge( {int config_addr;int ret; +/* Waiting 0.2s maximum before skipping configuration */ +int max_wait =200 ;/* Figure out the PE address */ config_addr = pe->config_addr;if (pe->addr) config_addr = pe->addr; -/* Use new configure-pe function, if supported */ -if (ibm_configure_pe !=RTAS_UNKNOWN_SERVICE ) { - ret =rtas_call (ibm_configure_pe,3 ,1 ,NULL , - config_addr,BUID_HI (pe->phb->buid), -BUID_LO (pe->phb->buid)); - }else if (ibm_configure_bridge !=RTAS_UNKNOWN_SERVICE ) { - ret =rtas_call (ibm_configure_bridge,3 ,1 ,NULL , - config_addr,BUID_HI (pe->phb->buid), -BUID_LO (pe->phb->buid)); - }else { -return -EFAULT ; - } +while (max_wait >0 ) { +/* Use new configure-pe function, if supported */ +if (ibm_configure_pe !=RTAS_UNKNOWN_SERVICE ) { + ret =rtas_call (ibm_configure_pe,3 ,1 ,NULL , + config_addr,BUID_HI (pe->phb->buid), +BUID_LO (pe->phb->buid)); + }else if (ibm_configure_bridge !=RTAS_UNKNOWN_SERVICE ) { + ret =rtas_call (ibm_configure_bridge,3 ,1 ,NULL , + config_addr,BUID_HI (pe->phb->buid), +BUID_LO (pe->phb->buid)); + }else { +return -EFAULT ; + } + +if (!ret) +return ret; + +/* +* If RTAS returns a delay value that's above 100ms, cut it +* down to 100ms in case firmware made a mistake. For more +* on how these delay values work see rtas_busy_delay_time +*/ +if (ret >RTAS_EXTENDED_DELAY_MIN +2 && + ret <=RTAS_EXTENDED_DELAY_MAX ) + ret =RTAS_EXTENDED_DELAY_MIN +2 ; -if (ret) -pr_warning ("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n" , - __func__, pe->phb->global_number, pe->addr, ret); + max_wait -=rtas_busy_delay_time (ret); + +if (max_wait <0 ) +break ; + +rtas_busy_delay (ret); + } +pr_warn ("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n" , + __func__, pe->phb->global_number, pe->addr, ret);return ret; }
Greg Kroah-Hartman
maintainerPATCH 15/29 netfilter: x_tables: validate e->target_offset early
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit bdf533de6968e9686df777dc178486f600c6e617 upstream.
We should check that e->target_offset is sane before mark_source_chains gets called since it will fetch the target entry for loop detection.
--- net/ipv4/netfilter/arp_tables.c | 17 ++++++++--------- net/ipv4/netfilter/ip_tables.c | 17 ++++++++--------- net/ipv6/netfilter/ip6_tables.c | 17 ++++++++--------- 3 files changed, 24 insertions(+), 27 deletions(-)
net/ipv4/netfilter/arp_tables.c +8 -9
@@ -470,14 +470,12 @@ static int mark_source_chains(const strureturn 1 ; } -static inline int check_entry (const struct arpt_entry *e,const char *name) +static inline int check_entry (const struct arpt_entry *e) {const struct xt_entry_target *t; -if (!arp_checkentry (&e->arp)) { -duprintf ("arp_tables: arp check failed %p %s.\n" , e, name); +if (!arp_checkentry (&e->arp))return -EINVAL ; - }if (e->target_offset +sizeof (struct xt_entry_target ) > e->next_offset)return -EINVAL ;
@@ -518,10 +516,6 @@ find_check_entry(struct arpt_entry *e, cstruct xt_target *target;int ret; - ret =check_entry (e, name); -if (ret) -return ret; - t =arpt_get_target (e); target =xt_request_find_target (NFPROTO_ARP , t->u.user.name, t->u.user.revision);
@@ -566,6 +560,7 @@ static inline int check_entry_size_and_h unsigned int valid_hooks) {unsigned int h; +int err;if ((unsigned long )e % __alignof__(struct arpt_entry ) !=0 || (unsigned char *)e +sizeof (struct arpt_entry ) >= limit) {
@@ -580,6 +575,10 @@ static inline int check_entry_size_and_hreturn -EINVAL ; } + err =check_entry (e); +if (err) +return err; +/* Check hooks & underflows */ for (h =0 ; h <NF_ARP_NUMHOOKS ; h++) {if (!(valid_hooks & (1 << h)))
@@ -1237,7 +1236,7 @@ check_compat_entry_size_and_hooks(struct }/* For purposes of check_entry casting the compat entry is fine */ - ret =check_entry ((struct arpt_entry *)e, name); + ret =check_entry ((struct arpt_entry *)e);if (ret)return ret;
net/ipv4/netfilter/ip_tables.c +8 -9
@@ -565,14 +565,12 @@ static void cleanup_match(struct xt_entr }static int -check_entry (const struct ipt_entry *e,const char *name) +check_entry (const struct ipt_entry *e) {const struct xt_entry_target *t; -if (!ip_checkentry (&e->ip)) { -duprintf ("ip check failed %p %s.\n" , e, name); +if (!ip_checkentry (&e->ip))return -EINVAL ; - }if (e->target_offset +sizeof (struct xt_entry_target ) > e->next_offset)
@@ -662,10 +660,6 @@ find_check_entry(struct ipt_entry *e, ststruct xt_mtchk_param mtpar;struct xt_entry_match *ematch; - ret =check_entry (e, name); -if (ret) -return ret; - j =0 ; mtpar.net = net; mtpar.table = name;
@@ -729,6 +723,7 @@ check_entry_size_and_hooks(struct ipt_en unsigned int valid_hooks) {unsigned int h; +int err;if ((unsigned long )e % __alignof__(struct ipt_entry ) !=0 || (unsigned char *)e +sizeof (struct ipt_entry ) >= limit) {
@@ -743,6 +738,10 @@ check_entry_size_and_hooks(struct ipt_enreturn -EINVAL ; } + err =check_entry (e); +if (err) +return err; +/* Check hooks & underflows */ for (h =0 ; h <NF_INET_NUMHOOKS ; h++) {if (!(valid_hooks & (1 << h)))
@@ -1503,7 +1502,7 @@ check_compat_entry_size_and_hooks(struct }/* For purposes of check_entry casting the compat entry is fine */ - ret =check_entry ((struct ipt_entry *)e, name); + ret =check_entry ((struct ipt_entry *)e);if (ret)return ret;
net/ipv6/netfilter/ip6_tables.c +8 -9
@@ -575,14 +575,12 @@ static void cleanup_match(struct xt_entr }static int -check_entry (const struct ip6t_entry *e,const char *name) +check_entry (const struct ip6t_entry *e) {const struct xt_entry_target *t; -if (!ip6_checkentry (&e->ipv6)) { -duprintf ("ip_tables: ip check failed %p %s.\n" , e, name); +if (!ip6_checkentry (&e->ipv6))return -EINVAL ; - }if (e->target_offset +sizeof (struct xt_entry_target ) > e->next_offset)
@@ -673,10 +671,6 @@ find_check_entry(struct ip6t_entry *e, sstruct xt_mtchk_param mtpar;struct xt_entry_match *ematch; - ret =check_entry (e, name); -if (ret) -return ret; - j =0 ; mtpar.net = net; mtpar.table = name;
@@ -740,6 +734,7 @@ check_entry_size_and_hooks(struct ip6t_e unsigned int valid_hooks) {unsigned int h; +int err;if ((unsigned long )e % __alignof__(struct ip6t_entry ) !=0 || (unsigned char *)e +sizeof (struct ip6t_entry ) >= limit) {
@@ -754,6 +749,10 @@ check_entry_size_and_hooks(struct ip6t_ereturn -EINVAL ; } + err =check_entry (e); +if (err) +return err; +/* Check hooks & underflows */ for (h =0 ; h <NF_INET_NUMHOOKS ; h++) {if (!(valid_hooks & (1 << h)))
@@ -1515,7 +1514,7 @@ check_compat_entry_size_and_hooks(struct }/* For purposes of check_entry casting the compat entry is fine */ - ret =check_entry ((struct ip6t_entry *)e, name); + ret =check_entry ((struct ip6t_entry *)e);if (ret)return ret;
Greg Kroah-Hartman
maintainerPATCH 16/29 netfilter: x_tables: make sure e->next_offset covers remaining blob size
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit 6e94e0cfb0887e4013b3b930fa6ab1fe6bb6ba91 upstream.
Otherwise this function may read data beyond the ruleset blob.
--- net/ipv4/netfilter/arp_tables.c | 6 ++++-- net/ipv4/netfilter/ip_tables.c | 6 ++++-- net/ipv6/netfilter/ip6_tables.c | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-)
net/ipv4/netfilter/arp_tables.c +4 -2
@@ -563,7 +563,8 @@ static inline int check_entry_size_and_hint err;if ((unsigned long )e % __alignof__(struct arpt_entry ) !=0 || - (unsigned char *)e +sizeof (struct arpt_entry ) >= limit) { + (unsigned char *)e +sizeof (struct arpt_entry ) >= limit || + (unsigned char *)e + e->next_offset > limit) {duprintf ("Bad offset %p\n" , e);return -EINVAL ; }
@@ -1223,7 +1224,8 @@ check_compat_entry_size_and_hooks(structduprintf ("check_compat_entry_size_and_hooks %p\n" , e);if ((unsigned long )e % __alignof__(struct compat_arpt_entry ) !=0 || - (unsigned char *)e +sizeof (struct compat_arpt_entry ) >= limit) { + (unsigned char *)e +sizeof (struct compat_arpt_entry ) >= limit || + (unsigned char *)e + e->next_offset > limit) {duprintf ("Bad offset %p, limit = %p\n" , e, limit);return -EINVAL ; }
net/ipv4/netfilter/ip_tables.c +4 -2
@@ -726,7 +726,8 @@ check_entry_size_and_hooks(struct ipt_enint err;if ((unsigned long )e % __alignof__(struct ipt_entry ) !=0 || - (unsigned char *)e +sizeof (struct ipt_entry ) >= limit) { + (unsigned char *)e +sizeof (struct ipt_entry ) >= limit || + (unsigned char *)e + e->next_offset > limit) {duprintf ("Bad offset %p\n" , e);return -EINVAL ; }
@@ -1489,7 +1490,8 @@ check_compat_entry_size_and_hooks(structduprintf ("check_compat_entry_size_and_hooks %p\n" , e);if ((unsigned long )e % __alignof__(struct compat_ipt_entry ) !=0 || - (unsigned char *)e +sizeof (struct compat_ipt_entry ) >= limit) { + (unsigned char *)e +sizeof (struct compat_ipt_entry ) >= limit || + (unsigned char *)e + e->next_offset > limit) {duprintf ("Bad offset %p, limit = %p\n" , e, limit);return -EINVAL ; }
net/ipv6/netfilter/ip6_tables.c +4 -2
@@ -737,7 +737,8 @@ check_entry_size_and_hooks(struct ip6t_eint err;if ((unsigned long )e % __alignof__(struct ip6t_entry ) !=0 || - (unsigned char *)e +sizeof (struct ip6t_entry ) >= limit) { + (unsigned char *)e +sizeof (struct ip6t_entry ) >= limit || + (unsigned char *)e + e->next_offset > limit) {duprintf ("Bad offset %p\n" , e);return -EINVAL ; }
@@ -1501,7 +1502,8 @@ check_compat_entry_size_and_hooks(structduprintf ("check_compat_entry_size_and_hooks %p\n" , e);if ((unsigned long )e % __alignof__(struct compat_ip6t_entry ) !=0 || - (unsigned char *)e +sizeof (struct compat_ip6t_entry ) >= limit) { + (unsigned char *)e +sizeof (struct compat_ip6t_entry ) >= limit || + (unsigned char *)e + e->next_offset > limit) {duprintf ("Bad offset %p, limit = %p\n" , e, limit);return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 17/29 netfilter: x_tables: fix unconditional helper
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit 54d83fc74aa9ec72794373cb47432c5f7fb1a309 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.
Problem is that mark_source_chains should not have been called -- the rule doesn't have a next entry, so its supposed to return an absolute verdict of either ACCEPT or DROP.
However, the function conditional() doesn't work as the name implies. It only checks that the rule is using wildcard address matching.
However, an unconditional rule must also not be using any matches (no -m args).
The underflow validator only checked the addresses, therefore passing the 'unconditional absolute verdict' test, while mark_source_chains also tested for presence of matches, and thus proceeeded to the next (not-existent) rule.
Unify this so that all the callers have same idea of 'unconditional rule'.
--- net/ipv4/netfilter/arp_tables.c | 18 +++++++++--------- net/ipv4/netfilter/ip_tables.c | 23 +++++++++++------------ net/ipv6/netfilter/ip6_tables.c | 23 +++++++++++------------ 3 files changed, 31 insertions(+), 33 deletions(-)
net/ipv4/netfilter/arp_tables.c +9 -9
@@ -355,11 +355,12 @@ unsigned int arpt_do_table(struct sk_buf }/* All zeroes == unconditional rule. */ -static inline bool unconditional (const struct arpt_arp *arp) +static inline bool unconditional (const struct arpt_entry *e) {static const struct arpt_arp uncond; -return memcmp (arp, &uncond,sizeof (uncond)) ==0 ; +return e->target_offset ==sizeof (struct arpt_entry ) && +memcmp (&e->arp, &uncond,sizeof (uncond)) ==0 ; }/* Figures out from what hook each rule can be called: returns 0 if
@@ -398,11 +399,10 @@ static int mark_source_chains(const stru |= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));/* Unconditional return/END. */ -if ((e->target_offset ==sizeof (struct arpt_entry ) && +if ((unconditional (e) && (strcmp (t->target.u.user.name,XT_STANDARD_TARGET ) ==0 ) && - t->verdict <0 &&unconditional (&e->arp)) || - visited) { + t->verdict <0 ) || visited) {unsigned int oldpos, size; if ((strcmp(t->target.u.user.name,
@@ -541,7 +541,7 @@ static bool check_underflow(const structconst struct xt_entry_target *t;unsigned int verdict; -if (!unconditional (&e->arp)) +if (!unconditional (e))return false; t =arpt_get_target_c (e);if (strcmp (t->u.user.name,XT_STANDARD_TARGET ) !=0 )
@@ -588,9 +588,9 @@ static inline int check_entry_size_and_h newinfo->hook_entry[h] = hook_entries[h];if ((unsigned char *)e - base == underflows[h]) {if (!check_underflow (e)) { -pr_err ("Underflows must be unconditional and " -"use the STANDARD target with " -"ACCEPT/DROP\n" ); +pr_debug ("Underflows must be unconditional and " +"use the STANDARD target with " +"ACCEPT/DROP\n" );return -EINVAL ; } newinfo->underflow[h] = underflows[h];
net/ipv4/netfilter/ip_tables.c +11 -12
@@ -168,11 +168,12 @@ get_entry(const void *base, unsigned int/* All zeroes == unconditional rule. */ /* Mildly perf critical (only if packet tracing is on) */ -static inline bool unconditional (const struct ipt_ip *ip) +static inline bool unconditional (const struct ipt_entry *e) {static const struct ipt_ip uncond; -return memcmp (ip, &uncond,sizeof (uncond)) ==0 ; +return e->target_offset ==sizeof (struct ipt_entry ) && +memcmp (&e->ip, &uncond,sizeof (uncond)) ==0 ;#undef FWINV }
@@ -229,11 +230,10 @@ get_chainname_rulenum(const struct ipt_e }else if (s == e) { (*rulenum)++; -if (s->target_offset ==sizeof (struct ipt_entry ) && +if (unconditional (s) &&strcmp (t->target.u.kernel.target->name,XT_STANDARD_TARGET ) ==0 && - t->verdict <0 && -unconditional (&s->ip)) { + t->verdict <0 ) {/* Tail of chains: STANDARD target (return/policy) */ *comment = *chainname == hookname ? comments[NF_IP_TRACE_COMMENT_POLICY]
@@ -472,11 +472,10 @@ mark_source_chains(const struct xt_table e->comefrom |= ((1 << hook) | (1 <<NF_INET_NUMHOOKS ));/* Unconditional return/END. */ -if ((e->target_offset ==sizeof (struct ipt_entry ) && +if ((unconditional (e) && (strcmp (t->target.u.user.name,XT_STANDARD_TARGET ) ==0 ) && - t->verdict <0 &&unconditional (&e->ip)) || - visited) { + t->verdict <0 ) || visited) {unsigned int oldpos, size; if ((strcmp(t->target.u.user.name,
@@ -703,7 +702,7 @@ static bool check_underflow(const structconst struct xt_entry_target *t;unsigned int verdict; -if (!unconditional (&e->ip)) +if (!unconditional (e))return false; t =ipt_get_target_c (e);if (strcmp (t->u.user.name,XT_STANDARD_TARGET ) !=0 )
@@ -751,9 +750,9 @@ check_entry_size_and_hooks(struct ipt_en newinfo->hook_entry[h] = hook_entries[h];if ((unsigned char *)e - base == underflows[h]) {if (!check_underflow (e)) { -pr_err ("Underflows must be unconditional and " -"use the STANDARD target with " -"ACCEPT/DROP\n" ); +pr_debug ("Underflows must be unconditional and " +"use the STANDARD target with " +"ACCEPT/DROP\n" );return -EINVAL ; } newinfo->underflow[h] = underflows[h];
net/ipv6/netfilter/ip6_tables.c +11 -12
@@ -195,11 +195,12 @@ get_entry(const void *base, unsigned int/* All zeroes == unconditional rule. */ /* Mildly perf critical (only if packet tracing is on) */ -static inline bool unconditional (const struct ip6t_ip6 *ipv6) +static inline bool unconditional (const struct ip6t_entry *e) {static const struct ip6t_ip6 uncond; -return memcmp (ipv6, &uncond,sizeof (uncond)) ==0 ; +return e->target_offset ==sizeof (struct ip6t_entry ) && +memcmp (&e->ipv6, &uncond,sizeof (uncond)) ==0 ; } static inline const struct xt_entry_target *
@@ -255,11 +256,10 @@ get_chainname_rulenum(const struct ip6t_ }else if (s == e) { (*rulenum)++; -if (s->target_offset ==sizeof (struct ip6t_entry ) && +if (unconditional (s) &&strcmp (t->target.u.kernel.target->name,XT_STANDARD_TARGET ) ==0 && - t->verdict <0 && -unconditional (&s->ipv6)) { + t->verdict <0 ) {/* Tail of chains: STANDARD target (return/policy) */ *comment = *chainname == hookname ? comments[NF_IP6_TRACE_COMMENT_POLICY]
@@ -482,11 +482,10 @@ mark_source_chains(const struct xt_table e->comefrom |= ((1 << hook) | (1 <<NF_INET_NUMHOOKS ));/* Unconditional return/END. */ -if ((e->target_offset ==sizeof (struct ip6t_entry ) && +if ((unconditional (e) && (strcmp (t->target.u.user.name,XT_STANDARD_TARGET ) ==0 ) && - t->verdict <0 && -unconditional (&e->ipv6)) || visited) { + t->verdict <0 ) || visited) {unsigned int oldpos, size; if ((strcmp(t->target.u.user.name,
@@ -714,7 +713,7 @@ static bool check_underflow(const structconst struct xt_entry_target *t;unsigned int verdict; -if (!unconditional (&e->ipv6)) +if (!unconditional (e))return false; t =ip6t_get_target_c (e);if (strcmp (t->u.user.name,XT_STANDARD_TARGET ) !=0 )
@@ -762,9 +761,9 @@ check_entry_size_and_hooks(struct ip6t_e newinfo->hook_entry[h] = hook_entries[h];if ((unsigned char *)e - base == underflows[h]) {if (!check_underflow (e)) { -pr_err ("Underflows must be unconditional and " -"use the STANDARD target with " -"ACCEPT/DROP\n" ); +pr_debug ("Underflows must be unconditional and " +"use the STANDARD target with " +"ACCEPT/DROP\n" );return -EINVAL ; } newinfo->underflow[h] = underflows[h];
Greg Kroah-Hartman
maintainerPATCH 18/29 xfs: fix up backport error in fs/xfs/xfs_inode.c
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
Commit c66edeaf79bb6f0ca688ffec9ca50a61b7569984, which was a backport of commit b1438f477934f5a4d5a44df26f3079a7575d5946 upstream, needed to have the error value be positive, not negative, in order to work properly.
--- fs/xfs/xfs_inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/xfs/xfs_inode.c +1 -1
@@ -3098,7 +3098,7 @@ xfs_iflush(*/ error =xfs_imap_to_bp (mp,NULL , &ip->i_imap, &dip, &bp,XBF_TRYLOCK ,0 ); -if (error == -EAGAIN ) { +if (error ==EAGAIN ) {xfs_ifunlock (ip);return error; }
Greg Kroah-Hartman
maintainerPATCH 19/29 pipe: limit the per-user amount of pages allocated in pipes
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willy Tarreau <[email protected]>
commit 759c01142a5d0f364a462346168a56de28a80f52 upstream.
On no-so-small systems, it is possible for a single process to cause an OOM condition by filling large pipes with data that are never read. A typical process filling 4000 pipes with 1 MB of data will use 4 GB of memory. On small systems it may be tricky to set the pipe max size to prevent this from happening.
This patch makes it possible to enforce a per-user soft limit above which new pipes will be limited to a single page, effectively limiting them to 4 kB each, as well as a hard limit above which no new pipes may be created for this user. This has the effect of protecting the system against memory abuse without hurting other users, and still allowing pipes to work correctly though with less data at once.
The limit are controlled by two new sysctls : pipe-user-pages-soft, and pipe-user-pages-hard. Both may be disabled by setting them to zero. The default soft limit allows the default number of FDs per process (1024) to create pipes of the default size (64kB), thus reaching a limit of 64MB before starting to create only smaller pipes. With 256 processes limited to 1024 FDs each, this results in 1024*64kB + (256*1024 - 1024) * 4kB = 1084 MB of memory allocated for a user. The hard limit is disabled by default to avoid breaking existing applications that make intensive use of pipes (eg: for splicing).
Mitigates: CVE-2013-4312 (Linux 2.0+)
--- Documentation/sysctl/fs.txt | 23 +++++++++++++++++++++ fs/pipe.c | 47 ++++++++++++++++++++++++++++++++++++++++++-- include/linux/pipe_fs_i.h | 4 +++ include/linux/sched.h | 1 kernel/sysctl.c | 14 +++++++++++++ 5 files changed, 87 insertions(+), 2 deletions(-)
Documentation/sysctl/fs.txt +23 -0
@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/ - nr_open - overflowuid - overflowgid +- pipe-user-pages-hard +- pipe-user-pages-soft - protected_hardlinks - protected_symlinks - suid_dumpable
@@ -159,6 +161,27 @@ The default is 65534. ============================================================== +pipe-user-pages-hard: + +Maximum total number of pages a non-privileged user may allocate for pipes. +Once this limit is reached, no new pipes may be allocated until usage goes +below the limit again. When set to 0, no limit is applied, which is the default +setting. + +============================================================== + +pipe-user-pages-soft: + +Maximum total number of pages a non-privileged user may allocate for pipes +before the pipe size gets limited to a single page. Once this limit is reached, +new pipes will be limited to a single page in size for this user in order to +limit total memory usage, and trying to increase them using fcntl() will be +denied until usage goes below the limit again. The default value allows to +allocate up to 1024 pipes at their default size. When set to 0, no limit is +applied. + +============================================================== + protected_hardlinks: A long-standing class of security issues is the hardlink-based
fs/pipe.c +45 -2
89 lines not on this page · raw message
include/linux/pipe_fs_i.h +4 -0
@@ -42,6 +42,7 @@ struct pipe_buffer {* @fasync_readers: reader side fasync * @fasync_writers: writer side fasync * @bufs: the circular array of pipe buffers +* @user: the user who created this pipe **/ struct pipe_inode_info {struct mutex mutex;
@@ -57,6 +58,7 @@ struct pipe_inode_info {struct fasync_struct *fasync_readers;struct fasync_struct *fasync_writers;struct pipe_buffer *bufs; +struct user_struct *user; };/*
@@ -140,6 +142,8 @@ void pipe_unlock(struct pipe_inode_infovoid pipe_double_lock (struct pipe_inode_info *,struct pipe_inode_info *);extern unsigned int pipe_max_size, pipe_min_size; +extern unsigned long pipe_user_pages_hard; +extern unsigned long pipe_user_pages_soft;int pipe_proc_fn (struct ctl_table *,int ,void __user *,size_t *,loff_t *);
include/linux/sched.h +1 -0
@@ -756,6 +756,7 @@ struct user_struct {#endif unsigned long locked_shm;/* How many pages of mlocked shm ? */ unsigned long unix_inflight;/* How many files in flight in unix sockets */ +atomic_long_t pipe_bufs;/* how many pages are allocated in pipe buffers */ #ifdef CONFIG_KEYS struct key *uid_keyring;/* UID specific keyring */
kernel/sysctl.c +14 -0
@@ -1668,6 +1668,20 @@ static struct ctl_table fs_table[] = { .proc_handler = &pipe_proc_fn, .extra1 = &pipe_min_size, }, + { + .procname = "pipe-user-pages-hard", + .data = &pipe_user_pages_hard, + .maxlen = sizeof(pipe_user_pages_hard), + .mode = 0644, + .proc_handler = proc_doulongvec_minmax, + }, + { + .procname = "pipe-user-pages-soft", + .data = &pipe_user_pages_soft, + .maxlen = sizeof(pipe_user_pages_soft), + .mode = 0644, + .proc_handler = proc_doulongvec_minmax, + }, { } };
Greg Kroah-Hartman
maintainerPATCH 20/29 netfilter: x_tables: dont move to non-existent next rule
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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.
--- 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(-)
net/ipv4/netfilter/arp_tables.c +5 -3
@@ -435,6 +435,8 @@ static int mark_source_chains(const stru 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 {
@@ -457,6 +459,8 @@ static int mark_source_chains(const stru }else {/* ... this is a fallthru */ newpos = pos + e->next_offset; +if (newpos >= newinfo->size) +return 0 ; } e = (struct arpt_entry *) (entry0 + newpos);
@@ -680,10 +684,8 @@ static int translate_table(struct xt_tab } } -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 ;
net/ipv4/netfilter/ip_tables.c +4 -0
@@ -516,6 +516,8 @@ mark_source_chains(const struct xt_table 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 {
@@ -537,6 +539,8 @@ mark_source_chains(const struct xt_table }else {/* ... this is a fallthru */ newpos = pos + e->next_offset; +if (newpos >= newinfo->size) +return 0 ; } e = (struct ipt_entry *) (entry0 + newpos);
net/ipv6/netfilter/ip6_tables.c +4 -0
@@ -526,6 +526,8 @@ mark_source_chains(const struct xt_table 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 {
@@ -547,6 +549,8 @@ mark_source_chains(const struct xt_table }else {/* ... this is a fallthru */ newpos = pos + e->next_offset; +if (newpos >= newinfo->size) +return 0 ; } e = (struct ip6t_entry *) (entry0 + newpos);
Greg Kroah-Hartman
maintainerPATCH 21/29 netfilter: x_tables: validate targets of jumps
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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
--- net/ipv4/netfilter/arp_tables.c | 16 ++++++++++++++++ net/ipv4/netfilter/ip_tables.c | 16 ++++++++++++++++ net/ipv6/netfilter/ip6_tables.c | 16 ++++++++++++++++ 3 files changed, 48 insertions(+)
net/ipv4/netfilter/arp_tables.c +16 -0
@@ -363,6 +363,18 @@ static inline bool unconditional(const smemcmp (&e->arp, &uncond,sizeof (uncond)) ==0 ; } +static bool find_jump_target (const struct xt_table_info *t, +const struct arpt_entry *target) +{ +struct arpt_entry *iter; + + xt_entry_foreach(iter, t->entries, 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. */
@@ -456,6 +468,10 @@ static int mark_source_chains(const stru/* This a jump; chase it. */ duprintf ("Jump rule %u -> %u\n" , pos, newpos); + e = (struct arpt_entry *) + (entry0 + newpos); +if (!find_jump_target (newinfo, e)) +return 0 ; }else {/* ... this is a fallthru */ newpos = pos + e->next_offset;
net/ipv4/netfilter/ip_tables.c +16 -0
@@ -439,6 +439,18 @@ ipt_do_table(struct sk_buff *skb,#endif } +static bool find_jump_target (const struct xt_table_info *t, +const struct ipt_entry *target) +{ +struct ipt_entry *iter; + + xt_entry_foreach(iter, t->entries, 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
@@ -536,6 +548,10 @@ mark_source_chains(const struct xt_table/* This a jump; chase it. */ duprintf ("Jump rule %u -> %u\n" , pos, newpos); + e = (struct ipt_entry *) + (entry0 + newpos); +if (!find_jump_target (newinfo, e)) +return 0 ; }else {/* ... this is a fallthru */ newpos = pos + e->next_offset;
net/ipv6/netfilter/ip6_tables.c +16 -0
@@ -449,6 +449,18 @@ ip6t_do_table(struct sk_buff *skb,#endif } +static bool find_jump_target (const struct xt_table_info *t, +const struct ip6t_entry *target) +{ +struct ip6t_entry *iter; + + xt_entry_foreach(iter, t->entries, 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
@@ -546,6 +558,10 @@ mark_source_chains(const struct xt_table/* This a jump; chase it. */ duprintf ("Jump rule %u -> %u\n" , pos, newpos); + e = (struct ip6t_entry *) + (entry0 + newpos); +if (!find_jump_target (newinfo, e)) +return 0 ; }else {/* ... this is a fallthru */ newpos = pos + e->next_offset;
Re: [PATCH 3.14 21/29] netfilter: x_tables: validate targets of jumps
Quoted 1 line · Greg Kroah-Hartman
3.14-stable review patch. If anyone has any objections, please let me know.
I have -- this doesn't work in 3.14 as t->entries (the ruleset blob) is still kept percpu.
net/ipv4/netfilter/arp_tables.c static inline bool unconditional(const s · line 371
Quoted 6 lines
net/ipv4/netfilter/arp_tables.c +6
-0+static bool find_jump_target (const struct xt_table_info *t, +const struct arpt_entry *target) +{ +struct arpt_entry *iter; + + xt_entry_foreach(iter, t->entries, t->size) {
.. so this causes in kernel soft lockup when I try to insert a rule.
I will go over the 3.14 stable queue and see if I can amend this to work with 3.14.
Re: [PATCH 3.14 21/29] netfilter: x_tables: validate targets of jumps
Quoted 16 lines · Florian Westphal
Quoted 1 line · Greg Kroah-Hartman
3.14-stable review patch. If anyone has any objections, please let me know.
I have -- this doesn't work in 3.14 as
t->entries(the ruleset blob) is still kept percpu.Review
Quoted 6 lines
(quoted diff) +6
-0+static bool find_jump_target(const struct xt_table_info *t, + const struct arpt_entry *target) +{ + struct arpt_entry *iter; + + xt_entry_foreach(iter, t->entries, t->size) {.. so this causes in kernel soft lockup when I try to insert a rule.
Quoted 2 lines
I will go over the 3.14 stable queue and see if I can amend this to work with 3.14.
This amended patch works for me (iptables-test.py passes except those tests that I expected to fail due to some missing features in 3.14).
I also briefly tried 32bit iptables/ip6tables and that seems happy as well. The reproduces for the two bugs fail with -EINVAL.
ebtables doesn't work (even ebtables -A INPUT -j ACCEPT fails), but that should be solved by picking up d26e2c9ffa385dd1b646f43c1397ba12af9e, "Revert "netfilter: ensure number of counters is >0 in do_replace()" [ its a PARTIAL revert, so don't drop the original patch ... ]
Subject: netfilter: x_tables: validate targets of jumps
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
---
Need to pass the start of the ruleset as extra argument as t->entries won't work in 3.14 (its percpu and not even set up for all processors at this point).
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(+)
net/ipv4/netfilter/arp_tables.c +17 -0
@@ -363,6 +363,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. */
@@ -456,6 +469,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;
net/ipv4/netfilter/ip_tables.c +17 -0
@@ -439,6 +439,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
@@ -536,6 +549,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;
net/ipv6/netfilter/ip6_tables.c +17 -0
@@ -449,6 +449,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
@@ -546,6 +559,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;
Signature · 1 line
2.7.3
Greg Kroah-Hartman
maintainerRe: [PATCH 3.14 21/29] netfilter: x_tables: validate targets of jumps
Quoted 54 lines · Florian Westphal
Quoted 16 lines · Florian Westphal
Quoted 1 line · Greg Kroah-Hartman
3.14-stable review patch. If anyone has any objections, please let me know.
I have -- this doesn't work in 3.14 as
t->entries(the ruleset blob) is still kept percpu.net/ipv4/netfilter/arp_tables.c static inline bool unconditional(const struct arpt_entry *e)
Quoted 6 lines
net/ipv4/netfilter/arp_tables.c +6
-0+static bool find_jump_target (const struct xt_table_info *t, +const struct arpt_entry *target) +{ +struct arpt_entry *iter; + + xt_entry_foreach(iter, t->entries, t->size) {.. so this causes in kernel soft lockup when I try to insert a rule.
Quoted 2 lines
I will go over the 3.14 stable queue and see if I can amend this to work with 3.14.
This amended patch works for me (
iptables-test.pypasses except those tests that I expected to fail due to some missing features in 3.14).I also briefly tried 32bit iptables/ip6tables and that seems happy as well. The reproduces for the two bugs fail with
-EINVAL.ebtables doesn't work (even ebtables -A INPUT -j ACCEPT fails), but that should be solved by picking up
d26e2c9ffa385dd1b646f43c1397ba12af9e, "Revert "netfilter: ensure number of counters is >0 indo_replace()" [ its a PARTIAL revert, so don't drop the original patch ... ]Subject: netfilter:
x_tables: validate targets of jumpscommit
36472341017529e2b12573093cc0f68719300997upstream.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.076sAfter:
real 0m27.464s user 0m7.436s sys 0m18.840s
Quoted 7 lines
Signed-off-by Florian Westphal <[email protected]>Signed-off-by Pablo Neira Ayuso <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>---
Need to pass the start of the ruleset as extra argument ast->entrieswon't work in 3.14 (its percpu and not even set up for all processors at this point).
Thank you for the update, now applied.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 22/29 netfilter: x_tables: add and use xt_check_entry_offsets
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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.
--- 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(-)
include/linux/netfilter/x_tables.h +4 -0
@@ -239,6 +239,10 @@ void xt_unregister_match(struct xt_matchint xt_register_matches (struct xt_match *match,unsigned int n);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); +int xt_check_match (struct xt_mtchk_param *,unsigned int size,u_int8_t proto,bool inv_proto); int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto,
net/ipv4/netfilter/arp_tables.c +1 -10
@@ -492,19 +492,10 @@ static int mark_source_chains(const strustatic 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)
net/ipv4/netfilter/ip_tables.c +1 -11
@@ -586,20 +586,10 @@ static void cleanup_match(struct xt_entrstatic 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
net/ipv6/netfilter/ip6_tables.c +1 -11
@@ -596,20 +596,10 @@ static void cleanup_match(struct xt_entrstatic 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)
net/netfilter/x_tables.c +34 -0
@@ -560,6 +560,40 @@ int xt_compat_match_to_user(const structEXPORT_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) {
Greg Kroah-Hartman
maintainerPATCH 23/29 netfilter: x_tables: kill check_entry helper
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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.
--- 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(-)
net/ipv4/netfilter/arp_tables.c +8 -11
@@ -490,14 +490,6 @@ static int mark_source_chains(const strureturn 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);
@@ -587,7 +579,10 @@ static inline int check_entry_size_and_hreturn -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;
@@ -1246,8 +1241,10 @@ check_compat_entry_size_and_hooks(structreturn -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;
net/ipv4/netfilter/ip_tables.c +8 -12
@@ -584,15 +584,6 @@ static void cleanup_match(struct xt_entr }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;
@@ -748,7 +739,10 @@ check_entry_size_and_hooks(struct ipt_enreturn -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;
@@ -1512,8 +1506,10 @@ check_compat_entry_size_and_hooks(structreturn -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;
net/ipv6/netfilter/ip6_tables.c +8 -12
@@ -593,15 +593,6 @@ static void cleanup_match(struct xt_entrmodule_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;
@@ -759,7 +750,10 @@ check_entry_size_and_hooks(struct ip6t_ereturn -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;
@@ -1524,8 +1518,10 @@ check_compat_entry_size_and_hooks(structreturn -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;
Greg Kroah-Hartman
maintainerPATCH 24/29 netfilter: x_tables: assert minimum target size
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit a08e4e190b866579896c09af59b3bdca821da2cd upstream.
The target size includes the size of the xt_entry_target struct.
--- net/netfilter/x_tables.c | 3 +++ 1 file changed, 3 insertions(+)
net/netfilter/x_tables.c +3 -0
@@ -587,6 +587,9 @@ int xt_check_entry_offsets(const void *breturn -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 ;
Greg Kroah-Hartman
maintainerPATCH 25/29 netfilter: x_tables: add compat version of xt_check_entry_offsets
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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.
--- 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(-)
include/linux/netfilter/x_tables.h +3 -0
@@ -435,6 +435,9 @@ void xt_compat_target_from_user(struct x unsigned int *size);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 */
net/ipv4/netfilter/arp_tables.c +2 -1
@@ -1244,7 +1244,8 @@ check_compat_entry_size_and_hooks(structif (!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;
net/ipv4/netfilter/ip_tables.c +2 -1
@@ -1509,7 +1509,8 @@ check_compat_entry_size_and_hooks(structif (!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;
net/ipv6/netfilter/ip6_tables.c +2 -1
@@ -1521,7 +1521,8 @@ check_compat_entry_size_and_hooks(structif (!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;
net/netfilter/x_tables.c +22 -0
@@ -558,6 +558,27 @@ int xt_compat_match_to_user(const struct 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_use* @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
Greg Kroah-Hartman
maintainerPATCH 26/29 netfilter: x_tables: check standard target size too
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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.
--- net/netfilter/x_tables.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
net/netfilter/x_tables.c +15 -0
@@ -559,6 +559,13 @@ int xt_compat_match_to_user(const struct }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(constif (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 *bif (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);
Greg Kroah-Hartman
maintainerPATCH 27/29 netfilter: x_tables: check for bogus target offset
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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.
--- 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(-)
include/linux/netfilter/x_tables.h +2 -2
@@ -239,7 +239,7 @@ void xt_unregister_match(struct xt_matchint xt_register_matches (struct xt_match *match,unsigned int n);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);
@@ -435,7 +435,7 @@ void xt_compat_target_from_user(struct x unsigned int *size);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);
net/ipv4/netfilter/arp_tables.c +3 -2
@@ -582,7 +582,8 @@ static inline int check_entry_size_and_hif (!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;
@@ -1244,7 +1245,7 @@ check_compat_entry_size_and_hooks(structif (!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;
net/ipv4/netfilter/ip_tables.c +3 -2
@@ -742,7 +742,8 @@ check_entry_size_and_hooks(struct ipt_enif (!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;
@@ -1509,7 +1510,7 @@ check_compat_entry_size_and_hooks(structif (!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;
net/ipv6/netfilter/ip6_tables.c +3 -2
@@ -753,7 +753,8 @@ check_entry_size_and_hooks(struct ip6t_eif (!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;
@@ -1521,7 +1522,7 @@ check_compat_entry_size_and_hooks(structif (!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;
net/netfilter/x_tables.c +15 -2
@@ -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_offs* 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_offs* 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 ;
Greg Kroah-Hartman
maintainerPATCH 28/29 netfilter: x_tables: validate all offsets and sizes in a rule
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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.
--- net/netfilter/x_tables.c | 81 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-)
net/netfilter/x_tables.c +76 -5
@@ -435,6 +435,47 @@ int xt_check_match(struct xt_mtchk_param }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 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_offs* @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 *b 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);
Greg Kroah-Hartman
maintainerPATCH 29/29 netfilter: x_tables: dont reject valid target size on some architectures
In reply to Greg Kroah-Hartman3.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
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.
--- net/netfilter/x_tables.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/x_tables.c +2 -2
@@ -628,7 +628,7 @@ int xt_compat_check_entry_offsets(constreturn -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 *breturn -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,
Greg Kroah-Hartman
maintainerRe: [PATCH 3.14 00/29] 3.14.73-stable review -rc2
In reply to Greg Kroah-Hartman-rc2!
Please test this...
This is the start of the stable review cycle for the 3.14.73 release. There are 35 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat Jun 25 04:50:44 UTC 2016. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v3.x/stable-review/patch-3.14.73-rc2.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-3.14.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 3.14.73-rc2
Florian Westphal <[email protected]>
netfilter: x_tables: do compat validation via translate_table
Dave Jones <[email protected]>
netfilter: ensure number of counters is >0 in do_replace()
Florian Westphal <[email protected]>
netfilter: x_tables: xt_compat_match_from_user doesn't need a retval
Florian Westphal <[email protected]>
netfilter: ip6_tables: simplify translate_compat_table args
Florian Westphal <[email protected]>
netfilter: ip_tables: simplify translate_compat_table args
Florian Westphal <[email protected]>
netfilter: arp_tables: simplify translate_compat_table args
Florian Westphal <[email protected]>
netfilter: x_tables: don't reject valid target size on some architectures
Florian Westphal <[email protected]>
netfilter: x_tables: validate all offsets and sizes in a rule
Florian Westphal <[email protected]>
netfilter: x_tables: check for bogus target offset
Florian Westphal <[email protected]>
netfilter: x_tables: check standard target size too
Florian Westphal <[email protected]>
netfilter: x_tables: add compat version of xt_check_entry_offsets
Florian Westphal <[email protected]>
netfilter: x_tables: assert minimum target size
Florian Westphal <[email protected]>
netfilter: x_tables: kill check_entry helper
Florian Westphal <[email protected]>
netfilter: x_tables: add and use xt_check_entry_offsets
Florian Westphal <[email protected]>
netfilter: x_tables: validate targets of jumps
Florian Westphal <[email protected]>
netfilter: x_tables: don't move to non-existent next rule
Willy Tarreau <[email protected]>
pipe: limit the per-user amount of pages allocated in pipes
Greg Kroah-Hartman <[email protected]>
xfs: fix up backport error in fs/xfs/xfs_inode.c
Florian Westphal <[email protected]>
netfilter: x_tables: fix unconditional helper
Florian Westphal <[email protected]>
netfilter: x_tables: make sure e->next_offset covers remaining blob size
Florian Westphal <[email protected]>
netfilter: x_tables: validate e->target_offset early
Russell Currey <[email protected]>
powerpc/pseries/eeh: Handle RTAS delay requests in configure_bridge
Ralf Baechle <[email protected]>
MIPS: Fix 64k page support for 32 bit kernels.
Al Viro <[email protected]>
fix d_walk()/non-delayed __d_free() race
Prasun Maiti <[email protected]>
wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel
Jann Horn <[email protected]>
ecryptfs: forbid opening files without mmap handler
Helge Deller <[email protected]>
parisc: Fix pagefault crash in unaligned __get_user() call
Thomas Huth <[email protected]>
powerpc: Use privileged SPR number for MMCR2
Thomas Huth <[email protected]>
powerpc: Fix definition of SIAR and SDAR registers
Tom Lendacky <[email protected]>
crypto: ccp - Fix AES XTS error for request sizes above 4096
Russell King <[email protected]>
ARM: fix PTRACE_SETVFPREGS on SMP systems
Paolo Bonzini <[email protected]>
KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS
Yuchung Cheng <[email protected]>
tcp: record TLP and ER timer stats in v6 stats
Edward Cree <[email protected]>
sfc: on MC reset, clear PIO buffer linkage in TXQs
Herbert Xu <[email protected]>
netlink: Fix dump skb leak/double free
-------------
Diffstat:
Documentation/sysctl/fs.txt | 23 ++ Makefile | 4 +- arch/arm/kernel/ptrace.c | 2 +- arch/mips/include/asm/processor.h | 2 +- arch/parisc/kernel/unaligned.c | 10 +- arch/powerpc/include/asm/reg.h | 6 +- arch/powerpc/platforms/pseries/eeh_pseries.c | 51 +++-- arch/x86/kvm/x86.c | 5 + drivers/crypto/ccp/ccp-crypto-aes-xts.c | 17 +- drivers/net/ethernet/sfc/ef10.c | 16 ++ fs/dcache.c | 4 +- fs/ecryptfs/kthread.c | 13 +- fs/pipe.c | 47 +++- fs/xfs/xfs_inode.c | 2 +- include/linux/netfilter/x_tables.h | 9 +- include/linux/pipe_fs_i.h | 4 + include/linux/sched.h | 1 + kernel/sysctl.c | 14 ++ net/bridge/netfilter/ebtables.c | 4 + net/ipv4/netfilter/arp_tables.c | 279 +++++++++--------------- net/ipv4/netfilter/ip_tables.c | 312 +++++++++------------------ net/ipv6/netfilter/ip6_tables.c | 305 +++++++++----------------- net/ipv6/tcp_ipv6.c | 4 +- net/netfilter/x_tables.c | 171 ++++++++++++++- net/netlink/af_netlink.c | 7 +- net/wireless/wext-core.c | 25 ++- 26 files changed, 708 insertions(+), 629 deletions(-)
Re: [PATCH 3.14 00/29] 3.14.73-stable review -rc2
Quoted 4 lines · Greg Kroah-Hartman
-rc2!
Please test this...
Quoted 8 lines
This is the start of the stable review cycle for the 3.14.73 release. There are 35 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat Jun 25 04:50:44 UTC 2016. Anything received after that time might be too late.
Build results:
total: 131 pass: 131 fail: 0 Qemu test results: total: 89 pass: 89 fail: 0
Details are available at http://kerneltests.org/builders.
Guenter
Re: [PATCH 3.14 00/29] 3.14.73-stable review -rc2
In reply to Greg Kroah-HartmanQuoted 9 lines · Greg Kroah-Hartman
-rc2!
Please test this...
This is the start of the stable review cycle for the 3.14.73 release. There are 35 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Quoted 9 lines
Responses should be made by Sat Jun 25 04:50:44 UTC 2016. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v3.x/stable-review/patch-3.14.73-rc2.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-3.14.y
and the diffstat can be found below.
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah