Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1467049 > unrolled thread
| Started by | Willy Tarreau <w@1wt.eu> |
|---|---|
| First post | 2016-08-21 17:40 +0200 |
| Last post | 2016-08-21 18:20 +0200 |
| Articles | 20 on this page of 141 — 4 participants |
Back to article view | Back to linux.kernel
[PATCH 3.10 000/180] 3.10.103-stable review Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 036/180] usb: renesas_usbhs: protect the CFIFOSEL setting in usbhsg_ep_enable() Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 028/180] udp: properly support MSG_PEEK with truncated buffers Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 017/180] netfilter: ip_tables: simplify translate_compat_table args Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 132/180] ALSA: timer: Fix leak in SNDRV_TIMER_IOCTL_PARAMS Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 053/180] MIPS: KVM: Propagate kseg0/mapped tlb fault errors Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 008/180] netfilter: x_tables: add and use xt_check_entry_offsets Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 135/180] scsi: fix race between simultaneous decrements of ->host_failed Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 131/180] ALSA: ctl: Stop notification after disconnection Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 178/180] isdn: hfcpci_softirq: get func return to suppress compiler warning Willy Tarreau <w@1wt.eu> - 2016-08-21 17:40 +0200
[PATCH 3.10 177/180] net: rfkill: Do not ignore errors from regulator_enable() Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 145/180] ARC: use ASL assembler mnemonic Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 093/180] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 153/180] x86/mm: Improve switch_mm() barrier comments Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 061/180] Input: xpad - validate USB endpoint count during probe Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 104/180] sit: correct IP protocol used in ipip6_err Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 162/180] s5p-mfc: Add release callback for memory region devs Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 126/180] iio:ad7266: Fix broken regulator error handling Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 049/180] tcp: consider recv buf for the initial window scale Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 127/180] iio:ad7266: Fix probe deferral for vref Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 054/180] MIPS: math-emu: Fix jalr emulation when rd == $0 Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 173/180] be2iscsi: Fix bogus WARN_ON length check Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 020/180] netfilter: ensure number of counters is >0 in do_replace() Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 109/180] IB/mlx4: Properly initialize GRH TClass and FlowLabel in AHs Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 019/180] netfilter: x_tables: xt_compat_match_from_user doesn't need a retval Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 165/180] netlabel: add address family checks to netlbl_{sock,req}_delattr() Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 039/180] cdc_ncm: do not call usbnet_link_change from cdc_ncm_bind Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 055/180] MIPS: Fix siginfo.h to use strict posix types Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 071/180] powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 174/180] squash mm: Export migrate_page_... : also make it non-static Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 026/180] signal: remove warning about using SI_TKILL in rt_[tg]sigqueueinfo Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 129/180] ALSA: dummy: Fix a use-after-free at closing Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 009/180] netfilter: x_tables: kill check_entry helper Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 158/180] net/irda: fix NULL pointer dereference on memory allocation failure Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 015/180] netfilter: x_tables: don't reject valid target size on some architectures Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 058/180] MIPS: KVM: Fix modular KVM under QEMU Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 113/180] x86, build: copy ldlinux.c32 to image.iso Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 112/180] IB/mlx4: Fix the SQ size of an RC QP Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 095/180] arm: oabi compat: add missing access checks Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 096/180] parisc: Fix pagefault crash in unaligned __get_user() call Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 059/180] Input: uinput - handle compat ioctl for UI_SET_PHYS Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 064/180] aacraid: Fix for aac_command_thread hang Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 124/180] staging: iio: accel: fix error check Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 052/180] MIPS: KVM: Fix gfn range check in kseg0 tlb faults Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 012/180] netfilter: x_tables: check standard target size too Willy Tarreau <w@1wt.eu> - 2016-08-21 17:50 +0200
[PATCH 3.10 176/180] ALSA: oxygen: Fix logical-not-parentheses warning Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 111/180] IB/IPoIB: Don't update neigh validity for unresolved entries Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 163/180] Bluetooth: Fix l2cap_sock_setsockopt() with optname BT_RCVMTU Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 094/180] ARM: fix PTRACE_SETVFPREGS on SMP systems Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 024/180] perf/x86: Honor the architectural performance monitoring version Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 130/180] ALSA: au88x0: Fix calculation in vortex_wtdma_bufshift() Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 141/180] arc: unwind: warn only once if DW2_UNWIND is disabled Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 092/180] xfs: skip stale inodes in xfs_iflush_cluster Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 050/180] MIPS: KVM: Fix mapped fault broken commpage handling Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 128/180] tty/vt/keyboard: fix OOB access in do_compute_shiftstate() Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 161/180] s5p-mfc: Set device name for reserved memory region devs Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 140/180] fs/nilfs2: fix potential underflow in call to crc32_le Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 068/180] powerpc: Fix definition of SIAR and SDAR registers Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 078/180] drm/radeon: add a delay after ATPX dGPU power off Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 018/180] netfilter: ip6_tables: simplify translate_compat_table args Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 136/180] scsi: remove scsi_end_request Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 152/180] sctp: Prevent soft lockup when sctp_accept() is called during a timeout event Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 062/180] ath5k: Change led pin configuration for compaq c700 laptop Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 100/180] xfs: fix up backport error in fs/xfs/xfs_inode.c Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 076/180] drm/fb_helper: Fix references to dev->mode_config.num_connector Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 099/180] fix d_walk()/non-delayed __d_free() race Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 156/180] block: fix use-after-free in seq file Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 121/180] tracing: Handle NULL formats in hold_module_trace_bprintk_format() Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 066/180] rtlwifi: Fix logic error in enter/exit power-save mode Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 167/180] ftrace/recordmcount: Work around for addition of metag magic but not relocations Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 149/180] can: fix oops caused by wrong rtnl dellink usage Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 037/180] x86/mm: Add barriers and document switch_mm()-vs-flush synchronization Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 134/180] ALSA: timer: Fix leak in events via snd_timer_user_tinterrupt Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 098/180] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
Re: [PATCH 3.10 098/180] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel Johannes Berg <johannes@sipsolutions.net> - 2016-08-22 07:40 +0200
Re: [PATCH 3.10 098/180] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel Willy Tarreau <w@1wt.eu> - 2016-08-22 07:50 +0200
[PATCH 3.10 044/180] libceph: apply new_state before new_up_client on incrementals Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 045/180] tmpfs: don't undo fallocate past its last page Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 168/180] metag: Fix __cmpxchg_u32 asm constraint for CMP Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 046/180] tmpfs: fix regression hang in fallocate undo Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 075/180] drm/gma500: Fix possible out of bounds read Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 169/180] ubi: Make volume resize power cut aware Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 179/180] stb6100: fix buffer length check in stb6100_write_reg_range() Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 089/180] dma-debug: avoid spinlock recursion when disabling dma-debug Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 139/180] s390/seccomp: fix error return for filtered system calls Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 103/180] crypto: scatterwalk - Fix test in scatterwalk_done Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 147/180] mmc: block: fix packed command header endianness Willy Tarreau <w@1wt.eu> - 2016-08-21 18:00 +0200
[PATCH 3.10 102/180] crypto: gcm - Filter out async ghash if necessary Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 142/180] xen/pciback: Fix conf_space read/write overlap check. Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 090/180] xfs: xfs_iflush_cluster fails to abort on error Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
Re: [PATCH 3.10 090/180] xfs: xfs_iflush_cluster fails to abort on error Dave Chinner <david@fromorbit.com> - 2016-08-22 06:30 +0200
Re: [PATCH 3.10 090/180] xfs: xfs_iflush_cluster fails to abort on error Willy Tarreau <w@1wt.eu> - 2016-08-22 07:20 +0200
Re: [PATCH 3.10 090/180] xfs: xfs_iflush_cluster fails to abort on error Willy Tarreau <w@1wt.eu> - 2016-08-22 07:30 +0200
Re: [PATCH 3.10 090/180] xfs: xfs_iflush_cluster fails to abort on error Dave Chinner <dchinner@redhat.com> - 2016-08-22 13:00 +0200
Re: [PATCH 3.10 090/180] xfs: xfs_iflush_cluster fails to abort on error Willy Tarreau <w@1wt.eu> - 2016-08-22 13:10 +0200
[PATCH 3.10 003/180] netfilter: x_tables: validate e->target_offset early Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 025/180] perf/x86: Fix undefined shift on 32-bit kernels Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 164/180] cifs: Check for existing directory when opening file with O_CREAT Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 091/180] xfs: fix inode validity check in xfs_iflush_cluster Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 038/180] pipe: limit the per-user amount of pages allocated in pipes Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 118/180] UBIFS: Implement ->migratepage() Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 175/180] HID: hid-input: Add parentheses to quell gcc warning Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 065/180] PCI: Disable all BAR sizing for devices with non-compliant BARs Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 144/180] ecryptfs: don't allow mmap when the lower fs doesn't support it Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 043/180] HID: hiddev: validate num_values for HIDIOCGUSAGES, HIDIOCSUSAGES commands Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 067/180] powerpc/book3s64: Fix branching to OOL handlers in relocatable kernel Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 157/180] fuse: fix wrong assignment of ->flags in fuse_send_init() Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 023/180] netfilter: x_tables: introduce and use xt_copy_counters_from_user Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 011/180] netfilter: x_tables: add compat version of xt_check_entry_offsets Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 122/180] base: make module_create_drivers_dir race-free Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 087/180] ext4: short-cut orphan cleanup on error Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 125/180] iio: accel: kxsd9: fix the usage of spi_w8r8() Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 070/180] powerpc/pseries/eeh: Handle RTAS delay requests in configure_bridge Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 107/180] mac80211: mesh: flush mesh paths unconditionally Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 138/180] xen/acpi: allow xen-acpi-processor driver to load on Xen 4.7 Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 119/180] cdc_ncm: workaround for EM7455 "silent" data interface Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 106/180] net: alx: Work around the DMA RX overflow issue Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 032/180] USB: EHCI: declare hostpc register as zero-length array Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 031/180] USB: fix up faulty backports Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 150/180] ipr: Clear interrupt on croc/crocodile when running with LSI Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 041/180] mm: migrate dirty page without clear_page_dirty_for_io etc Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 116/180] NFS: Fix another OPEN_DOWNGRADE bug Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 069/180] powerpc: Use privileged SPR number for MMCR2 Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 085/180] ext4: check for extents that wrap around Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 072/180] powerpc/pseries: Fix PCI config address for DDW Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 110/180] IB/security: Restrict use of the write() interface Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 133/180] ALSA: timer: Fix leak in events via snd_timer_user_ccallback Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 123/180] iio: Fix error handling in iio_trigger_attach_poll_func Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 172/180] module: Invalidate signatures on force-loaded modules Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 160/180] hp-wmi: Fix wifi cannot be hard-unblocked Willy Tarreau <w@1wt.eu> - 2016-08-21 18:10 +0200
[PATCH 3.10 004/180] netfilter: x_tables: make sure e->next_offset covers remaining blob size Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 042/180] printk: do cond_resched() between lines while outputting to consoles Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 001/180] X.509: remove possible code fragility: enumeration values not handled Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 097/180] ecryptfs: forbid opening files without mmap handler Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 021/180] netfilter: x_tables: do compat validation via translate_table Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 030/180] USB: usbfs: fix potential infoleak in devio Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 040/180] KEYS: potential uninitialized variable Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 034/180] usb: musb: Stop bulk endpoint while queue is rotated Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 005/180] netfilter: x_tables: fix unconditional helper Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 014/180] netfilter: x_tables: validate all offsets and sizes in a rule Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
[PATCH 3.10 022/180] Revert "netfilter: ensure number of counters is >0 in do_replace()" Willy Tarreau <w@1wt.eu> - 2016-08-21 18:20 +0200
Page 7 of 8 — ← Prev page 1 2 3 4 5 6 [7] 8 Next page →
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 041/180] mm: migrate dirty page without clear_page_dirty_for_io etc |
| Message-ID | <s8DtV-2yc-85@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Hugh Dickins <hughd@google.com>
commit 42cb14b110a5698ccf26ce59c4441722605a3743 upstream.
clear_page_dirty_for_io() has accumulated writeback and memcg subtleties
since v2.6.16 first introduced page migration; and the set_page_dirty()
which completed its migration of PageDirty, later had to be moderated to
__set_page_dirty_nobuffers(); then PageSwapBacked had to skip that too.
No actual problems seen with this procedure recently, but if you look into
what the clear_page_dirty_for_io(page)+set_page_dirty(newpage) is actually
achieving, it turns out to be nothing more than moving the PageDirty flag,
and its NR_FILE_DIRTY stat from one zone to another.
It would be good to avoid a pile of irrelevant decrementations and
incrementations, and improper event counting, and unnecessary descent of
the radix_tree under tree_lock (to set the PAGECACHE_TAG_DIRTY which
radix_tree_replace_slot() left in place anyway).
Do the NR_FILE_DIRTY movement, like the other stats movements, while
interrupts still disabled in migrate_page_move_mapping(); and don't even
bother if the zone is the same. Do the PageDirty movement there under
tree_lock too, where old page is frozen and newpage not yet visible:
bearing in mind that as soon as newpage becomes visible in radix_tree, an
un-page-locked set_page_dirty() might interfere (or perhaps that's just
not possible: anything doing so should already hold an additional
reference to the old page, preventing its migration; but play safe).
But we do still need to transfer PageDirty in migrate_page_copy(), for
those who don't go the mapping route through migrate_page_move_mapping().
CVE-2016-3070
Signed-off-by: Hugh Dickins <hughd@google.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[ciwillia@brocade.com: backported to 3.10: adjusted context]
Signed-off-by: Charles (Chas) Williams <ciwillia@brocade.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
mm/migrate.c | 51 +++++++++++++++++++++++++++++++--------------------
1 file changed, 31 insertions(+), 20 deletions(-)
diff --git a/mm/migrate.c b/mm/migrate.c
index a88c12f..a61500f 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -30,6 +30,7 @@
#include <linux/mempolicy.h>
#include <linux/vmalloc.h>
#include <linux/security.h>
+#include <linux/backing-dev.h>
#include <linux/memcontrol.h>
#include <linux/syscalls.h>
#include <linux/hugetlb.h>
@@ -311,6 +312,8 @@ static int migrate_page_move_mapping(struct address_space *mapping,
struct page *newpage, struct page *page,
struct buffer_head *head, enum migrate_mode mode)
{
+ struct zone *oldzone, *newzone;
+ int dirty;
int expected_count = 0;
void **pslot;
@@ -321,6 +324,9 @@ static int migrate_page_move_mapping(struct address_space *mapping,
return MIGRATEPAGE_SUCCESS;
}
+ oldzone = page_zone(page);
+ newzone = page_zone(newpage);
+
spin_lock_irq(&mapping->tree_lock);
pslot = radix_tree_lookup_slot(&mapping->page_tree,
@@ -361,6 +367,13 @@ static int migrate_page_move_mapping(struct address_space *mapping,
set_page_private(newpage, page_private(page));
}
+ /* Move dirty while page refs frozen and newpage not yet exposed */
+ dirty = PageDirty(page);
+ if (dirty) {
+ ClearPageDirty(page);
+ SetPageDirty(newpage);
+ }
+
radix_tree_replace_slot(pslot, newpage);
/*
@@ -370,6 +383,9 @@ static int migrate_page_move_mapping(struct address_space *mapping,
*/
page_unfreeze_refs(page, expected_count - 1);
+ spin_unlock(&mapping->tree_lock);
+ /* Leave irq disabled to prevent preemption while updating stats */
+
/*
* If moved to a different zone then also account
* the page for that zone. Other VM counters will be
@@ -380,13 +396,19 @@ static int migrate_page_move_mapping(struct address_space *mapping,
* via NR_FILE_PAGES and NR_ANON_PAGES if they
* are mapped to swap space.
*/
- __dec_zone_page_state(page, NR_FILE_PAGES);
- __inc_zone_page_state(newpage, NR_FILE_PAGES);
- if (!PageSwapCache(page) && PageSwapBacked(page)) {
- __dec_zone_page_state(page, NR_SHMEM);
- __inc_zone_page_state(newpage, NR_SHMEM);
+ if (newzone != oldzone) {
+ __dec_zone_state(oldzone, NR_FILE_PAGES);
+ __inc_zone_state(newzone, NR_FILE_PAGES);
+ if (PageSwapBacked(page) && !PageSwapCache(page)) {
+ __dec_zone_state(oldzone, NR_SHMEM);
+ __inc_zone_state(newzone, NR_SHMEM);
+ }
+ if (dirty && mapping_cap_account_dirty(mapping)) {
+ __dec_zone_state(oldzone, NR_FILE_DIRTY);
+ __inc_zone_state(newzone, NR_FILE_DIRTY);
+ }
}
- spin_unlock_irq(&mapping->tree_lock);
+ local_irq_enable();
return MIGRATEPAGE_SUCCESS;
}
@@ -460,20 +482,9 @@ void migrate_page_copy(struct page *newpage, struct page *page)
if (PageMappedToDisk(page))
SetPageMappedToDisk(newpage);
- if (PageDirty(page)) {
- clear_page_dirty_for_io(page);
- /*
- * Want to mark the page and the radix tree as dirty, and
- * redo the accounting that clear_page_dirty_for_io undid,
- * but we can't use set_page_dirty because that function
- * is actually a signal that all of the page has become dirty.
- * Whereas only part of our page may be dirty.
- */
- if (PageSwapBacked(page))
- SetPageDirty(newpage);
- else
- __set_page_dirty_nobuffers(newpage);
- }
+ /* Move dirty on pages not done by migrate_page_move_mapping() */
+ if (PageDirty(page))
+ SetPageDirty(newpage);
mlock_migrate_page(newpage, page);
ksm_migrate_page(newpage, page);
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 116/180] NFS: Fix another OPEN_DOWNGRADE bug |
| Message-ID | <s8DtV-2yc-73@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Trond Myklebust <trond.myklebust@primarydata.com>
commit e547f2628327fec6afd2e03b46f113f614cca05b upstream.
Olga Kornievskaia reports that the following test fails to trigger
an OPEN_DOWNGRADE on the wire, and only triggers the final CLOSE.
fd0 = open(foo, RDRW) -- should be open on the wire for "both"
fd1 = open(foo, RDONLY) -- should be open on the wire for "read"
close(fd0) -- should trigger an open_downgrade
read(fd1)
close(fd1)
The issue is that we're missing a check for whether or not the current
state transitioned from an O_RDWR state as opposed to having transitioned
from a combination of O_RDONLY and O_WRONLY.
Reported-by: Olga Kornievskaia <aglo@umich.edu>
Fixes: cd9288ffaea4 ("NFSv4: Fix another bug in the close/open_downgrade code")
Cc: stable@vger.kernel.org # 2.6.33+
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
fs/nfs/nfs4proc.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d8ac734..c2b89a1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2332,12 +2332,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
call_close |= is_wronly;
else if (is_wronly)
calldata->arg.fmode |= FMODE_WRITE;
+ if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
+ call_close |= is_rdwr;
} else if (is_rdwr)
calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
- if (calldata->arg.fmode == 0)
- call_close |= is_rdwr;
-
if (!nfs4_valid_open_stateid(state))
call_close = 0;
spin_unlock(&state->owner->so_lock);
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 069/180] powerpc: Use privileged SPR number for MMCR2 |
| Message-ID | <s8DtV-2yc-75@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Thomas Huth <thuth@redhat.com>
commit 8dd75ccb571f3c92c48014b3dabd3d51a115ab41 upstream.
We are already using the privileged versions of MMCR0, MMCR1
and MMCRA in the kernel, so for MMCR2, we should better use
the privileged versions, too, to be consistent.
Fixes: 240686c13687 ("powerpc: Initialise PMU related regs on Power8")
Suggested-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Acked-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
arch/powerpc/include/asm/reg.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index d2a6651..469d771 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -643,7 +643,7 @@
#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
#define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */
#define SPRN_MMCR1 798
-#define SPRN_MMCR2 769
+#define SPRN_MMCR2 785
#define SPRN_MMCRA 0x312
#define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
#define MMCRA_SDAR_DCACHE_MISS 0x40000000UL
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 085/180] ext4: check for extents that wrap around |
| Message-ID | <s8DtV-2yc-69@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Vegard Nossum <vegard.nossum@oracle.com>
commit f70749ca42943faa4d4dcce46dfdcaadb1d0c4b6 upstream.
An extent with lblock = 4294967295 and len = 1 will pass the
ext4_valid_extent() test:
ext4_lblk_t last = lblock + len - 1;
if (len == 0 || lblock > last)
return 0;
since last = 4294967295 + 1 - 1 = 4294967295. This would later trigger
the BUG_ON(es->es_lblk + es->es_len < es->es_lblk) in ext4_es_end().
We can simplify it by removing the - 1 altogether and changing the test
to use lblock + len <= lblock, since now if len = 0, then lblock + 0 ==
lblock and it fails, and if len > 0 then lblock + len > lblock in order
to pass (i.e. it doesn't overflow).
Fixes: 5946d0893 ("ext4: check for overlapping extents in ext4_valid_extent_entries()")
Fixes: 2f974865f ("ext4: check for zero length extent explicitly")
Cc: Eryu Guan <guaneryu@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Phil Turnbull <phil.turnbull@oracle.com>
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
fs/ext4/extents.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index f9fe359..7eea761 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -361,9 +361,13 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
ext4_fsblk_t block = ext4_ext_pblock(ext);
int len = ext4_ext_get_actual_len(ext);
ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
- ext4_lblk_t last = lblock + len - 1;
- if (len == 0 || lblock > last)
+ /*
+ * We allow neither:
+ * - zero length
+ * - overflow/wrap-around
+ */
+ if (lblock + len <= lblock)
return 0;
return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
}
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 072/180] powerpc/pseries: Fix PCI config address for DDW |
| Message-ID | <s8DtV-2yc-77@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Gavin Shan <gwshan@linux.vnet.ibm.com>
commit 8a934efe94347eee843aeea65bdec8077a79e259 upstream.
In commit 8445a87f7092 "powerpc/iommu: Remove the dependency on EEH
struct in DDW mechanism", the PE address was replaced with the PCI
config address in order to remove dependency on EEH. According to PAPR
spec, firmware (pHyp or QEMU) should accept "xxBBSSxx" format PCI config
address, not "xxxxBBSS" provided by the patch. Note that "BB" is PCI bus
number and "SS" is the combination of slot and function number.
This fixes the PCI address passed to DDW RTAS calls.
Fixes: 8445a87f7092 ("powerpc/iommu: Remove the dependency on EEH struct in DDW mechanism")
Cc: stable@vger.kernel.org # v3.4+
Reported-by: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Tested-by: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
arch/powerpc/platforms/pseries/iommu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 1d2fc2f..4013691 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -873,7 +873,7 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
dn = pci_device_to_OF_node(dev);
pdn = PCI_DN(dn);
buid = pdn->phb->buid;
- cfg_addr = (pdn->busno << 8) | pdn->devfn;
+ cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
cfg_addr, BUID_HI(buid), BUID_LO(buid));
@@ -902,7 +902,7 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
dn = pci_device_to_OF_node(dev);
pdn = PCI_DN(dn);
buid = pdn->phb->buid;
- cfg_addr = (pdn->busno << 8) | pdn->devfn;
+ cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
do {
/* extra outputs are LIOBN and dma-addr (hi, lo) */
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 110/180] IB/security: Restrict use of the write() interface |
| Message-ID | <s8DtW-2yc-93@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
commit e6bd18f57aad1a2d1ef40e646d03ed0f2515c9e3 upstream.
The drivers/infiniband stack uses write() as a replacement for
bi-directional ioctl(). This is not safe. There are ways to
trigger write calls that result in the return structure that
is normally written to user space being shunted off to user
specified kernel memory instead.
For the immediate repair, detect and deny suspicious accesses to
the write API.
For long term, update the user space libraries and the kernel API
to something that doesn't present the same security vulnerabilities
(likely a structured ioctl() interface).
The impacted uAPI interfaces are generally only available if
hardware from drivers/infiniband is installed in the system.
Reported-by: Jann Horn <jann@thejh.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
[ Expanded check to all known write() entry points ]
Cc: stable@vger.kernel.org
Signed-off-by: Doug Ledford <dledford@redhat.com>
[wt: no hfi1 subdir in 3.10. A minimal rdma/ib.h had to be created
from 3.11 sources to keep the code similar to mainline]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
drivers/infiniband/core/ucm.c | 4 +++
drivers/infiniband/core/ucma.c | 4 +++
drivers/infiniband/core/uverbs_main.c | 5 +++
drivers/infiniband/hw/qib/qib_file_ops.c | 5 +++
include/rdma/ib.h | 54 ++++++++++++++++++++++++++++++++
5 files changed, 72 insertions(+)
create mode 100644 include/rdma/ib.h
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index f2f6393..5befec1 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -48,6 +48,7 @@
#include <asm/uaccess.h>
+#include <rdma/ib.h>
#include <rdma/ib_cm.h>
#include <rdma/ib_user_cm.h>
#include <rdma/ib_marshall.h>
@@ -1104,6 +1105,9 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
struct ib_ucm_cmd_hdr hdr;
ssize_t result;
+ if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
+ return -EACCES;
+
if (len < sizeof(hdr))
return -EINVAL;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 5ca44cd..99f1c170 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -43,6 +43,7 @@
#include <linux/sysctl.h>
#include <linux/module.h>
+#include <rdma/ib.h>
#include <rdma/rdma_user_cm.h>
#include <rdma/ib_marshall.h>
#include <rdma/rdma_cm.h>
@@ -1249,6 +1250,9 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf,
struct rdma_ucm_cmd_hdr hdr;
ssize_t ret;
+ if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
+ return -EACCES;
+
if (len < sizeof(hdr))
return -EINVAL;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index b6062b9..f50623d 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -48,6 +48,8 @@
#include <asm/uaccess.h>
+#include <rdma/ib.h>
+
#include "uverbs.h"
MODULE_AUTHOR("Roland Dreier");
@@ -588,6 +590,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
struct ib_uverbs_file *file = filp->private_data;
struct ib_uverbs_cmd_hdr hdr;
+ if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
+ return -EACCES;
+
if (count < sizeof hdr)
return -EINVAL;
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index b56c942..8cb29b3 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -45,6 +45,8 @@
#include <linux/delay.h>
#include <linux/export.h>
+#include <rdma/ib.h>
+
#include "qib.h"
#include "qib_common.h"
#include "qib_user_sdma.h"
@@ -1977,6 +1979,9 @@ static ssize_t qib_write(struct file *fp, const char __user *data,
ssize_t ret = 0;
void *dest;
+ if (WARN_ON_ONCE(!ib_safe_file_access(fp)))
+ return -EACCES;
+
if (count < sizeof(cmd.type)) {
ret = -EINVAL;
goto bail;
diff --git a/include/rdma/ib.h b/include/rdma/ib.h
new file mode 100644
index 0000000..f09331a
--- /dev/null
+++ b/include/rdma/ib.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(_RDMA_IB_H)
+#define _RDMA_IB_H
+
+#include <linux/types.h>
+#include <linux/sched.h>
+
+/*
+ * The IB interfaces that use write() as bi-directional ioctl() are
+ * fundamentally unsafe, since there are lots of ways to trigger "write()"
+ * calls from various contexts with elevated privileges. That includes the
+ * traditional suid executable error message writes, but also various kernel
+ * interfaces that can write to file descriptors.
+ *
+ * This function provides protection for the legacy API by restricting the
+ * calling context.
+ */
+static inline bool ib_safe_file_access(struct file *filp)
+{
+ return filp->f_cred == current_cred() && segment_eq(get_fs(), USER_DS);
+}
+
+#endif /* _RDMA_IB_H */
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 133/180] ALSA: timer: Fix leak in events via snd_timer_user_ccallback |
| Message-ID | <s8DtW-2yc-95@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Kangjie Lu <kangjielu@gmail.com> commit 9a47e9cff994f37f7f0dbd9ae23740d0f64f9fe6 upstream. The stack object “r1†has a total size of 32 bytes. Its field “event†and “val†both contain 4 bytes padding. These 8 bytes padding bytes are sent to user without being initialized. Signed-off-by: Kangjie Lu <kjlu@gatech.edu> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Willy Tarreau <w@1wt.eu> --- sound/core/timer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/core/timer.c b/sound/core/timer.c index 54ff806..7ba0709 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1208,6 +1208,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, tu->tstamp = *tstamp; if ((tu->filter & (1 << event)) == 0 || !tu->tread) return; + memset(&r1, 0, sizeof(r1)); r1.event = event; r1.tstamp = *tstamp; r1.val = resolution; -- 2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 123/180] iio: Fix error handling in iio_trigger_attach_poll_func |
| Message-ID | <s8DtV-2yc-83@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Crestez Dan Leonard <leonard.crestez@intel.com>
commit 99543823357966ac938d9a310947e731b67338e6 upstream.
When attaching a pollfunc iio_trigger_attach_poll_func will allocate a
virtual irq and call the driver's set_trigger_state function. Fix error
handling to undo previous steps if any fails.
In particular this fixes handling errors from a driver's
set_trigger_state function. When using triggered buffers a failure to
enable the trigger used to make the buffer unusable.
Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
drivers/iio/industrialio-trigger.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 4d6c7d8..301becc 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -203,22 +203,35 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
/* Prevent the module from being removed whilst attached to a trigger */
__module_get(pf->indio_dev->info->driver_module);
+
+ /* Get irq number */
pf->irq = iio_trigger_get_irq(trig);
+ if (pf->irq < 0)
+ goto out_put_module;
+
+ /* Request irq */
ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
pf->type, pf->name,
pf);
- if (ret < 0) {
- module_put(pf->indio_dev->info->driver_module);
- return ret;
- }
+ if (ret < 0)
+ goto out_put_irq;
+ /* Enable trigger in driver */
if (trig->ops && trig->ops->set_trigger_state && notinuse) {
ret = trig->ops->set_trigger_state(trig, true);
if (ret < 0)
- module_put(pf->indio_dev->info->driver_module);
+ goto out_free_irq;
}
return ret;
+
+out_free_irq:
+ free_irq(pf->irq, pf);
+out_put_irq:
+ iio_trigger_put_irq(trig, pf->irq);
+out_put_module:
+ module_put(pf->indio_dev->info->driver_module);
+ return ret;
}
static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 172/180] module: Invalidate signatures on force-loaded modules |
| Message-ID | <s8DtV-2yc-87@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Ben Hutchings <ben@decadent.org.uk>
commit bca014caaa6130e57f69b5bf527967aa8ee70fdd upstream.
Signing a module should only make it trusted by the specific kernel it
was built for, not anything else. Loading a signed module meant for a
kernel with a different ABI could have interesting effects.
Therefore, treat all signatures as invalid when a module is
force-loaded.
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
kernel/module.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/kernel/module.c b/kernel/module.c
index f8a4f48..2c87e52 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2475,13 +2475,18 @@ static inline void kmemleak_load_module(const struct module *mod,
#endif
#ifdef CONFIG_MODULE_SIG
-static int module_sig_check(struct load_info *info)
+static int module_sig_check(struct load_info *info, int flags)
{
int err = -ENOKEY;
const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
const void *mod = info->hdr;
- if (info->len > markerlen &&
+ /*
+ * Require flags == 0, as a module with version information
+ * removed is no longer the module that was signed
+ */
+ if (flags == 0 &&
+ info->len > markerlen &&
memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
/* We truncate the module to discard the signature */
info->len -= markerlen;
@@ -2503,7 +2508,7 @@ static int module_sig_check(struct load_info *info)
return err;
}
#else /* !CONFIG_MODULE_SIG */
-static int module_sig_check(struct load_info *info)
+static int module_sig_check(struct load_info *info, int flags)
{
return 0;
}
@@ -3228,7 +3233,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
struct module *mod;
long err;
- err = module_sig_check(info);
+ err = module_sig_check(info, flags);
if (err)
goto free_copy;
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:10 +0200 |
| Subject | [PATCH 3.10 160/180] hp-wmi: Fix wifi cannot be hard-unblocked |
| Message-ID | <s8DtW-2yc-91@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Alex Hung <alex.hung@canonical.com>
commit fc8a601e1175ae351f662506030f9939cb7fdbfe upstream.
Several users reported wifi cannot be unblocked as discussed in [1].
This patch removes the use of the 2009 flag by BIOS but uses the actual
WMI function calls - it will be skipped if WMI reports unsupported.
[1] https://bugzilla.kernel.org/show_bug.cgi?id=69131
Signed-off-by: Alex Hung <alex.hung@canonical.com>
Tested-by: Evgenii Shatokhin <eugene.shatokhin@yandex.ru>
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
drivers/platform/x86/hp-wmi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index d111c86..46497c6 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -640,6 +640,11 @@ static int hp_wmi_rfkill_setup(struct platform_device *device)
if (err)
return err;
+ err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, &wireless,
+ sizeof(wireless), 0);
+ if (err)
+ return err;
+
if (wireless & 0x1) {
wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
RFKILL_TYPE_WLAN,
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 004/180] netfilter: x_tables: make sure e->next_offset covers remaining blob size |
| Message-ID | <s8DDz-2Bs-5@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Florian Westphal <fw@strlen.de>
commit 6e94e0cfb0887e4013b3b930fa6ab1fe6bb6ba91 upstream.
Otherwise this function may read data beyond the ruleset blob.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
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(-)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 269759d..ee40bd4 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -558,7 +558,8 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
int 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;
}
@@ -1218,7 +1219,8 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
duprintf("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;
}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 5ca478f..7cfd566 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -721,7 +721,8 @@ check_entry_size_and_hooks(struct ipt_entry *e,
int 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;
}
@@ -1484,7 +1485,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
duprintf("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;
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 597f539..9c6b543 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -732,7 +732,8 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
int 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;
}
@@ -1496,7 +1497,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
duprintf("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;
}
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 042/180] printk: do cond_resched() between lines while outputting to consoles |
| Message-ID | <s8DDz-2Bs-3@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Tejun Heo <tj@kernel.org>
commit 8d91f8b15361dfb438ab6eb3b319e2ded43458ff upstream.
@console_may_schedule tracks whether console_sem was acquired through
lock or trylock. If the former, we're inside a sleepable context and
console_conditional_schedule() performs cond_resched(). This allows
console drivers which use console_lock for synchronization to yield
while performing time-consuming operations such as scrolling.
However, the actual console outputting is performed while holding
irq-safe logbuf_lock, so console_unlock() clears @console_may_schedule
before starting outputting lines. Also, only a few drivers call
console_conditional_schedule() to begin with. This means that when a
lot of lines need to be output by console_unlock(), for example on a
console registration, the task doing console_unlock() may not yield for
a long time on a non-preemptible kernel.
If this happens with a slow console devices, for example a serial
console, the outputting task may occupy the cpu for a very long time.
Long enough to trigger softlockup and/or RCU stall warnings, which in
turn pile more messages, sometimes enough to trigger the next cycle of
warnings incapacitating the system.
Fix it by making console_unlock() insert cond_resched() between lines if
@console_may_schedule.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Calvin Owens <calvinowens@fb.com>
Acked-by: Jan Kara <jack@suse.com>
Cc: Dave Jones <davej@codemonkey.org.uk>
Cc: Kyle McMartin <kyle@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[ciwillia@brocade.com: adjust context for 3.10.y]
Signed-off-by: Chas Williams <ciwillia@brocade.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
include/linux/console.h | 1 +
kernel/panic.c | 3 +++
kernel/printk.c | 35 ++++++++++++++++++++++++++++++++++-
3 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/include/linux/console.h b/include/linux/console.h
index 73bab0f..6877ffc 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -153,6 +153,7 @@ extern int console_trylock(void);
extern void console_unlock(void);
extern void console_conditional_schedule(void);
extern void console_unblank(void);
+extern void console_flush_on_panic(void);
extern struct tty_driver *console_device(int *);
extern void console_stop(struct console *);
extern void console_start(struct console *);
diff --git a/kernel/panic.c b/kernel/panic.c
index 167ec097..d3d74c4 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -22,6 +22,7 @@
#include <linux/sysrq.h>
#include <linux/init.h>
#include <linux/nmi.h>
+#include <linux/console.h>
#define PANIC_TIMER_STEP 100
#define PANIC_BLINK_SPD 18
@@ -128,6 +129,8 @@ void panic(const char *fmt, ...)
bust_spinlocks(0);
+ console_flush_on_panic();
+
if (!panic_blink)
panic_blink = no_blink;
diff --git a/kernel/printk.c b/kernel/printk.c
index fd0154a..ee8f6be 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -2033,13 +2033,24 @@ void console_unlock(void)
static u64 seen_seq;
unsigned long flags;
bool wake_klogd = false;
- bool retry;
+ bool do_cond_resched, retry;
if (console_suspended) {
up(&console_sem);
return;
}
+ /*
+ * Console drivers are called under logbuf_lock, so
+ * @console_may_schedule should be cleared before; however, we may
+ * end up dumping a lot of lines, for example, if called from
+ * console registration path, and should invoke cond_resched()
+ * between lines if allowable. Not doing so can cause a very long
+ * scheduling stall on a slow console leading to RCU stall and
+ * softlockup warnings which exacerbate the issue with more
+ * messages practically incapacitating the system.
+ */
+ do_cond_resched = console_may_schedule;
console_may_schedule = 0;
/* flush buffered message fragment immediately to console */
@@ -2096,6 +2107,9 @@ skip:
call_console_drivers(level, text, len);
start_critical_timings();
local_irq_restore(flags);
+
+ if (do_cond_resched)
+ cond_resched();
}
console_locked = 0;
mutex_release(&console_lock_dep_map, 1, _RET_IP_);
@@ -2164,6 +2178,25 @@ void console_unblank(void)
console_unlock();
}
+/**
+ * console_flush_on_panic - flush console content on panic
+ *
+ * Immediately output all pending messages no matter what.
+ */
+void console_flush_on_panic(void)
+{
+ /*
+ * If someone else is holding the console lock, trylock will fail
+ * and may_schedule may be set. Ignore and proceed to unlock so
+ * that messages are flushed out. As this can be called from any
+ * context and we don't want to get preempted while flushing,
+ * ensure may_schedule is cleared.
+ */
+ console_trylock();
+ console_may_schedule = 0;
+ console_unlock();
+}
+
/*
* Return the console tty driver structure and its associated index
*/
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 001/180] X.509: remove possible code fragility: enumeration values not handled |
| Message-ID | <s8DDA-2Bs-21@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Antonio Alecrim Jr <antonio.alecrim@gmail.com> commit eb8948a03704f3dbbfc7e83090e20e93c6c476d2 upstream. Signed-off-by: Antonio Alecrim Jr <antonio.alecrim@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Willy Tarreau <w@1wt.eu> --- scripts/asn1_compiler.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c index db0e5cd..91c4117 100644 --- a/scripts/asn1_compiler.c +++ b/scripts/asn1_compiler.c @@ -1353,6 +1353,8 @@ static void render_out_of_line_list(FILE *out) render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); render_opcode(out, "_jump_target(%u),\n", entry); break; + default: + break; } if (e->action) render_opcode(out, "_action(ACT_%s),\n", -- 2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 097/180] ecryptfs: forbid opening files without mmap handler |
| Message-ID | <s8DDA-2Bs-7@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Jann Horn <jannh@google.com>
commit 2f36db71009304b3f0b95afacd8eba1f9f046b87 upstream.
This prevents users from triggering a stack overflow through a recursive
invocation of pagefault handling that involves mapping procfs files into
virtual memory.
Signed-off-by: Jann Horn <jannh@google.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
fs/ecryptfs/kthread.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
index f1ea610..9b661a4 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/mount.h>
+#include <linux/file.h>
#include "ecryptfs_kernel.h"
struct ecryptfs_open_req {
@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
(*lower_file) = dentry_open(&req.path, flags, cred);
if (!IS_ERR(*lower_file))
- goto out;
+ goto have_file;
if ((flags & O_ACCMODE) == O_RDONLY) {
rc = PTR_ERR((*lower_file));
goto out;
@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file **lower_file,
mutex_unlock(&ecryptfs_kthread_ctl.mux);
wake_up(&ecryptfs_kthread_ctl.wait);
wait_for_completion(&req.done);
- if (IS_ERR(*lower_file))
+ if (IS_ERR(*lower_file)) {
rc = PTR_ERR(*lower_file);
+ goto out;
+ }
+have_file:
+ if ((*lower_file)->f_op->mmap == NULL) {
+ fput(*lower_file);
+ *lower_file = NULL;
+ rc = -EMEDIUMTYPE;
+ }
out:
return rc;
}
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 021/180] netfilter: x_tables: do compat validation via translate_table |
| Message-ID | <s8DDA-2Bs-11@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Florian Westphal <fw@strlen.de>
commit 09d9686047dbbe1cf4faa558d3ecc4aae2046054 upstream.
This looks like refactoring, but its also a bug fix.
Problem is that the compat path (32bit iptables, 64bit kernel) lacks a few
sanity tests that are done in the normal path.
For example, we do not check for underflows and the base chain policies.
While its possible to also add such checks to the compat path, its more
copy&pastry, for instance we cannot reuse check_underflow() helper as
e->target_offset differs in the compat case.
Other problem is that it makes auditing for validation errors harder; two
places need to be checked and kept in sync.
At a high level 32 bit compat works like this:
1- initial pass over blob:
validate match/entry offsets, bounds checking
lookup all matches and targets
do bookkeeping wrt. size delta of 32/64bit structures
assign match/target.u.kernel pointer (points at kernel
implementation, needed to access ->compatsize etc.)
2- allocate memory according to the total bookkeeping size to
contain the translated ruleset
3- second pass over original blob:
for each entry, copy the 32bit representation to the newly allocated
memory. This also does any special match translations (e.g.
adjust 32bit to 64bit longs, etc).
4- check if ruleset is free of loops (chase all jumps)
5-first pass over translated blob:
call the checkentry function of all matches and targets.
The alternative implemented by this patch is to drop steps 3&4 from the
compat process, the translation is changed into an intermediate step
rather than a full 1:1 translate_table replacement.
In the 2nd pass (step #3), change the 64bit ruleset back to a kernel
representation, i.e. put() the kernel pointer and restore ->u.user.name .
This gets us a 64bit ruleset that is in the format generated by a 64bit
iptables userspace -- we can then use translate_table() to get the
'native' sanity checks.
This has two drawbacks:
1. we re-validate all the match and target entry structure sizes even
though compat translation is supposed to never generate bogus offsets.
2. we put and then re-lookup each match and target.
THe upside is that we get all sanity tests and ruleset validations
provided by the normal path and can remove some duplicated compat code.
iptables-restore time of autogenerated ruleset with 300k chains of form
-A CHAIN0001 -m limit --limit 1/s -j CHAIN0002
-A CHAIN0002 -m limit --limit 1/s -j CHAIN0003
shows no noticeable differences in restore times:
old: 0m30.796s
new: 0m31.521s
64bit: 0m25.674s
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
net/ipv4/netfilter/arp_tables.c | 109 ++++++-----------------------
net/ipv4/netfilter/ip_tables.c | 151 ++++++++--------------------------------
net/ipv6/netfilter/ip6_tables.c | 145 ++++++--------------------------------
net/netfilter/x_tables.c | 8 +++
4 files changed, 80 insertions(+), 333 deletions(-)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index b65b562..2339399 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1222,19 +1222,17 @@ static inline void compat_release_entry(struct compat_arpt_entry *e)
module_put(t->u.kernel.target->me);
}
-static inline int
+static int
check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
struct xt_table_info *newinfo,
unsigned int *size,
const unsigned char *base,
- const unsigned char *limit,
- const unsigned int *hook_entries,
- const unsigned int *underflows)
+ const unsigned char *limit)
{
struct xt_entry_target *t;
struct xt_target *target;
unsigned int entry_offset;
- int ret, off, h;
+ int ret, off;
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 ||
@@ -1279,17 +1277,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
if (ret)
goto release_target;
- /* Check hooks & underflows */
- for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
- if ((unsigned char *)e - base == hook_entries[h])
- newinfo->hook_entry[h] = hook_entries[h];
- if ((unsigned char *)e - base == underflows[h])
- newinfo->underflow[h] = underflows[h];
- }
-
- /* Clear counters and comefrom */
- memset(&e->counters, 0, sizeof(e->counters));
- e->comefrom = 0;
return 0;
release_target:
@@ -1339,7 +1326,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
struct xt_table_info *newinfo, *info;
void *pos, *entry0, *entry1;
struct compat_arpt_entry *iter0;
- struct arpt_entry *iter1;
+ struct arpt_replace repl;
unsigned int size;
int ret = 0;
@@ -1348,12 +1335,6 @@ static int translate_compat_table(struct xt_table_info **pinfo,
size = compatr->size;
info->number = compatr->num_entries;
- /* Init all hooks to impossible value. */
- for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
- info->hook_entry[i] = 0xFFFFFFFF;
- info->underflow[i] = 0xFFFFFFFF;
- }
-
duprintf("translate_compat_table: size %u\n", info->size);
j = 0;
xt_compat_lock(NFPROTO_ARP);
@@ -1362,9 +1343,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
xt_entry_foreach(iter0, entry0, compatr->size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0,
- entry0 + compatr->size,
- compatr->hook_entry,
- compatr->underflow);
+ entry0 + compatr->size);
if (ret != 0)
goto out_unlock;
++j;
@@ -1377,23 +1356,6 @@ static int translate_compat_table(struct xt_table_info **pinfo,
goto out_unlock;
}
- /* Check hooks all assigned */
- for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
- /* Only hooks which are valid */
- if (!(compatr->valid_hooks & (1 << i)))
- continue;
- if (info->hook_entry[i] == 0xFFFFFFFF) {
- duprintf("Invalid hook entry %u %u\n",
- i, info->hook_entry[i]);
- goto out_unlock;
- }
- if (info->underflow[i] == 0xFFFFFFFF) {
- duprintf("Invalid underflow %u %u\n",
- i, info->underflow[i]);
- goto out_unlock;
- }
- }
-
ret = -ENOMEM;
newinfo = xt_alloc_table_info(size);
if (!newinfo)
@@ -1410,51 +1372,25 @@ static int translate_compat_table(struct xt_table_info **pinfo,
xt_entry_foreach(iter0, entry0, compatr->size)
compat_copy_entry_from_user(iter0, &pos, &size,
newinfo, entry1);
+
+ /* all module references in entry0 are now gone */
+
xt_compat_flush_offsets(NFPROTO_ARP);
xt_compat_unlock(NFPROTO_ARP);
- ret = -ELOOP;
- if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
- goto free_newinfo;
+ memcpy(&repl, compatr, sizeof(*compatr));
- i = 0;
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- ret = check_target(iter1, compatr->name);
- if (ret != 0)
- break;
- ++i;
- if (strcmp(arpt_get_target(iter1)->u.user.name,
- XT_ERROR_TARGET) == 0)
- ++newinfo->stacksize;
- }
- if (ret) {
- /*
- * The first i matches need cleanup_entry (calls ->destroy)
- * because they had called ->check already. The other j-i
- * entries need only release.
- */
- int skip = i;
- j -= i;
- xt_entry_foreach(iter0, entry0, newinfo->size) {
- if (skip-- > 0)
- continue;
- if (j-- == 0)
- break;
- compat_release_entry(iter0);
- }
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- if (i-- == 0)
- break;
- cleanup_entry(iter1);
- }
- xt_free_table_info(newinfo);
- return ret;
+ for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
+ repl.hook_entry[i] = newinfo->hook_entry[i];
+ repl.underflow[i] = newinfo->underflow[i];
}
- /* And one copy for every other CPU */
- for_each_possible_cpu(i)
- if (newinfo->entries[i] && newinfo->entries[i] != entry1)
- memcpy(newinfo->entries[i], entry1, newinfo->size);
+ repl.num_counters = 0;
+ repl.counters = NULL;
+ repl.size = newinfo->size;
+ ret = translate_table(newinfo, entry1, &repl);
+ if (ret)
+ goto free_newinfo;
*pinfo = newinfo;
*pentry0 = entry1;
@@ -1463,17 +1399,16 @@ static int translate_compat_table(struct xt_table_info **pinfo,
free_newinfo:
xt_free_table_info(newinfo);
-out:
+ return ret;
+out_unlock:
+ xt_compat_flush_offsets(NFPROTO_ARP);
+ xt_compat_unlock(NFPROTO_ARP);
xt_entry_foreach(iter0, entry0, compatr->size) {
if (j-- == 0)
break;
compat_release_entry(iter0);
}
return ret;
-out_unlock:
- xt_compat_flush_offsets(NFPROTO_ARP);
- xt_compat_unlock(NFPROTO_ARP);
- goto out;
}
static int compat_do_replace(struct net *net, void __user *user,
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index b9dd1fd..c48b86a 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1477,16 +1477,14 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
struct xt_table_info *newinfo,
unsigned int *size,
const unsigned char *base,
- const unsigned char *limit,
- const unsigned int *hook_entries,
- const unsigned int *underflows)
+ const unsigned char *limit)
{
struct xt_entry_match *ematch;
struct xt_entry_target *t;
struct xt_target *target;
unsigned int entry_offset;
unsigned int j;
- int ret, off, h;
+ int ret, off;
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
@@ -1539,17 +1537,6 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
if (ret)
goto out;
- /* Check hooks & underflows */
- for (h = 0; h < NF_INET_NUMHOOKS; h++) {
- if ((unsigned char *)e - base == hook_entries[h])
- newinfo->hook_entry[h] = hook_entries[h];
- if ((unsigned char *)e - base == underflows[h])
- newinfo->underflow[h] = underflows[h];
- }
-
- /* Clear counters and comefrom */
- memset(&e->counters, 0, sizeof(e->counters));
- e->comefrom = 0;
return 0;
out:
@@ -1592,6 +1579,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
xt_compat_target_from_user(t, dstptr, size);
de->next_offset = e->next_offset - (origsize - *size);
+
for (h = 0; h < NF_INET_NUMHOOKS; h++) {
if ((unsigned char *)de - base < newinfo->hook_entry[h])
newinfo->hook_entry[h] -= origsize - *size;
@@ -1601,41 +1589,6 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
}
static int
-compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
-{
- struct xt_entry_match *ematch;
- struct xt_mtchk_param mtpar;
- unsigned int j;
- int ret = 0;
-
- j = 0;
- mtpar.net = net;
- mtpar.table = name;
- mtpar.entryinfo = &e->ip;
- mtpar.hook_mask = e->comefrom;
- mtpar.family = NFPROTO_IPV4;
- xt_ematch_foreach(ematch, e) {
- ret = check_match(ematch, &mtpar);
- if (ret != 0)
- goto cleanup_matches;
- ++j;
- }
-
- ret = check_target(e, net, name);
- if (ret)
- goto cleanup_matches;
- return 0;
-
- cleanup_matches:
- xt_ematch_foreach(ematch, e) {
- if (j-- == 0)
- break;
- cleanup_match(ematch, net);
- }
- return ret;
-}
-
-static int
translate_compat_table(struct net *net,
struct xt_table_info **pinfo,
void **pentry0,
@@ -1645,7 +1598,7 @@ translate_compat_table(struct net *net,
struct xt_table_info *newinfo, *info;
void *pos, *entry0, *entry1;
struct compat_ipt_entry *iter0;
- struct ipt_entry *iter1;
+ struct ipt_replace repl;
unsigned int size;
int ret;
@@ -1654,12 +1607,6 @@ translate_compat_table(struct net *net,
size = compatr->size;
info->number = compatr->num_entries;
- /* Init all hooks to impossible value. */
- for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- info->hook_entry[i] = 0xFFFFFFFF;
- info->underflow[i] = 0xFFFFFFFF;
- }
-
duprintf("translate_compat_table: size %u\n", info->size);
j = 0;
xt_compat_lock(AF_INET);
@@ -1668,9 +1615,7 @@ translate_compat_table(struct net *net,
xt_entry_foreach(iter0, entry0, compatr->size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0,
- entry0 + compatr->size,
- compatr->hook_entry,
- compatr->underflow);
+ entry0 + compatr->size);
if (ret != 0)
goto out_unlock;
++j;
@@ -1683,23 +1628,6 @@ translate_compat_table(struct net *net,
goto out_unlock;
}
- /* Check hooks all assigned */
- for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- /* Only hooks which are valid */
- if (!(compatr->valid_hooks & (1 << i)))
- continue;
- if (info->hook_entry[i] == 0xFFFFFFFF) {
- duprintf("Invalid hook entry %u %u\n",
- i, info->hook_entry[i]);
- goto out_unlock;
- }
- if (info->underflow[i] == 0xFFFFFFFF) {
- duprintf("Invalid underflow %u %u\n",
- i, info->underflow[i]);
- goto out_unlock;
- }
- }
-
ret = -ENOMEM;
newinfo = xt_alloc_table_info(size);
if (!newinfo)
@@ -1707,8 +1635,8 @@ translate_compat_table(struct net *net,
newinfo->number = compatr->num_entries;
for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- newinfo->hook_entry[i] = info->hook_entry[i];
- newinfo->underflow[i] = info->underflow[i];
+ newinfo->hook_entry[i] = compatr->hook_entry[i];
+ newinfo->underflow[i] = compatr->underflow[i];
}
entry1 = newinfo->entries[raw_smp_processor_id()];
pos = entry1;
@@ -1717,51 +1645,29 @@ translate_compat_table(struct net *net,
compat_copy_entry_from_user(iter0, &pos, &size,
newinfo, entry1);
+ /* all module references in entry0 are now gone.
+ * entry1/newinfo contains a 64bit ruleset that looks exactly as
+ * generated by 64bit userspace.
+ *
+ * Call standard translate_table() to validate all hook_entrys,
+ * underflows, check for loops, etc.
+ */
xt_compat_flush_offsets(AF_INET);
xt_compat_unlock(AF_INET);
- ret = -ELOOP;
- if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
- goto free_newinfo;
+ memcpy(&repl, compatr, sizeof(*compatr));
- i = 0;
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- ret = compat_check_entry(iter1, net, compatr->name);
- if (ret != 0)
- break;
- ++i;
- if (strcmp(ipt_get_target(iter1)->u.user.name,
- XT_ERROR_TARGET) == 0)
- ++newinfo->stacksize;
- }
- if (ret) {
- /*
- * The first i matches need cleanup_entry (calls ->destroy)
- * because they had called ->check already. The other j-i
- * entries need only release.
- */
- int skip = i;
- j -= i;
- xt_entry_foreach(iter0, entry0, newinfo->size) {
- if (skip-- > 0)
- continue;
- if (j-- == 0)
- break;
- compat_release_entry(iter0);
- }
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- if (i-- == 0)
- break;
- cleanup_entry(iter1, net);
- }
- xt_free_table_info(newinfo);
- return ret;
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
+ repl.hook_entry[i] = newinfo->hook_entry[i];
+ repl.underflow[i] = newinfo->underflow[i];
}
- /* And one copy for every other CPU */
- for_each_possible_cpu(i)
- if (newinfo->entries[i] && newinfo->entries[i] != entry1)
- memcpy(newinfo->entries[i], entry1, newinfo->size);
+ repl.num_counters = 0;
+ repl.counters = NULL;
+ repl.size = newinfo->size;
+ ret = translate_table(net, newinfo, entry1, &repl);
+ if (ret)
+ goto free_newinfo;
*pinfo = newinfo;
*pentry0 = entry1;
@@ -1770,17 +1676,16 @@ translate_compat_table(struct net *net,
free_newinfo:
xt_free_table_info(newinfo);
-out:
+ return ret;
+out_unlock:
+ xt_compat_flush_offsets(AF_INET);
+ xt_compat_unlock(AF_INET);
xt_entry_foreach(iter0, entry0, compatr->size) {
if (j-- == 0)
break;
compat_release_entry(iter0);
}
return ret;
-out_unlock:
- xt_compat_flush_offsets(AF_INET);
- xt_compat_unlock(AF_INET);
- goto out;
}
static int
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 6e7f5ac..1e44ad2 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1489,16 +1489,14 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
struct xt_table_info *newinfo,
unsigned int *size,
const unsigned char *base,
- const unsigned char *limit,
- const unsigned int *hook_entries,
- const unsigned int *underflows)
+ const unsigned char *limit)
{
struct xt_entry_match *ematch;
struct xt_entry_target *t;
struct xt_target *target;
unsigned int entry_offset;
unsigned int j;
- int ret, off, h;
+ int ret, off;
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
@@ -1551,17 +1549,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
if (ret)
goto out;
- /* Check hooks & underflows */
- for (h = 0; h < NF_INET_NUMHOOKS; h++) {
- if ((unsigned char *)e - base == hook_entries[h])
- newinfo->hook_entry[h] = hook_entries[h];
- if ((unsigned char *)e - base == underflows[h])
- newinfo->underflow[h] = underflows[h];
- }
-
- /* Clear counters and comefrom */
- memset(&e->counters, 0, sizeof(e->counters));
- e->comefrom = 0;
return 0;
out:
@@ -1610,41 +1597,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
}
}
-static int compat_check_entry(struct ip6t_entry *e, struct net *net,
- const char *name)
-{
- unsigned int j;
- int ret = 0;
- struct xt_mtchk_param mtpar;
- struct xt_entry_match *ematch;
-
- j = 0;
- mtpar.net = net;
- mtpar.table = name;
- mtpar.entryinfo = &e->ipv6;
- mtpar.hook_mask = e->comefrom;
- mtpar.family = NFPROTO_IPV6;
- xt_ematch_foreach(ematch, e) {
- ret = check_match(ematch, &mtpar);
- if (ret != 0)
- goto cleanup_matches;
- ++j;
- }
-
- ret = check_target(e, net, name);
- if (ret)
- goto cleanup_matches;
- return 0;
-
- cleanup_matches:
- xt_ematch_foreach(ematch, e) {
- if (j-- == 0)
- break;
- cleanup_match(ematch, net);
- }
- return ret;
-}
-
static int
translate_compat_table(struct net *net,
struct xt_table_info **pinfo,
@@ -1655,7 +1607,7 @@ translate_compat_table(struct net *net,
struct xt_table_info *newinfo, *info;
void *pos, *entry0, *entry1;
struct compat_ip6t_entry *iter0;
- struct ip6t_entry *iter1;
+ struct ip6t_replace repl;
unsigned int size;
int ret = 0;
@@ -1664,12 +1616,6 @@ translate_compat_table(struct net *net,
size = compatr->size;
info->number = compatr->num_entries;
- /* Init all hooks to impossible value. */
- for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- info->hook_entry[i] = 0xFFFFFFFF;
- info->underflow[i] = 0xFFFFFFFF;
- }
-
duprintf("translate_compat_table: size %u\n", info->size);
j = 0;
xt_compat_lock(AF_INET6);
@@ -1678,9 +1624,7 @@ translate_compat_table(struct net *net,
xt_entry_foreach(iter0, entry0, compatr->size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0,
- entry0 + compatr->size,
- compatr->hook_entry,
- compatr->underflow);
+ entry0 + compatr->size);
if (ret != 0)
goto out_unlock;
++j;
@@ -1693,23 +1637,6 @@ translate_compat_table(struct net *net,
goto out_unlock;
}
- /* Check hooks all assigned */
- for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- /* Only hooks which are valid */
- if (!(compatr->valid_hooks & (1 << i)))
- continue;
- if (info->hook_entry[i] == 0xFFFFFFFF) {
- duprintf("Invalid hook entry %u %u\n",
- i, info->hook_entry[i]);
- goto out_unlock;
- }
- if (info->underflow[i] == 0xFFFFFFFF) {
- duprintf("Invalid underflow %u %u\n",
- i, info->underflow[i]);
- goto out_unlock;
- }
- }
-
ret = -ENOMEM;
newinfo = xt_alloc_table_info(size);
if (!newinfo)
@@ -1717,60 +1644,33 @@ translate_compat_table(struct net *net,
newinfo->number = compatr->num_entries;
for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- newinfo->hook_entry[i] = info->hook_entry[i];
- newinfo->underflow[i] = info->underflow[i];
+ newinfo->hook_entry[i] = compatr->hook_entry[i];
+ newinfo->underflow[i] = compatr->underflow[i];
}
entry1 = newinfo->entries[raw_smp_processor_id()];
pos = entry1;
+ size = compatr->size;
xt_entry_foreach(iter0, entry0, compatr->size)
compat_copy_entry_from_user(iter0, &pos, &size,
newinfo, entry1);
+ /* all module references in entry0 are now gone. */
xt_compat_flush_offsets(AF_INET6);
xt_compat_unlock(AF_INET6);
- ret = -ELOOP;
- if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
- goto free_newinfo;
+ memcpy(&repl, compatr, sizeof(*compatr));
- i = 0;
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- ret = compat_check_entry(iter1, net, compatr->name);
- if (ret != 0)
- break;
- ++i;
- if (strcmp(ip6t_get_target(iter1)->u.user.name,
- XT_ERROR_TARGET) == 0)
- ++newinfo->stacksize;
- }
- if (ret) {
- /*
- * The first i matches need cleanup_entry (calls ->destroy)
- * because they had called ->check already. The other j-i
- * entries need only release.
- */
- int skip = i;
- j -= i;
- xt_entry_foreach(iter0, entry0, newinfo->size) {
- if (skip-- > 0)
- continue;
- if (j-- == 0)
- break;
- compat_release_entry(iter0);
- }
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- if (i-- == 0)
- break;
- cleanup_entry(iter1, net);
- }
- xt_free_table_info(newinfo);
- return ret;
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
+ repl.hook_entry[i] = newinfo->hook_entry[i];
+ repl.underflow[i] = newinfo->underflow[i];
}
- /* And one copy for every other CPU */
- for_each_possible_cpu(i)
- if (newinfo->entries[i] && newinfo->entries[i] != entry1)
- memcpy(newinfo->entries[i], entry1, newinfo->size);
+ repl.num_counters = 0;
+ repl.counters = NULL;
+ repl.size = newinfo->size;
+ ret = translate_table(net, newinfo, entry1, &repl);
+ if (ret)
+ goto free_newinfo;
*pinfo = newinfo;
*pentry0 = entry1;
@@ -1779,17 +1679,16 @@ translate_compat_table(struct net *net,
free_newinfo:
xt_free_table_info(newinfo);
-out:
+ return ret;
+out_unlock:
+ xt_compat_flush_offsets(AF_INET6);
+ xt_compat_unlock(AF_INET6);
xt_entry_foreach(iter0, entry0, compatr->size) {
if (j-- == 0)
break;
compat_release_entry(iter0);
}
return ret;
-out_unlock:
- xt_compat_flush_offsets(AF_INET6);
- xt_compat_unlock(AF_INET6);
- goto out;
}
static int
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 9cf3039..da11978 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -552,6 +552,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
int pad, off = xt_compat_match_offset(match);
u_int16_t msize = cm->u.user.match_size;
+ char name[sizeof(m->u.user.name)];
m = *dstptr;
memcpy(m, cm, sizeof(*cm));
@@ -565,6 +566,9 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
msize += off;
m->u.user.match_size = msize;
+ strlcpy(name, match->name, sizeof(name));
+ module_put(match->me);
+ strncpy(m->u.user.name, name, sizeof(m->u.user.name));
*size += off;
*dstptr += msize;
@@ -782,6 +786,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
int pad, off = xt_compat_target_offset(target);
u_int16_t tsize = ct->u.user.target_size;
+ char name[sizeof(t->u.user.name)];
t = *dstptr;
memcpy(t, ct, sizeof(*ct));
@@ -795,6 +800,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
tsize += off;
t->u.user.target_size = tsize;
+ strlcpy(name, target->name, sizeof(name));
+ module_put(target->me);
+ strncpy(t->u.user.name, name, sizeof(t->u.user.name));
*size += off;
*dstptr += tsize;
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 030/180] USB: usbfs: fix potential infoleak in devio |
| Message-ID | <s8DDA-2Bs-13@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Kangjie Lu <kangjielu@gmail.com>
commit 681fef8380eb818c0b845fca5d2ab1dcbab114ee upstream.
The stack object "ci" has a total size of 8 bytes. Its last 3 bytes
are padding bytes which are not initialized and leaked to userland
via "copy_to_user".
CVE-2016-4482
Signed-off-by: Kangjie Lu <kjlu@gatech.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ciwillia@brocade.com: backported to 3.10: adjusted context]
Signed-off-by: Charles (Chas) Williams <ciwillia@brocade.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
drivers/usb/core/devio.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 62e532f..cfce807 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1106,10 +1106,11 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
static int proc_connectinfo(struct dev_state *ps, void __user *arg)
{
- struct usbdevfs_connectinfo ci = {
- .devnum = ps->dev->devnum,
- .slow = ps->dev->speed == USB_SPEED_LOW
- };
+ struct usbdevfs_connectinfo ci;
+
+ memset(&ci, 0, sizeof(ci));
+ ci.devnum = ps->dev->devnum;
+ ci.slow = ps->dev->speed == USB_SPEED_LOW;
if (copy_to_user(arg, &ci, sizeof(ci)))
return -EFAULT;
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 040/180] KEYS: potential uninitialized variable |
| Message-ID | <s8DDA-2Bs-9@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Dan Carpenter <dan.carpenter@oracle.com>
commit 38327424b40bcebe2de92d07312c89360ac9229a upstream.
If __key_link_begin() failed then "edit" would be uninitialized. I've
added a check to fix that.
This allows a random user to crash the kernel, though it's quite
difficult to achieve. There are three ways it can be done as the user
would have to cause an error to occur in __key_link():
(1) Cause the kernel to run out of memory. In practice, this is difficult
to achieve without ENOMEM cropping up elsewhere and aborting the
attempt.
(2) Revoke the destination keyring between the keyring ID being looked up
and it being tested for revocation. In practice, this is difficult to
time correctly because the KEYCTL_REJECT function can only be used
from the request-key upcall process. Further, users can only make use
of what's in /sbin/request-key.conf, though this does including a
rejection debugging test - which means that the destination keyring
has to be the caller's session keyring in practice.
(3) Have just enough key quota available to create a key, a new session
keyring for the upcall and a link in the session keyring, but not then
sufficient quota to create a link in the nominated destination keyring
so that it fails with EDQUOT.
The bug can be triggered using option (3) above using something like the
following:
echo 80 >/proc/sys/kernel/keys/root_maxbytes
keyctl request2 user debug:fred negate @t
The above sets the quota to something much lower (80) to make the bug
easier to trigger, but this is dependent on the system. Note also that
the name of the keyring created contains a random number that may be
between 1 and 10 characters in size, so may throw the test off by
changing the amount of quota used.
Assuming the failure occurs, something like the following will be seen:
kfree_debugcheck: out of range ptr 6b6b6b6b6b6b6b68h
------------[ cut here ]------------
kernel BUG at ../mm/slab.c:2821!
...
RIP: 0010:[<ffffffff811600f9>] kfree_debugcheck+0x20/0x25
RSP: 0018:ffff8804014a7de8 EFLAGS: 00010092
RAX: 0000000000000034 RBX: 6b6b6b6b6b6b6b68 RCX: 0000000000000000
RDX: 0000000000040001 RSI: 00000000000000f6 RDI: 0000000000000300
RBP: ffff8804014a7df0 R08: 0000000000000001 R09: 0000000000000000
R10: ffff8804014a7e68 R11: 0000000000000054 R12: 0000000000000202
R13: ffffffff81318a66 R14: 0000000000000000 R15: 0000000000000001
...
Call Trace:
kfree+0xde/0x1bc
assoc_array_cancel_edit+0x1f/0x36
__key_link_end+0x55/0x63
key_reject_and_link+0x124/0x155
keyctl_reject_key+0xb6/0xe0
keyctl_negate_key+0x10/0x12
SyS_keyctl+0x9f/0xe7
do_syscall_64+0x63/0x13a
entry_SYSCALL64_slow_path+0x25/0x25
CVE-2016-4470
Fixes: f70e2e06196a ('KEYS: Do preallocation for __key_link()')
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[ciwillia@brocade.com: backported to 3.10: adjusted context]
Signed-off-by: Charles (Chas) Williams <ciwillia@brocade.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
security/keys/key.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/keys/key.c b/security/keys/key.c
index 8fb7c7b..6595b2d 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -580,7 +580,7 @@ int key_reject_and_link(struct key *key,
mutex_unlock(&key_construction_mutex);
- if (keyring)
+ if (keyring && link_ret == 0)
__key_link_end(keyring, key->type, prealloc);
/* wake up anyone waiting for a key to be constructed */
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 034/180] usb: musb: Stop bulk endpoint while queue is rotated |
| Message-ID | <s8DDA-2Bs-17@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Andrew Goodbody <andrew.goodbody@cambrionix.com>
commit 7b2c17f829545df27a910e8d82e133c21c9a8c9c upstream.
Ensure that the endpoint is stopped by clearing REQPKT before
clearing DATAERR_NAKTIMEOUT before rotating the queue on the
dedicated bulk endpoint.
This addresses an issue where a race could result in the endpoint
receiving data before it was reprogrammed resulting in a warning
about such data from musb_rx_reinit before it was thrown away.
The data thrown away was a valid packet that had been correctly
ACKed which meant the host and device got out of sync.
Signed-off-by: Andrew Goodbody <andrew.goodbody@cambrionix.com>
Cc: stable@vger.kernel.org
Signed-off-by: Bin Liu <b-liu@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
drivers/usb/musb/musb_host.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 9d3044b..cdadbe6 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -948,9 +948,15 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep,
if (is_in) {
dma = is_dma_capable() ? ep->rx_channel : NULL;
- /* clear nak timeout bit */
+ /*
+ * Need to stop the transaction by clearing REQPKT first
+ * then the NAK Timeout bit ref MUSBMHDRC USB 2.0 HIGH-SPEED
+ * DUAL-ROLE CONTROLLER Programmer's Guide, section 9.2.2
+ */
rx_csr = musb_readw(epio, MUSB_RXCSR);
rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+ rx_csr &= ~MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR, rx_csr);
rx_csr &= ~MUSB_RXCSR_DATAERROR;
musb_writew(epio, MUSB_RXCSR, rx_csr);
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 005/180] netfilter: x_tables: fix unconditional helper |
| Message-ID | <s8DDA-2Bs-19@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Florian Westphal <fw@strlen.de>
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'.
Reported-by: Ben Hawkes <hawkes@google.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
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(-)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index ee40bd4..456fc6e 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -350,11 +350,12 @@ unsigned int arpt_do_table(struct sk_buff *skb,
}
/* 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
@@ -393,11 +394,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
|= ((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,
@@ -536,7 +536,7 @@ static bool check_underflow(const struct arpt_entry *e)
const 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)
@@ -583,9 +583,9 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *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];
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 7cfd566..a5bd3c8 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -168,11 +168,12 @@ get_entry(const void *base, unsigned int offset)
/* 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_entry *s, const struct ipt_entry *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]
@@ -467,11 +467,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
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,
@@ -698,7 +697,7 @@ static bool check_underflow(const struct ipt_entry *e)
const 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)
@@ -746,9 +745,9 @@ check_entry_size_and_hooks(struct ipt_entry *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];
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 9c6b543..fb8a146 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -195,11 +195,12 @@ get_entry(const void *base, unsigned int offset)
/* 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_entry *s, const struct ip6t_entry *e,
} 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]
@@ -477,11 +477,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
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,
@@ -709,7 +708,7 @@ static bool check_underflow(const struct ip6t_entry *e)
const 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)
@@ -757,9 +756,9 @@ check_entry_size_and_hooks(struct ip6t_entry *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];
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-08-21 18:20 +0200 |
| Subject | [PATCH 3.10 014/180] netfilter: x_tables: validate all offsets and sizes in a rule |
| Message-ID | <s8DDA-2Bs-15@gated-at.bofh.it> |
| In reply to | #1467049 |
From: Florian Westphal <fw@strlen.de>
commit 13631bfc604161a9d69cd68991dff8603edd66f9 upstream.
Validate that all matches (if any) add up to the beginning of
the target and that each match covers at least the base structure size.
The compat path should be able to safely re-use the function
as the structures only differ in alignment; added a
BUILD_BUG_ON just in case we have an arch that adds padding as well.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
net/netfilter/x_tables.c | 81 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 76 insertions(+), 5 deletions(-)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index ea14746..c482633 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -435,6 +435,47 @@ int xt_check_match(struct xt_mtchk_param *par,
}
EXPORT_SYMBOL_GPL(xt_check_match);
+/** xt_check_entry_match - check that matches end before start of target
+ *
+ * @match: beginning of xt_entry_match
+ * @target: beginning of this rules target (alleged end of matches)
+ * @alignment: alignment requirement of match structures
+ *
+ * Validates that all matches add up to the beginning of the target,
+ * and that each match covers at least the base structure size.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+static int xt_check_entry_match(const char *match, const char *target,
+ const size_t alignment)
+{
+ const struct xt_entry_match *pos;
+ int length = target - match;
+
+ if (length == 0) /* no matches */
+ return 0;
+
+ pos = (struct xt_entry_match *)match;
+ do {
+ if ((unsigned long)pos % alignment)
+ return -EINVAL;
+
+ if (length < (int)sizeof(struct xt_entry_match))
+ return -EINVAL;
+
+ if (pos->u.match_size < sizeof(struct xt_entry_match))
+ return -EINVAL;
+
+ if (pos->u.match_size > length)
+ return -EINVAL;
+
+ length -= pos->u.match_size;
+ pos = ((void *)((char *)(pos) + (pos)->u.match_size));
+ } while (length > 0);
+
+ return 0;
+}
+
#ifdef CONFIG_COMPAT
int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta)
{
@@ -590,7 +631,14 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
target_offset + sizeof(struct compat_xt_standard_target) != next_offset)
return -EINVAL;
- return 0;
+ /* compat_xt_entry match has less strict aligment requirements,
+ * otherwise they are identical. In case of padding differences
+ * we need to add compat version of xt_check_entry_match.
+ */
+ BUILD_BUG_ON(sizeof(struct compat_xt_entry_match) != sizeof(struct xt_entry_match));
+
+ return xt_check_entry_match(elems, base + target_offset,
+ __alignof__(struct compat_xt_entry_match));
}
EXPORT_SYMBOL(xt_compat_check_entry_offsets);
#endif /* CONFIG_COMPAT */
@@ -603,17 +651,39 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets);
* @target_offset: the arp/ip/ip6_t->target_offset
* @next_offset: the arp/ip/ip6_t->next_offset
*
- * validates that target_offset and next_offset are sane.
- * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
+ * validates that target_offset and next_offset are sane and that all
+ * match sizes (if any) align with the target offset.
*
* This function does not validate the targets or matches themselves, it
- * only tests that all the offsets and sizes are correct.
+ * only tests that all the offsets and sizes are correct, that all
+ * match structures are aligned, and that the last structure ends where
+ * the target structure begins.
+ *
+ * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
*
* The arp/ip/ip6t_entry structure @base must have passed following tests:
* - it must point to a valid memory location
* - base to base + next_offset must be accessible, i.e. not exceed allocated
* length.
*
+ * A well-formed entry looks like this:
+ *
+ * ip(6)t_entry match [mtdata] match [mtdata] target [tgdata] ip(6)t_entry
+ * e->elems[]-----' | |
+ * matchsize | |
+ * matchsize | |
+ * | |
+ * target_offset---------------------------------' |
+ * next_offset---------------------------------------------------'
+ *
+ * elems[]: flexible array member at end of ip(6)/arpt_entry struct.
+ * This is where matches (if any) and the target reside.
+ * target_offset: beginning of target.
+ * next_offset: start of the next rule; also: size of this rule.
+ * Since targets have a minimum size, target_offset + minlen <= next_offset.
+ *
+ * Every match stores its size, sum of sizes must not exceed target_offset.
+ *
* Return: 0 on success, negative errno on failure.
*/
int xt_check_entry_offsets(const void *base,
@@ -643,7 +713,8 @@ int xt_check_entry_offsets(const void *base,
target_offset + sizeof(struct xt_standard_target) != next_offset)
return -EINVAL;
- return 0;
+ return xt_check_entry_match(elems, base + target_offset,
+ __alignof__(struct xt_entry_match));
}
EXPORT_SYMBOL(xt_check_entry_offsets);
--
2.8.0.rc2.1.gbe9624a
[toc] | [prev] | [next] | [standalone]
Page 7 of 8 — ← Prev page 1 2 3 4 5 6 [7] 8 Next page →
Back to top | Article view | linux.kernel
csiph-web