This is the start of the stable review cycle for the 3.2.100 release. There are 140 patches in this series, which will be posted as responses to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri Mar 02 18:00:00 UTC 2018. Anything received after that time might be too late.
All the patches have also been committed to the linux-3.2.y-rc branch of https://git.kernel.org/pub/scm/linux/kernel/git/bwh/linux-stable-rc.git . A shortlog and diffstat can be found below.
Ben.
-------------
Aaron Ma (2): Input: elantech - add new icbody type 15 [10d900303f1c3a821eb0bef4e7b7ece16768fba4] Input: trackpoint - force 3 buttons if 0 button is reported [f5d07b9e98022d50720e38aa936fc11c67868ece]
Alexey Kodanev (1): dccp: don't restart ccid2_hc_tx_rto_expire() if sk in closed state [dd5684ecae3bd8e44b644f50e2c12c7e57fdfef5]
Andrew Honig (1): KVM: x86: Add memory barrier on vmcs field lookup [75f139aaf896d6fdeec2e468ddfa4b2fe469bf40]
Andrzej Hajda (1): [media] v4l2-compat-ioctl32: fix alignment for ARM64 [655e9780ab913a3a06d4a164d55e3b755524186d]
Anshuman Khandual (1): mm/mprotect: add a cond_resched() inside change_pmd_range() [4991c09c7c812dba13ea9be79a68b4565bb1fa4e]
Arnd Bergmann (1): mmc: s3mci: mark debug_regs[] as static [2bd7b4aacdb6efa5ccd4749c365c171b884791d2]
Bart Westgeest (1): staging: usbip: removed dead code from receive function [5a08c5267e45fe936452051a8c126e8418984eb7]
Ben Hutchings (2): nfsd: auth: Fix gid sorting when rootsquash enabled [1995266727fa8143897e89b55f5d3c79aa828420] of: fdt: Fix return with value in void function [not upstream; fixes incorrect backport]
Benjamin Poirier (2): e1000e: Fix e1000_check_for_copper_link_ich8lan return value. [4110e02eb45ea447ec6f5459c9934de0a273fb91] e1000e: Separate signaling for link check/link up [19110cfbb34d4af0cdfe14cd243f3b09dc95b013]
Chandan Rajendra (1): ext4: fix crash when a directory's i_size is too small [9d5afec6b8bd46d6ed821aa1579634437f58ef1f]
Christian Holl (1): USB: serial: cp210x: add new device ID ELV ALC 8xxx [d14ac576d10f865970bb1324d337e5e24d79aaf4]
Christoph Hellwig (1): scsi: dma-mapping: always provide dma_get_cache_alignment [860dd4424f344400b491b212ee4acb3a358ba9d9]
Christoph Paasch (1): tcp md5sig: Use skb's saddr when replying to an incoming segment [30791ac41927ebd3e75486f9504b6d2280463bf0]
Christophe Leroy (1): net: fs_enet: do not call phy_stop() in interrupts [f8b39039cbf2a15f2b8c9f081e1cbd5dee00aaf5]
Colin Ian King (1): usb: host: fix incorrect updating of offset [1d5a31582ef046d3b233f0da1a68ae26519b2f0a]
Cong Wang (1): 8021q: fix a memory leak for VLAN 0 device [78bbb15f2239bc8e663aa20bbe1987c91a0b75f6]
Dan Williams (1): [SCSI] libsas: remove unused ata_task_resp fields [95ac7fd189b7e81a200b4d00b2bb6669b31acf3a]
Daniel Mentz (2): media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic [a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a] media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha [025a26fa14f8fd55d50ab284a30c016a5be953d0]
Daniel Thompson (1): kdb: Fix handling of kallsyms_symbol_next() return value [c07d35338081d107e57cf37572d8cc931a8e32e2]
David Howells (1): fscache: Fix the default for fscache_maybe_release_page() [98801506552593c9b8ac11021b0cdad12cab4f6b]
David Kozub (1): USB: uas and storage: Add US_FL_BROKEN_FUA for another JMicron JMS567 ID [62354454625741f0569c2cbe45b2d192f8fd258e]
Dennis Yang (1): dm thin metadata: THIN_MAX_CONCURRENT_LOCKS should be 6 [490ae017f54e55bde382d45ea24bddfb6d1a0aaf]
Denys Vlasenko (1): include/stddef.h: Move offsetofend() from vfio.h to a generic kernel header [3876488444e71238e287459c39d7692b6f718c3e]
Diego Elio Pettenò (1): USB: serial: cp210x: add IDs for LifeScan OneTouch Verio IQ [4307413256ac1e09b8f53e8715af3df9e49beec3]
Dmitry Fleytman Dmitry Fleytman (1): usb: Add device quirk for Logitech HD Pro Webcam C925e [7f038d256c723dd390d2fca942919573995f4cfd]
Eric Biggers (3): af_key: fix buffer overread in parse_exthdrs() [4e765b4972af7b07adcb1feb16e7a525ce1f6b28] af_key: fix buffer overread in verify_address_len() [06b335cb51af018d5feeff5dd4fd53847ddb675a] crypto: algapi - fix NULL dereference in crypto_remove_spawns() [9a00674213a3f00394f4e3221b88f2d21fc05789]
Eric Dumazet (1): net/packet: fix a race in packet_bind() and packet_notifier() [15fe076edea787807a7cdc168df832544b58eba6]
Felix Fietkau (1): net: igmp: fix source address check for IGMPv3 reports [ad23b750933ea7bf962678972a286c78a8fa36aa]
Geert Uytterhoeven (1): m32r: fix 'fix breakage from "m32r: use generic ptrace_resume code"' fallout [a6b202979661eb32646048aeaad7be7b70c2cd22]
Gleb Natapov (2): KVM: VMX: do not try to reexecute failed instruction while emulating invalid guest state [991eebf9f8e523e7ff1e4d31ac80641582b2e57a] KVM: apic: fix LDR calculation in x2apic mode [7f46ddbd487e0d0528d89534fdfb31d885977804]
Greg Kroah-Hartman (1): ACPI: sbshc: remove raw pointer from printk() message [43cdd1b716b26f6af16da4e145b6578f98798bf6]
Guennadi Liakhovetski (1): [media] V4L2: fix VIDIOC_CREATE_BUFS 32-bit compatibility mode data copy-back [6ed9b28504326f8cf542e6b68245b2f7ce009216]
Guillaume Nault (1): pppoe: take ->needed_headroom of lower device into account on xmit [02612bb05e51df8489db5e94d0cf8d1c81f87b0c]
Hans Verkuil (12): [media] v4l2-compat-ioctl32: fix sparse warnings [8ae632b11775254c5e555ee8c42b7d19baeb1473] media: v4l2-compat-ioctl32.c: add capabilities field to, v4l2_input32 [037e0865c2ecbaa4558feba239ece08d7e457ec0] media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF [3ee6d040719ae09110e5cdf24d5386abe5d1b776] media: v4l2-compat-ioctl32.c: avoid sizeof(type) [333b1e9f96ce05f7498b581509bb30cde03018bf] media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32 [8ed5a59dcb47a6f76034ee760b36e089f3e82529] media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32 [a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4] media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors [d83a8243aaefe62ace433e4384a4f077bed86acb] media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type [169f24ca68bf0f247d111aef07af00dd3a02ae88] media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer [b8c601e8af2d08f733d74defa8465303391bb930] media: v4l2-compat-ioctl32.c: fix the indentation [b7b957d429f601d6d1942122b339474f31191d75] media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32 [486c521510c44a04cd756a9267e7d1e271c8a4ba] media: v4l2-ioctl.c: don't copy back the result for -ENOTTY [181a4a2d5a0a7b43cab08a70710d727e7764ccdd]
Heiko Carstens (1): s390: always save and restore all registers on context switch [fbbd7f1a51965b50dd12924841da0d478f3da71b]
Heiner Kallweit (1): eeprom: at24: check at24_read/write arguments [d9bcd462daf34aebb8de9ad7f76de0198bb5a0f0]
Helge Deller (1): parisc: Hide Diva-built-in serial aux and graphics card [bcf3f1752a622f1372d3252d0fea8855d89812e7]
Herbert Xu (5): ipv4: Avoid reading user iov twice after raw_probe_proto_opt [c008ba5bdc9fa830e1a349b20b0be5a137bdef7a] ipv4: Use standard iovec primitive in raw_probe_proto_opt [32b5913a931fd753faf3d4e1124b2bc2edb364da] xfrm: Reinject transport-mode packets through tasklet [acf568ee859f098279eadf551612f103afdacb4e] xfrm: Return error on unknown encap_type in init_state [bcfd09f7837f5240c30fd2f52ee7293516641faa] xfrm: Use __skb_queue_tail in xfrm_trans_queue [d16b46e4fd8bc6063624605f25b8c0835bb1fbe3]
Huacai Chen (2): scsi: libsas: align sata_device's rps_resp on a cacheline [c2e8fbf908afd81ad502b567a6639598f92c9b9d] scsi: use dma_get_cache_alignment() as minimum DMA alignment [90addc6b3c9cda0146fbd62a08e234c2b224a80c]
Håkon Bugge (1): rds: Fix NULL pointer dereference in __rds_rdma_map [f3069c6d33f6ae63a1668737bc78aaaa51bff7ca]
Jaejoong Kim (2): ALSA: usb-audio: Add check return value for usb_string() [89b89d121ffcf8d9546633b98ded9d18b8f75891] ALSA: usb-audio: Fix out-of-bound error [251552a2b0d454badc8f486e6d79100970c744b0]
Jan Engelhardt (1): crypto: n2 - cure use after free [203f45003a3d03eea8fa28d74cfc74c354416fdb]
Jeremy Compostella (1): i2c: core-smbus: prevent stack corruption on read I2C_BLOCK_DATA [89c6efa61f5709327ecfa24bff18e57a4e80c7fa]
Joe Thornber (2): dm btree: fix serious bug in btree_split_beneath() [bc68d0a43560e950850fc69b58f0f8254b28f6d6] dm thin metadata: introduce THIN_MAX_CONCURRENT_LOCKS [8c971178a788c70e8d6db5c3a813de1a1f54e5b7]
Johannes Berg (2): cfg80211: check dev_set_name() return value [59b179b48ce2a6076448a44531242ac2b3f6cef2] cfg80211: fix station info handling bugs [5762d7d3eda25c03cc2d9d45227be3f5ab6bec9e]
Johannes Thumshirn (1): dm mpath: simplify failure path of dm_multipath_init() [ff658e9c1aae9a84dd06d46f847dc0cd2bf0dd11]
Josef Bacik (1): btrfs: clear space cache inode generation always [8e138e0d92c6c9d3d481674fb14e3439b495be37]
Juan Zea (1): usbip: fix usbip bind writing random string after command in match_busid [544c4605acc5ae4afe7dd5914147947db182f2fb]
Kevin Cernekee (1): net: igmp: Use correct source address on IGMPv3 reports [a46182b00290839fa3fa159d54fd3237bd8669f0]
Lan Tianyu (1): KVM/x86: Check input paging mode when cs.l is set [f29810335965ac1f7bcb501ee2af5f039f792416]
Laurent Caumont (1): media: dvb: i2c transfers over usb cannot be done from stack [6d33377f2abbf9f0e561b116dd468d1c3ff36a6a]
Li Jinyue (1): futex: Prevent overflow by strengthen input validation [fbe0e839d1e22d88810f3ee3e2f1479be4c0aa4a]
Linus Torvalds (2): kbuild: add '-fno-stack-check' to kernel build options [3ce120b16cc548472f80cf8644f90eda958cf1b6] n_tty: fix EXTPROC vs ICANON interaction with TIOCINQ (aka FIONREAD) [966031f340185eddd05affcf72b740549f056348]
Liran Alon (1): KVM: x86: Don't re-execute instruction when not passing CR2 value [9b8ae63798cb97e785a667ff27e43fa6220cb734]
Marc Kleine-Budde (1): can: af_can: can_rcv(): replace WARN_ONCE by pr_warn_once [8cb68751c115d176ec851ca56ecfbb411568c9e8]
Martin Kelly (2): can: ems_usb: cancel urb on -EPIPE and -EPROTO [bd352e1adfe0d02d3ea7c8e3fb19183dc317e679] can: esd_usb2: cancel urb on -EPIPE and -EPROTO [7a31ced3de06e9878e4f9c3abe8f87d9344d8144]
Masakazu Mokuno (1): USB: core: Add type-specific length check of BOS descriptors [81cf4a45360f70528f1f64ba018d61cb5767249a]
Mathias Nyman (2): xhci: Don't add a virt_dev to the devs array before it's fully allocated [5d9b70f7d52eb14bb37861c663bae44de9521c35] xhci: Don't show incorrect WARN message about events for empty rings [e4ec40ec4b260efcca15089de4285a0a3411259b]
Matt Wilson (1): serial: 8250_pci: Add Amazon PCI serial device ID [3bfd1300abfe3adb18e84a89d97a0e82a22124bb]
Max Schulze (1): USB: serial: ftdi_sio: add id for Airbus DS P8GR [c6a36ad383559a60a249aa6016cebf3cb8b6c485]
Mohamed Ghannam (1): net: ipv4: fix for a race condition in raw_sendmsg [8f659a03a0ba9289b9aeb9b4470e6fb263d6f483]
Monty_pavel@Sina.Com (1): dm: fix various targets to dm_register_target after module __init resources created [7e6358d244e4706fe612a77b9c36519a33600ac0]
Nicolai Stange (1): net: ipv4: emulate READ_ONCE() on ->hdrincl bit-field in raw_sendmsg() [20b50d79974ea3192e8c3ab7faf4e536e5f14d8f]
Nikolay Aleksandrov (1): net: bridge: fix early call to br_stp_change_bridge_id and plug newlink leaks [84aeb437ab98a2bce3d4b2111c79723aedfceb33]
Nikolay Borisov (1): btrfs: Fix possible off-by-one in btrfs_search_path_in_tree [c8bcbfbd239ed60a6562964b58034ac8a25f4c31]
Nogah Frankel (1): net_sched: red: Avoid illegal values [8afa10cbe281b10371fee5a87ab266e48d71a7f9]
Oliver Neukum (2): USB: usbfs: Filter flags passed in from user space [446f666da9f019ce2ffd03800995487e79a91462] usb: add RESET_RESUME for ELSA MicroLink 56K [b9096d9f15c142574ebebe8fbb137012bb9d99c2]
Oliver Stäbler (1): can: ti_hecc: Fix napi poll return value for repoll [f6c23b174c3c96616514827407769cbcfc8005cf]
Oscar Campos (1): Input: trackpoint - assume 3 buttons when buttons detection fails [293b915fd9bebf33cdc906516fb28d54649a25ac]
Pete Zaitcev (1): USB: fix usbmon BUG trigger [46eb14a6e1585d99c1b9f58d0e7389082a5f466b]
Rafael J. Wysocki (1): PCI / PM: Force devices to D0 in pci_pm_thaw_noirq() [5839ee7389e893a31e4e3c9cf17b50d14103c902]
Robb Glasser (1): ALSA: pcm: prevent UAF in snd_pcm_info [362bca57f5d78220f8b5907b875961af9436e229]
Robert Lippert (1): hwmon: (pmbus) Use 64bit math for DIRECT format values [bd467e4eababe4c04272c1e646f066db02734c79]
Robin Murphy (1): iommu/vt-d: Fix scatterlist offset handling [29a90b70893817e2f2bb3cea40a29f5308e21b21]
SZ Lin (1): USB: serial: option: adding support for YUGA CLM920-NC5 [3920bb713038810f25770e7545b79f204685c8f2]
Sebastian Sjoholm (1): USB: serial: option: add Quectel BG96 id [c654b21ede93845863597de9ad774fd30db5f2ab]
Sergei Shtylyov (2): SolutionEngine771x: add Ether TSU resource [f9a531d6731d74f1e24298d9641c2dc1fef2631b] SolutionEngine771x: fix Ether platform data [195e2addbce09e5afbc766efc1e6567c9ce840d3]
Shuah Khan (4): usbip: prevent leaking socket pointer address in messages [90120d15f4c397272aaf41077960a157fc4212bf] usbip: remove kernel addresses from usb device and urb debug msgs [e1346fd87c71a1f61de1fe476ec8df1425ac931c] usbip: stub: stop printing kernel pointer addresses in messages [248a22044366f588d46754c54dfe29ffe4f8b4df] usbip: vhci: stop printing kernel pointer addresses in messages [8272d099d05f7ab2776cf56a2ab9f9443be18907]
Steve Wise (1): iw_cxgb4: Only validate the MSN for successful completions [f55688c45442bc863f40ad678c638785b26cdce6]
Steven Rostedt (1): ring-buffer: Mask out the info bits when returning buffer page length [45d8b80c2ac5d21cd1e2954431fb676bc2b1e099]
Sven Eckelmann (1): batman-adv: Fix lock for ogm cnt access in batadv_iv_ogm_calc_tq [5ba7dcfe77037b67016263ea597a8b431692ecab]
Takashi Iwai (13): ACPI: APEI / ERST: Fix missing error handling in erst_reader() [bb82e0b4a7e96494f0c1004ce50cec3d7b5fb3d1] ALSA: aloop: Fix inconsistent format due to incomplete rule [b088b53e20c7d09b5ab84c5688e609f478e5c417] ALSA: aloop: Fix racy hw constraints adjustment [898dfe4687f460ba337a01c11549f87269a13fa2] ALSA: aloop: Release cable upon open error path [9685347aa0a5c2869058ca6ab79fd8e93084a67f] ALSA: pcm: Abort properly at pending signal in OSS read/write loops [29159a4ed7044c52e3e2cf1a9fb55cec4745c60b] ALSA: pcm: Add missing error checks in OSS emulation plugin builder [6708913750344a900f2e73bfe4a4d6dbbce4fe8d] ALSA: pcm: Allow aborting mutex lock at OSS read/write loops [900498a34a3ac9c611e9b425094c8106bdd7dc1c] ALSA: pcm: Remove incorrect snd_BUG_ON() usages [fe08f34d066f4404934a509b6806db1a4f700c86] ALSA: pcm: Remove yet superfluous WARN_ON() [23b19b7b50fe1867da8d431eea9cd3e4b6328c2c] ALSA: rawmidi: Avoid racy info ioctl via ctl device [c1cfd9025cc394fd137a01159d74335c5ac978ce] ALSA: seq: Fix regression by incorrect ioctl_mutex usages [not upstream; fixes incorrect backport] ALSA: seq: Remove spurious WARN_ON() at timer check [43a3542870328601be02fcc9d27b09db467336ef] ALSA: usb-audio: Fix the missing ctl name suffix at parsing SU [5a15f289ee87eaf33f13f08a4909ec99d837ec5f]
Thiago Rafael Becker (1): kernel: make groups_sort calling a responsibility group_info allocators [bdcf0a423ea1c40bbb40e7ee483b50fc8aa3d758]
Thomas Gleixner (3): hrtimer: Reset hrtimer cpu base proper on CPU hotplug [d5421ea43d30701e03cadc56a38854c36a8b4433] posix-timer: Properly check sigevent->sigev_notify [cef31d9af908243421258f1df35a4a644604efbe] x86/mce: Make machine check speculation protected [6f41c34d69eb005e7848716bbcafc979b35037d5]
Tianyu Lan (1): KVM/x86: Fix wrong macro references of X86_CR0_PG_BIT and X86_CR4_PAE_BIT in kvm_valid_sregs() [37b95951c58fdf08dc10afa9d02066ed9f176fb5]
Tiffany Lin (1): [media] media: v4l2-compat-ioctl32: fix missing reserved field copy in put_v4l2_create32 [baf43c6eace43868e490f18560287fa3481b2159]
Wanpeng Li (1): KVM: X86: Fix load RFLAGS w/o the fixed bit [d73235d17ba63b53dc0e1051dbc10a1f1be91b71]
William Breathitt Gray (1): isa: Prevent NULL dereference in isa_bus driver callbacks [5a244727f428a06634f22bb890e78024ab0c89f3]
Xin Long (3): sctp: do not allow the v4 socket to bind a v4mapped v6 address [c5006b8aa74599ce19104b31d322d2ea9ff887cc] sctp: return error if the asoc has been peeled off in sctp_wait_for_sndbuf [a0ff660058b88d12625a783ce9e5c1371c87951f] sctp: use the right sk after waking up from wait_buf sleep [cea0cc80a6777beb6eb643d4ad53690e1ad1d4ff]
Zhao Qiang (1): net: phy: marvell: Limit 88m1101 autoneg errata to 88E1145 as well. [c505873eaece2b4aefd07d339dc7e1400e0235ac]
Makefile | 7 +- arch/m32r/kernel/ptrace.c | 7 +- arch/s390/include/asm/system.h | 18 +- arch/s390/kernel/compat_linux.c | 1 + arch/sh/boards/mach-se/770x/setup.c | 24 +- arch/sh/include/mach-se/mach/se.h | 1 + arch/x86/include/asm/kvm_host.h | 4 +- arch/x86/include/asm/traps.h | 1 + arch/x86/kernel/cpu/mcheck/mce.c | 5 + arch/x86/kernel/entry_64.S | 2 +- arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/vmx.c | 12 +- arch/x86/kvm/x86.c | 38 +- crypto/algapi.c | 12 + drivers/acpi/apei/erst.c | 2 +- drivers/acpi/sbshc.c | 4 +- drivers/base/isa.c | 10 +- drivers/crypto/n2_core.c | 3 + drivers/hwmon/pmbus/pmbus_core.c | 21 +- drivers/i2c/i2c-core.c | 13 +- drivers/infiniband/hw/cxgb4/cq.c | 6 +- drivers/input/mouse/elantech.c | 2 +- drivers/input/mouse/trackpoint.c | 7 +- drivers/iommu/intel-iommu.c | 8 +- drivers/md/dm-mpath.c | 34 +- drivers/md/dm-snap.c | 48 +- drivers/md/dm-thin-metadata.c | 18 +- drivers/md/persistent-data/dm-btree.c | 19 +- drivers/media/dvb/dvb-usb/dibusb-common.c | 16 +- drivers/media/video/Makefile | 7 +- drivers/media/video/v4l2-compat-ioctl32.c | 973 +++++++++++++-------- drivers/media/video/v4l2-ioctl.c | 6 +- drivers/misc/eeprom/at24.c | 6 + drivers/mmc/host/s3cmci.c | 6 +- drivers/net/can/ti_hecc.c | 3 + drivers/net/can/usb/ems_usb.c | 2 + drivers/net/can/usb/esd_usb2.c | 2 + .../net/ethernet/freescale/fs_enet/fs_enet-main.c | 16 +- drivers/net/ethernet/freescale/fs_enet/fs_enet.h | 1 + drivers/net/ethernet/intel/e1000e/ich8lan.c | 10 +- drivers/net/ethernet/intel/e1000e/lib.c | 11 +- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- drivers/net/phy/marvell.c | 2 +- drivers/net/ppp/pppoe.c | 11 +- drivers/of/fdt.c | 2 +- drivers/parisc/lba_pci.c | 33 + drivers/pci/pci-driver.c | 7 +- drivers/scsi/libsas/sas_ata.c | 4 - drivers/scsi/scsi_lib.c | 10 +- drivers/staging/usbip/stub_dev.c | 3 +- drivers/staging/usbip/stub_main.c | 5 +- drivers/staging/usbip/stub_rx.c | 9 +- drivers/staging/usbip/stub_tx.c | 4 +- drivers/staging/usbip/usbip_common.c | 85 +- drivers/staging/usbip/usbip_common.h | 3 +- drivers/staging/usbip/userspace/src/utils.c | 9 +- drivers/staging/usbip/vhci_hcd.c | 12 +- drivers/staging/usbip/vhci_rx.c | 26 +- drivers/staging/usbip/vhci_tx.c | 3 +- drivers/tty/n_tty.c | 4 +- drivers/tty/serial/8250_pci.c | 3 + drivers/usb/core/config.c | 16 +- drivers/usb/core/devio.c | 14 +- drivers/usb/core/quirks.c | 6 +- drivers/usb/host/ehci-dbg.c | 2 +- drivers/usb/host/xhci-mem.c | 17 +- drivers/usb/host/xhci-ring.c | 12 +- drivers/usb/mon/mon_bin.c | 8 +- drivers/usb/serial/cp210x.c | 2 + drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 + drivers/usb/serial/option.c | 12 + drivers/usb/storage/unusual_devs.h | 7 + fs/btrfs/extent-tree.c | 14 +- fs/btrfs/ioctl.c | 2 +- fs/ext4/namei.c | 4 + fs/nfsd/auth.c | 3 + include/asm-generic/dma-mapping-broken.h | 3 - include/linux/cred.h | 1 + include/linux/dma-mapping.h | 2 - include/linux/fscache.h | 2 +- include/linux/stddef.h | 10 + include/linux/usb/ch9.h | 2 + include/net/red.h | 11 + include/net/xfrm.h | 1 + include/scsi/libsas.h | 9 +- kernel/debug/kdb/kdb_io.c | 2 +- kernel/futex.c | 3 + kernel/groups.c | 5 +- kernel/hrtimer.c | 2 + kernel/posix-timers.c | 37 +- kernel/trace/ring_buffer.c | 6 +- kernel/uid16.c | 1 + mm/mprotect.c | 6 +- net/8021q/vlan.c | 6 +- net/batman-adv/bat_iv_ogm.c | 4 +- net/bridge/br_netlink.c | 7 +- net/can/af_can.c | 12 +- net/dccp/ccids/ccid2.c | 3 + net/ipv4/esp4.c | 1 + net/ipv4/igmp.c | 20 +- net/ipv4/raw.c | 119 ++- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/xfrm4_input.c | 11 +- net/ipv6/esp6.c | 3 +- net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/xfrm6_input.c | 9 +- net/key/af_key.c | 8 + net/packet/af_packet.c | 5 + net/rds/rdma.c | 2 +- net/sched/sch_choke.c | 3 + net/sched/sch_gred.c | 3 + net/sched/sch_red.c | 2 + net/sctp/socket.c | 27 +- net/sunrpc/auth_gss/svcauth_gss.c | 1 + net/sunrpc/svcauth_unix.c | 2 + net/wireless/core.c | 7 +- net/wireless/wext-compat.c | 3 +- net/xfrm/xfrm_input.c | 56 ++ sound/core/oss/pcm_oss.c | 41 +- sound/core/oss/pcm_plugin.c | 14 +- sound/core/pcm.c | 2 + sound/core/pcm_lib.c | 5 +- sound/core/rawmidi.c | 15 +- sound/core/seq/seq_clientmgr.c | 15 +- sound/core/seq/seq_timer.c | 2 +- sound/drivers/aloop.c | 98 ++- sound/usb/mixer.c | 27 +- 128 files changed, 1509 insertions(+), 882 deletions(-)
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner tglx@linutronix.de
commit cef31d9af908243421258f1df35a4a644604efbe upstream.
timer_create() specifies via sigevent->sigev_notify the signal delivery for the new timer. The valid modes are SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD and (SIGEV_SIGNAL | SIGEV_THREAD_ID).
The sanity check in good_sigevent() is only checking the valid combination for the SIGEV_THREAD_ID bit, i.e. SIGEV_SIGNAL, but if SIGEV_THREAD_ID is not set it accepts any random value.
This has no real effects on the posix timer and signal delivery code, but it affects show_timer() which handles the output of /proc/$PID/timers. That function uses a string array to pretty print sigev_notify. The access to that array has no bound checks, so random sigev_notify cause access beyond the array bounds.
Add proper checks for the valid notify modes and remove the SIGEV_THREAD_ID masking from various code pathes as SIGEV_NONE can never be set in combination with SIGEV_THREAD_ID.
Reported-by: Eric Biggers ebiggers3@gmail.com Reported-by: Dmitry Vyukov dvyukov@google.com Reported-by: Alexey Dobriyan adobriyan@gmail.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Cc: John Stultz john.stultz@linaro.org [bwh: Backported to 3.2: - Add sig_none variable in common_timer_get(), added earlier upstream - Adjust filename, context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- kernel/posix-timers.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)
--- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -440,17 +440,22 @@ static struct pid *good_sigevent(sigeven { struct task_struct *rtn = current->group_leader;
- if ((event->sigev_notify & SIGEV_THREAD_ID ) && - (!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) || - !same_thread_group(rtn, current) || - (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL)) + switch (event->sigev_notify) { + case SIGEV_SIGNAL | SIGEV_THREAD_ID: + rtn = find_task_by_vpid(event->sigev_notify_thread_id); + if (!rtn || !same_thread_group(rtn, current)) + return NULL; + /* FALLTHRU */ + case SIGEV_SIGNAL: + case SIGEV_THREAD: + if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX) + return NULL; + /* FALLTHRU */ + case SIGEV_NONE: + return task_pid(rtn); + default: return NULL; - - if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) && - ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX))) - return NULL; - - return task_pid(rtn); + } }
void posix_timers_register_clock(const clockid_t clock_id, @@ -683,16 +688,17 @@ common_timer_get(struct k_itimer *timr, { ktime_t now, remaining, iv; struct hrtimer *timer = &timr->it.real.timer; + bool sig_none;
memset(cur_setting, 0, sizeof(struct itimerspec));
+ sig_none = timr->it_sigev_notify == SIGEV_NONE; iv = timr->it.real.interval;
/* interval timer ? */ if (iv.tv64) cur_setting->it_interval = ktime_to_timespec(iv); - else if (!hrtimer_active(timer) && - (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) + else if (!hrtimer_active(timer) && !sig_none) return;
now = timer->base->get_time(); @@ -702,8 +708,7 @@ common_timer_get(struct k_itimer *timr, * timer move the expiry time forward by intervals, so * expiry is > now. */ - if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || - (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) + if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none)) timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
remaining = __hrtimer_expires_remaining_adjusted(timer, now); @@ -713,7 +718,7 @@ common_timer_get(struct k_itimer *timr, * A single shot SIGEV_NONE timer must return 0, when * it is expired ! */ - if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) + if (!sig_none) cur_setting->it_value.tv_nsec = 1; } else cur_setting->it_value = ktime_to_timespec(remaining); @@ -811,7 +816,7 @@ common_timer_set(struct k_itimer *timr, timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
/* SIGEV_NONE timers are not queued ! See common_timer_get */ - if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { + if (timr->it_sigev_notify == SIGEV_NONE) { /* Setup correct expiry time for relative timers */ if (mode == HRTIMER_MODE_REL) { hrtimer_add_expires(timer, timer->base->get_time());
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Thumshirn morbidrsa@gmail.com
commit ff658e9c1aae9a84dd06d46f847dc0cd2bf0dd11 upstream.
Currently the cleanup of all error cases are open-coded. Introduce a common exit path and labels.
Signed-off-by: Johannes Thumshirn morbidrsa@gmail.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/md/dm-mpath.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
--- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1661,16 +1661,15 @@ static int __init dm_multipath_init(void r = dm_register_target(&multipath_target); if (r < 0) { DMERR("register failed %d", r); - kmem_cache_destroy(_mpio_cache); - return -EINVAL; + r = -EINVAL; + goto bad_register_target; }
kmultipathd = alloc_workqueue("kmpathd", WQ_MEM_RECLAIM, 0); if (!kmultipathd) { DMERR("failed to create workqueue kmpathd"); - dm_unregister_target(&multipath_target); - kmem_cache_destroy(_mpio_cache); - return -ENOMEM; + r = -ENOMEM; + goto bad_alloc_kmultipathd; }
/* @@ -1683,16 +1682,23 @@ static int __init dm_multipath_init(void WQ_MEM_RECLAIM); if (!kmpath_handlerd) { DMERR("failed to create workqueue kmpath_handlerd"); - destroy_workqueue(kmultipathd); - dm_unregister_target(&multipath_target); - kmem_cache_destroy(_mpio_cache); - return -ENOMEM; + r = -ENOMEM; + goto bad_alloc_kmpath_handlerd; }
DMINFO("version %u.%u.%u loaded", multipath_target.version[0], multipath_target.version[1], multipath_target.version[2]);
+ return 0; + +bad_alloc_kmpath_handlerd: + destroy_workqueue(kmultipathd); +bad_alloc_kmultipathd: + dm_unregister_target(&multipath_target); +bad_register_target: + kmem_cache_destroy(_mpio_cache); + return r; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Laurent Caumont lcaumont2@gmail.com
commit 6d33377f2abbf9f0e561b116dd468d1c3ff36a6a upstream.
Signed-off-by: Laurent Caumont lcaumont2@gmail.com Signed-off-by: Sean Young sean@mess.org Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/dvb/dvb-usb/dibusb-common.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -169,8 +169,20 @@ EXPORT_SYMBOL(dibusb_i2c_algo);
int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) { - u8 wbuf[1] = { offs }; - return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1); + u8 *buf; + int rc; + + buf = kmalloc(2, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf[0] = offs; + + rc = dibusb_i2c_msg(d, 0x50, &buf[0], 1, &buf[1], 1); + *val = buf[1]; + kfree(buf); + + return rc; } EXPORT_SYMBOL(dibusb_read_eeprom_byte);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Aaron Ma aaron.ma@canonical.com
commit 10d900303f1c3a821eb0bef4e7b7ece16768fba4 upstream.
The touchpad of Lenovo Thinkpad L480 reports it's version as 15.
Signed-off-by: Aaron Ma aaron.ma@canonical.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/input/mouse/elantech.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1284,7 +1284,7 @@ static int elantech_set_properties(struc case 5: etd->hw_version = 3; break; - case 6 ... 14: + case 6 ... 15: etd->hw_version = 4; break; default:
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Bart Westgeest bart@elbrys.com
commit 5a08c5267e45fe936452051a8c126e8418984eb7 upstream.
The usbip_xmit function supported sending and receiving data, however the sending part of the function was never used/executed. Renamed the function to usbip_recv, and removed the unused code.
Signed-off-by: Bart Westgeest bart@elbrys.com Signed-off-by: Greg Kroah-Hartman gregkh@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/staging/usbip/stub_rx.c | 2 +- drivers/staging/usbip/usbip_common.c | 61 ++++++++++-------------------------- drivers/staging/usbip/usbip_common.h | 3 +- drivers/staging/usbip/vhci_rx.c | 2 +- 4 files changed, 20 insertions(+), 48 deletions(-)
--- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -586,7 +586,7 @@ static void stub_rx_pdu(struct usbip_dev memset(&pdu, 0, sizeof(pdu));
/* 1. receive a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0); + ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu)); if (ret != sizeof(pdu)) { dev_err(dev, "recv a header, %d\n", ret); usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -334,9 +334,8 @@ void usbip_dump_header(struct usbip_head } EXPORT_SYMBOL_GPL(usbip_dump_header);
-/* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */ -int usbip_xmit(int send, struct socket *sock, char *buf, int size, - int msg_flags) +/* Receive data over TCP/IP. */ +int usbip_recv(struct socket *sock, void *buf, int size) { int result; struct msghdr msg; @@ -355,19 +354,6 @@ int usbip_xmit(int send, struct socket * return -EINVAL; }
- if (usbip_dbg_flag_xmit) { - if (send) { - if (!in_interrupt()) - pr_debug("%-10s:", current->comm); - else - pr_debug("interrupt :"); - - pr_debug("sending... , sock %p, buf %p, size %d, " - "msg_flags %d\n", sock, buf, size, msg_flags); - usbip_dump_buffer(buf, size); - } - } - do { sock->sk->sk_allocation = GFP_NOIO; iov.iov_base = buf; @@ -377,42 +363,30 @@ int usbip_xmit(int send, struct socket * msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_namelen = 0; - msg.msg_flags = msg_flags | MSG_NOSIGNAL; - - if (send) - result = kernel_sendmsg(sock, &msg, &iov, 1, size); - else - result = kernel_recvmsg(sock, &msg, &iov, 1, size, - MSG_WAITALL); + msg.msg_flags = MSG_NOSIGNAL;
+ result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); if (result <= 0) { - pr_debug("%s sock %p buf %p size %u ret %d total %d\n", - send ? "send" : "receive", sock, buf, size, - result, total); + pr_debug("receive sock %p buf %p size %u ret %d total %d\n", + sock, buf, size, result, total); goto err; }
size -= result; buf += result; total += result; - } while (size > 0);
if (usbip_dbg_flag_xmit) { - if (!send) { - if (!in_interrupt()) - pr_debug("%-10s:", current->comm); - else - pr_debug("interrupt :"); - - pr_debug("receiving....\n"); - usbip_dump_buffer(bp, osize); - pr_debug("received, osize %d ret %d size %d total %d\n", - osize, result, size, total); - } + if (!in_interrupt()) + pr_debug("%-10s:", current->comm); + else + pr_debug("interrupt :");
- if (send) - pr_debug("send, total %d\n", total); + pr_debug("receiving....\n"); + usbip_dump_buffer(bp, osize); + pr_debug("received, osize %d ret %d size %d total %d\n", + osize, result, size, total); }
return total; @@ -420,7 +394,7 @@ int usbip_xmit(int send, struct socket * err: return result; } -EXPORT_SYMBOL_GPL(usbip_xmit); +EXPORT_SYMBOL_GPL(usbip_recv);
struct socket *sockfd_to_socket(unsigned int sockfd) { @@ -712,7 +686,7 @@ int usbip_recv_iso(struct usbip_device * if (!buff) return -ENOMEM;
- ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0); + ret = usbip_recv(ud->tcp_socket, buff, size); if (ret != size) { dev_err(&urb->dev->dev, "recv iso_frame_descriptor, %d\n", ret); @@ -831,8 +805,7 @@ int usbip_recv_xbuff(struct usbip_device } }
- ret = usbip_xmit(0, ud->tcp_socket, (char *)urb->transfer_buffer, - size, 0); + ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size); if (ret != size) { dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret); if (ud->side == USBIP_STUB) { --- a/drivers/staging/usbip/usbip_common.h +++ b/drivers/staging/usbip/usbip_common.h @@ -306,8 +306,7 @@ void setreuse(struct socket *); void usbip_dump_urb(struct urb *purb); void usbip_dump_header(struct usbip_header *pdu);
-int usbip_xmit(int send, struct socket *sock, char *buf, int size, - int msg_flags); +int usbip_recv(struct socket *sock, void *buf, int size); struct socket *sockfd_to_socket(unsigned int sockfd);
void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -205,7 +205,7 @@ static void vhci_rx_pdu(struct usbip_dev memset(&pdu, 0, sizeof(pdu));
/* 1. receive a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0); + ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu)); if (ret < 0) { if (ret == -ECONNRESET) pr_info("connection reset by peer\n");
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Chandan Rajendra chandan@linux.vnet.ibm.com
commit 9d5afec6b8bd46d6ed821aa1579634437f58ef1f upstream.
On a ppc64 machine, when mounting a fuzzed ext2 image (generated by fsfuzzer) the following call trace is seen,
VFS: brelse: Trying to free free buffer WARNING: CPU: 1 PID: 6913 at /root/repos/linux/fs/buffer.c:1165 .__brelse.part.6+0x24/0x40 .__brelse.part.6+0x20/0x40 (unreliable) .ext4_find_entry+0x384/0x4f0 .ext4_lookup+0x84/0x250 .lookup_slow+0xdc/0x230 .walk_component+0x268/0x400 .path_lookupat+0xec/0x2d0 .filename_lookup+0x9c/0x1d0 .vfs_statx+0x98/0x140 .SyS_newfstatat+0x48/0x80 system_call+0x58/0x6c
This happens because the directory that ext4_find_entry() looks up has inode->i_size that is less than the block size of the filesystem. This causes 'nblocks' to have a value of zero. ext4_bread_batch() ends up not reading any of the directory file's blocks. This renders the entries in bh_use[] array to continue to have garbage data. buffer_uptodate() on bh_use[0] can then return a zero value upon which brelse() function is invoked.
This commit fixes the bug by returning -ENOENT when the directory file has no associated blocks.
Reported-by: Abdul Haleem abdhalee@linux.vnet.ibm.com Signed-off-by: Chandan Rajendra chandan@linux.vnet.ibm.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- fs/ext4/namei.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -892,6 +892,10 @@ static struct buffer_head * ext4_find_en "falling back\n")); } nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb); + if (!nblocks) { + ret = NULL; + goto cleanup_and_exit; + } start = EXT4_I(dir)->i_dir_start_lookup; if (start >= nblocks) start = 0;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Stäbler oliver.staebler@bytesatwork.ch
commit f6c23b174c3c96616514827407769cbcfc8005cf upstream.
After commit d75b1ade567f ("net: less interrupt masking in NAPI") napi repoll is done only when work_done == budget. So we need to return budget if there are still packets to receive.
Signed-off-by: Oliver Stäbler oliver.staebler@bytesatwork.ch Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/net/can/ti_hecc.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -651,6 +651,9 @@ static int ti_hecc_rx_poll(struct napi_s mbx_mask = hecc_read(priv, HECC_CANMIM); mbx_mask |= HECC_TX_MBOX_MASK; hecc_write(priv, HECC_CANMIM, mbx_mask); + } else { + /* repoll is done only if whole budget is used */ + num_pkts = quota; }
return num_pkts;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: William Breathitt Gray vilhelm.gray@gmail.com
commit 5a244727f428a06634f22bb890e78024ab0c89f3 upstream.
The isa_driver structure for an isa_bus device is stored in the device platform_data member of the respective device structure. This platform_data member may be reset to NULL if isa_driver match callback for the device fails, indicating a device unsupported by the ISA driver.
This patch fixes a possible NULL pointer dereference if one of the isa_driver callbacks to attempted for an unsupported device. This error should not occur in practice since ISA devices are typically manually configured and loaded by the users, but we may as well prevent this error from popping up for the 0day testers.
Fixes: a5117ba7da37 ("[PATCH] Driver model: add ISA bus") Signed-off-by: William Breathitt Gray vilhelm.gray@gmail.com Acked-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/base/isa.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
--- a/drivers/base/isa.c +++ b/drivers/base/isa.c @@ -39,7 +39,7 @@ static int isa_bus_probe(struct device * { struct isa_driver *isa_driver = dev->platform_data;
- if (isa_driver->probe) + if (isa_driver && isa_driver->probe) return isa_driver->probe(dev, to_isa_dev(dev)->id);
return 0; @@ -49,7 +49,7 @@ static int isa_bus_remove(struct device { struct isa_driver *isa_driver = dev->platform_data;
- if (isa_driver->remove) + if (isa_driver && isa_driver->remove) return isa_driver->remove(dev, to_isa_dev(dev)->id);
return 0; @@ -59,7 +59,7 @@ static void isa_bus_shutdown(struct devi { struct isa_driver *isa_driver = dev->platform_data;
- if (isa_driver->shutdown) + if (isa_driver && isa_driver->shutdown) isa_driver->shutdown(dev, to_isa_dev(dev)->id); }
@@ -67,7 +67,7 @@ static int isa_bus_suspend(struct device { struct isa_driver *isa_driver = dev->platform_data;
- if (isa_driver->suspend) + if (isa_driver && isa_driver->suspend) return isa_driver->suspend(dev, to_isa_dev(dev)->id, state);
return 0; @@ -77,7 +77,7 @@ static int isa_bus_resume(struct device { struct isa_driver *isa_driver = dev->platform_data;
- if (isa_driver->resume) + if (isa_driver && isa_driver->resume) return isa_driver->resume(dev, to_isa_dev(dev)->id);
return 0;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shuah Khan shuahkh@osg.samsung.com
commit 8272d099d05f7ab2776cf56a2ab9f9443be18907 upstream.
Remove and/or change debug, info. and error messages to not print kernel pointer addresses.
Signed-off-by: Shuah Khan shuahkh@osg.samsung.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: adjust filenames, context, indentation] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/staging/usbip/vhci_hcd.c | 10 ---------- drivers/staging/usbip/vhci_rx.c | 23 +++++++++++------------ drivers/staging/usbip/vhci_tx.c | 3 ++- 3 files changed, 13 insertions(+), 23 deletions(-)
--- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -516,9 +516,6 @@ static int vhci_urb_enqueue(struct usb_h unsigned long flags; struct vhci_device *vdev;
- usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", - hcd, urb, mem_flags); - /* patch to usb_sg_init() is in 2.5.60 */ BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
@@ -677,8 +674,6 @@ static int vhci_urb_dequeue(struct usb_h struct vhci_priv *priv; struct vhci_device *vdev;
- pr_info("dequeue a urb %p\n", urb); - spin_lock_irqsave(&the_controller->lock, flags);
priv = urb->hcpriv; @@ -707,7 +702,6 @@ static int vhci_urb_dequeue(struct usb_h
spin_lock_irqsave(&vdev->priv_lock, flags2);
- pr_info("device %p seems to be disconnected\n", vdev); list_del(&priv->list); kfree(priv); urb->hcpriv = NULL; @@ -719,8 +713,6 @@ static int vhci_urb_dequeue(struct usb_h * vhci_rx will receive RET_UNLINK and give back the URB. * Otherwise, we give back it here. */ - pr_info("gives back urb %p\n", urb); - usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock_irqrestore(&the_controller->lock, flags); @@ -751,8 +743,6 @@ static int vhci_urb_dequeue(struct usb_h
unlink->unlink_seqnum = priv->seqnum;
- pr_info("device %p seems to be still connected\n", vdev); - /* send cmd_unlink and try to cancel the pending URB in the * peer */ list_add_tail(&unlink->list, &vdev->unlink_tx); --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -35,21 +35,19 @@ struct urb *pickup_urb_and_free_priv(str urb = priv->urb; status = urb->status;
- usbip_dbg_vhci_rx("find urb %p vurb %p seqnum %u\n", - urb, priv, seqnum); + usbip_dbg_vhci_rx("find urb seqnum %u\n", seqnum);
/* TODO: fix logic here to improve indent situtation */ if (status != -EINPROGRESS) { if (status == -ENOENT || status == -ECONNRESET) - dev_info(&urb->dev->dev, - "urb %p was unlinked " - "%ssynchronuously.\n", urb, - status == -ENOENT ? "" : "a"); + dev_dbg(&urb->dev->dev, + "urb seq# %u was unlinked %ssynchronuously\n", + seqnum, status == -ENOENT ? "" : "a"); else - dev_info(&urb->dev->dev, - "urb %p may be in a error, " - "status %d\n", urb, status); + dev_dbg(&urb->dev->dev, + "urb seq# %u may be in a error, status %d\n", + seqnum, status); }
list_del(&priv->list); @@ -75,8 +73,8 @@ static void vhci_recv_ret_submit(struct spin_unlock(&vdev->priv_lock);
if (!urb) { - pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum); - pr_info("max seqnum %d\n", + pr_err("cannot find a urb of seqnum %u max seqnum %d\n", + pdu->base.seqnum, atomic_read(&the_controller->seqnum)); usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); return; @@ -99,7 +97,7 @@ static void vhci_recv_ret_submit(struct if (usbip_dbg_flag_vhci_rx) usbip_dump_urb(urb);
- usbip_dbg_vhci_rx("now giveback urb %p\n", urb); + usbip_dbg_vhci_rx("now giveback urb %u\n", pdu->base.seqnum);
spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); @@ -165,7 +163,7 @@ static void vhci_recv_ret_unlink(struct pr_info("the urb (seqnum %d) was already given backed\n", pdu->base.seqnum); } else { - usbip_dbg_vhci_rx("now giveback urb %p\n", urb); + usbip_dbg_vhci_rx("now giveback urb %d\n", pdu->base.seqnum);
/* If unlink is succeed, status is -ECONNRESET */ urb->status = pdu->u.ret_unlink.status; --- a/drivers/staging/usbip/vhci_tx.c +++ b/drivers/staging/usbip/vhci_tx.c @@ -83,7 +83,8 @@ static int vhci_send_cmd_submit(struct v memset(&msg, 0, sizeof(msg)); memset(&iov, 0, sizeof(iov));
- usbip_dbg_vhci_tx("setup txdata urb %p\n", urb); + usbip_dbg_vhci_tx("setup txdata urb seqnum %lu\n", + priv->seqnum);
/* 1. setup usbip_header */ setup_cmd_submit_pdu(&pdu_header, urb);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 5a15f289ee87eaf33f13f08a4909ec99d837ec5f upstream.
The commit 89b89d121ffc ("ALSA: usb-audio: Add check return value for usb_string()") added the check of the return value from snd_usb_copy_string_desc(), which is correct per se, but it introduced a regression. In the original code, either the "Clock Source", "Playback Source" or "Capture Source" suffix is added after the terminal string, while the commit changed it to add the suffix only when get_term_name() is failing. It ended up with an incorrect ctl name like "PCM" instead of "PCM Capture Source".
Also, even the original code has a similar bug: when the ctl name is generated from snd_usb_copy_string_desc() for the given iSelector, it also doesn't put the suffix.
This patch addresses these issues: the suffix is added always when no static mapping is found. Also the patch tries to put more comments and cleans up the if/else block for better readability in order to avoid the same pitfall again.
Fixes: 89b89d121ffc ("ALSA: usb-audio: Add check return value for usb_string()") Reported-and-tested-by: Mauro Santos registo.mailling@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/usb/mixer.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
--- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1923,20 +1923,25 @@ static int parse_audio_selector_unit(str kctl->private_value = (unsigned long)namelist; kctl->private_free = usb_mixer_selector_elem_free;
- nameid = uac_selector_unit_iSelector(desc); + /* check the static mapping table at first */ len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); - if (len) - ; - else if (nameid) - len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, - sizeof(kctl->id.name)); - else - len = get_term_name(state, &state->oterm, - kctl->id.name, sizeof(kctl->id.name), 0); - if (!len) { - strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); + /* no mapping ? */ + /* if iSelector is given, use it */ + nameid = uac_selector_unit_iSelector(desc); + if (nameid) + len = snd_usb_copy_string_desc(state, nameid, + kctl->id.name, + sizeof(kctl->id.name)); + /* ... or pick up the terminal name at next */ + if (!len) + len = get_term_name(state, &state->oterm, + kctl->id.name, sizeof(kctl->id.name), 0); + /* ... or use the fixed string "USB" as the last resort */ + if (!len) + strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
+ /* and add the proper suffix */ if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) append_ctl_name(kctl, " Clock Source"); else if ((state->oterm.type & 0xff00) == 0x0100)
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Robin Murphy robin.murphy@arm.com
commit 29a90b70893817e2f2bb3cea40a29f5308e21b21 upstream.
The intel-iommu DMA ops fail to correctly handle scatterlists where sg->offset is greater than PAGE_SIZE - the IOVA allocation is computed appropriately based on the page-aligned portion of the offset, but the mapping is set up relative to sg->page, which means it fails to actually cover the whole buffer (and in the worst case doesn't cover it at all):
(sg->dma_address + sg->dma_len) ----+ sg->dma_address ---------+ | iov_pfn------+ | | | | | v v v iova: a b c d e f |--------|--------|--------|--------|--------| <...calculated....> [_____mapped______] pfn: 0 1 2 3 4 5 |--------|--------|--------|--------|--------| ^ ^ ^ | | | sg->page ----+ | | sg->offset --------------+ | (sg->offset + sg->length) ----------+
As a result, the caller ends up overrunning the mapping into whatever lies beyond, which usually goes badly:
[ 429.645492] DMAR: DRHD: handling fault status reg 2 [ 429.650847] DMAR: [DMA Write] Request device [02:00.4] fault addr f2682000 ...
Whilst this is a fairly rare occurrence, it can happen from the result of intermediate scatterlist processing such as scatterwalk_ffwd() in the crypto layer. Whilst that particular site could be fixed up, it still seems worthwhile to bring intel-iommu in line with other DMA API implementations in handling this robustly.
To that end, fix the intel_map_sg() path to line up the mapping correctly (in units of MM pages rather than VT-d pages to match the aligned_nrpages() calculation) regardless of the offset, and use sg_phys() consistently for clarity.
Reported-by: Harsh Jain Harsh@chelsio.com Signed-off-by: Robin Murphy robin.murphy@arm.com Reviewed by: Ashok Raj ashok.raj@intel.com Tested by: Jacob Pan jacob.jun.pan@intel.com Signed-off-by: Alex Williamson alex.williamson@redhat.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/iommu/intel-iommu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
--- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1783,10 +1783,12 @@ static int __domain_mapping(struct dmar_ uint64_t tmp;
if (!sg_res) { + unsigned int pgoff = sg->offset & ~PAGE_MASK; + sg_res = aligned_nrpages(sg->offset, sg->length); - sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; + sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff; sg->dma_length = sg->length; - pteval = page_to_phys(sg_page(sg)) | prot; + pteval = (sg_phys(sg) - pgoff) | prot; phys_pfn = pteval >> VTD_PAGE_SHIFT; }
@@ -3085,7 +3087,7 @@ static int intel_nontranslate_map_sg(str
for_each_sg(sglist, sg, nelems, i) { BUG_ON(!sg_page(sg)); - sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset; + sg->dma_address = sg_phys(sg); sg->dma_length = sg->length; } return nelems;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Masakazu Mokuno masakazu.mokuno@gmail.com
commit 81cf4a45360f70528f1f64ba018d61cb5767249a upstream.
As most of BOS descriptors are longer in length than their header 'struct usb_dev_cap_header', comparing solely with it is not sufficient to avoid out-of-bounds access to BOS descriptors.
This patch adds descriptor type specific length check in usb_get_bos_descriptor() to fix the issue.
Signed-off-by: Masakazu Mokuno masakazu.mokuno@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: - Drop handling of USB_PTM_CAP_TYPE and USB_SSP_CAP_TYPE - Adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -878,6 +878,13 @@ void usb_release_bos_descriptor(struct u } }
+static const __u8 bos_desc_len[256] = { + [USB_CAP_TYPE_WIRELESS_USB] = USB_DT_USB_WIRELESS_CAP_SIZE, + [USB_CAP_TYPE_EXT] = USB_DT_USB_EXT_CAP_SIZE, + [USB_SS_CAP_TYPE] = USB_DT_USB_SS_CAP_SIZE, + [CONTAINER_ID_TYPE] = USB_DT_USB_SS_CONTN_ID_SIZE, +}; + /* Get BOS descriptor set */ int usb_get_bos_descriptor(struct usb_device *dev) { @@ -886,6 +893,7 @@ int usb_get_bos_descriptor(struct usb_de struct usb_dev_cap_header *cap; unsigned char *buffer; int length, total_len, num, i; + __u8 cap_type; int ret;
bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL); @@ -938,7 +946,13 @@ int usb_get_bos_descriptor(struct usb_de dev->bos->desc->bNumDeviceCaps = i; break; } + cap_type = cap->bDevCapabilityType; length = cap->bLength; + if (bos_desc_len[cap_type] && length < bos_desc_len[cap_type]) { + dev->bos->desc->bNumDeviceCaps = i; + break; + } + total_len -= length;
if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { @@ -946,7 +960,7 @@ int usb_get_bos_descriptor(struct usb_de continue; }
- switch (cap->bDevCapabilityType) { + switch (cap_type) { case USB_CAP_TYPE_WIRELESS_USB: /* Wireless USB cap descriptor is handled by wusb */ break; --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -800,6 +800,8 @@ struct usb_wireless_cap_descriptor { /* __u8 bReserved; } __attribute__((packed));
+#define USB_DT_USB_WIRELESS_CAP_SIZE 11 + /* USB 2.0 Extension descriptor */ #define USB_CAP_TYPE_EXT 2
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Qiang qiang.zhao@nxp.com
commit c505873eaece2b4aefd07d339dc7e1400e0235ac upstream.
88E1145 also need this autoneg errata.
Fixes: f2899788353c ("net: phy: marvell: Limit errata to 88m1101") Signed-off-by: Zhao Qiang qiang.zhao@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/net/phy/marvell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -808,7 +808,7 @@ static struct phy_driver marvell_drivers .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &m88e1145_config_init, - .config_aneg = &marvell_config_aneg, + .config_aneg = &m88e1101_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr,
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Ben Hutchings ben.hutchings@codethink.co.uk
commit 1995266727fa8143897e89b55f5d3c79aa828420 upstream.
Commit bdcf0a423ea1 ("kernel: make groups_sort calling a responsibility group_info allocators") appears to break nfsd rootsquash in a pretty major way.
It adds a call to groups_sort() inside the loop that copies/squashes gids, which means the valid gids are sorted along with the following garbage. The net result is that the highest numbered valid gids are replaced with any lower-valued garbage gids, possibly including 0.
We should sort only once, after filling in all the gids.
Fixes: bdcf0a423ea1 ("kernel: make groups_sort calling a responsibility ...") Signed-off-by: Ben Hutchings ben.hutchings@codethink.co.uk Acked-by: J. Bruce Fields bfields@redhat.com Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- fs/nfsd/auth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c @@ -60,10 +60,10 @@ int nfsd_setuser(struct svc_rqst *rqstp, GROUP_AT(gi, i) = exp->ex_anon_gid; else GROUP_AT(gi, i) = GROUP_AT(rqgi, i); - - /* Each thread allocates its own gi, no race */ - groups_sort(gi); } + + /* Each thread allocates its own gi, no race */ + groups_sort(gi); } else { gi = get_group_info(rqgi); }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Gleb Natapov gleb@redhat.com
commit 991eebf9f8e523e7ff1e4d31ac80641582b2e57a upstream.
During invalid guest state emulation vcpu cannot enter guest mode to try to reexecute instruction that emulator failed to emulate, so emulation will happen again and again. Prevent that by telling the emulator that instruction reexecution should not be attempted.
Signed-off-by: Gleb Natapov gleb@redhat.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -694,6 +694,7 @@ enum emulation_result { #define EMULTYPE_NO_DECODE (1 << 0) #define EMULTYPE_TRAP_UD (1 << 1) #define EMULTYPE_SKIP (1 << 2) +#define EMULTYPE_NO_REEXECUTE (1 << 4) int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2, int emulation_type, void *insn, int insn_len);
--- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4891,7 +4891,7 @@ static int handle_invalid_guest_state(st && (kvm_get_rflags(&vmx->vcpu) & X86_EFLAGS_IF)) return handle_interrupt_window(&vmx->vcpu);
- err = emulate_instruction(vcpu, 0); + err = emulate_instruction(vcpu, EMULTYPE_NO_REEXECUTE);
if (err == EMULATE_DO_MMIO) { ret = 0; --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4888,10 +4888,14 @@ static int handle_emulation_failure(stru return r; }
-static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva) +static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva, + int emulation_type) { gpa_t gpa;
+ if (emulation_type & EMULTYPE_NO_REEXECUTE) + return false; + if (tdp_enabled) return false;
@@ -4942,7 +4946,7 @@ int x86_emulate_instruction(struct kvm_v if (r != EMULATION_OK) { if (emulation_type & EMULTYPE_TRAP_UD) return EMULATE_FAIL; - if (reexecute_instruction(vcpu, cr2)) + if (reexecute_instruction(vcpu, cr2, emulation_type)) return EMULATE_DONE; if (emulation_type & EMULTYPE_SKIP) return EMULATE_FAIL; @@ -4969,7 +4973,7 @@ restart: return EMULATE_DONE;
if (r == EMULATION_FAILED) { - if (reexecute_instruction(vcpu, cr2)) + if (reexecute_instruction(vcpu, cr2, emulation_type)) return EMULATE_DONE;
return handle_emulation_failure(vcpu);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Juan Zea juan.zea@qindel.com
commit 544c4605acc5ae4afe7dd5914147947db182f2fb upstream.
usbip bind writes commands followed by random string when writing to match_busid attribute in sysfs, caused by using full variable size instead of string length.
Signed-off-by: Juan Zea juan.zea@qindel.com Acked-by: Shuah Khan shuahkh@osg.samsung.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/staging/usbip/userspace/src/utils.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/staging/usbip/userspace/src/utils.c +++ b/drivers/staging/usbip/userspace/src/utils.c @@ -34,6 +34,7 @@ int modify_match_busid(char *busid, int char match_busid_attr_path[SYSFS_PATH_MAX]; struct sysfs_attribute *match_busid_attr; int rc, ret = 0; + int cmd_size;
if (strnlen(busid, SYSFS_BUS_ID_SIZE) > SYSFS_BUS_ID_SIZE - 1) { dbg("busid is too long"); @@ -58,13 +59,15 @@ int modify_match_busid(char *busid, int }
if (add) - snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s", busid); + cmd_size = snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s", + busid); else - snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "del %s", busid); + cmd_size = snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "del %s", + busid);
dbg("write "%s" to %s", buff, match_busid_attr->path);
- rc = sysfs_write_attribute(match_busid_attr, buff, sizeof(buff)); + rc = sysfs_write_attribute(match_busid_attr, buff, cmd_size); if (rc < 0) { dbg("failed to write match_busid: %s", strerror(errno)); ret = -1;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jaejoong Kim climbbb.kim@gmail.com
commit 89b89d121ffcf8d9546633b98ded9d18b8f75891 upstream.
snd_usb_copy_string_desc() returns zero if usb_string() fails. In case of failure, we need to check the snd_usb_copy_string_desc()'s return value and add an exception case
Signed-off-by: Jaejoong Kim climbbb.kim@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1928,12 +1928,14 @@ static int parse_audio_selector_unit(str if (len) ; else if (nameid) - snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); - else { + len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, + sizeof(kctl->id.name)); + else len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 0); - if (! len) - strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); + + if (!len) { + strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) append_ctl_name(kctl, " Clock Source");
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mohamed Ghannam simo.ghannam@gmail.com
commit 8f659a03a0ba9289b9aeb9b4470e6fb263d6f483 upstream.
inet->hdrincl is racy, and could lead to uninitialized stack pointer usage, so its value should be read only once.
Fixes: c008ba5bdc9f ("ipv4: Avoid reading user iov twice after raw_probe_proto_opt") Signed-off-by: Mohamed Ghannam simo.ghannam@gmail.com Reviewed-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: - flowi4 flags don't depend on hdrincl - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -484,11 +484,16 @@ static int raw_sendmsg(struct kiocb *ioc int err; struct ip_options_data opt_copy; struct raw_frag_vec rfv; + int hdrincl;
err = -EMSGSIZE; if (len > 0xFFFF) goto out;
+ /* hdrincl should be READ_ONCE(inet->hdrincl) + * but READ_ONCE() doesn't work with bit fields + */ + hdrincl = inet->hdrincl; /* * Check the flags. */ @@ -564,7 +569,7 @@ static int raw_sendmsg(struct kiocb *ioc /* Linux does not mangle headers on raw sockets, * so that IP options + IP_HDRINCL is non-sense. */ - if (inet->hdrincl) + if (hdrincl) goto done; if (ipc.opt->opt.srr) { if (!daddr) @@ -585,11 +590,11 @@ static int raw_sendmsg(struct kiocb *ioc
flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, - inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, + hdrincl ? IPPROTO_RAW : sk->sk_protocol, inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0);
- if (!inet->hdrincl) { + if (!hdrincl) { rfv.iov = msg->msg_iov; rfv.hlen = 0;
@@ -614,7 +619,7 @@ static int raw_sendmsg(struct kiocb *ioc goto do_confirm; back_from_confirm:
- if (inet->hdrincl) + if (hdrincl) err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len, &rt, msg->msg_flags);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann sven@narfation.org
commit 5ba7dcfe77037b67016263ea597a8b431692ecab upstream.
The originator node object orig_neigh_node is used to when accessing the bcast_own(_sum) and real_packet_count information. The access to them has to be protected with the spinlock in orig_neigh_node.
But the function uses the lock in orig_node instead. This is incorrect because they could be two different originator node objects.
Fixes: 0ede9f41b217 ("batman-adv: protect bit operations to count OGMs with spinlock") Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Simon Wunderlich sw@simonwunderlich.de [bwh: Backported to 3.2: - s/bat_iv.ogm_cnt_lock/ogm_cnt_lock/ - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/batman-adv/bat_iv_ogm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -760,10 +760,10 @@ static int bat_ogm_calc_tq(struct orig_n orig_node->last_valid = jiffies;
/* find packet count of corresponding one hop neighbor */ - spin_lock_bh(&orig_node->ogm_cnt_lock); + spin_lock_bh(&orig_neigh_node->ogm_cnt_lock); orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; neigh_rq_count = neigh_node->real_packet_count; - spin_unlock_bh(&orig_node->ogm_cnt_lock); + spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
/* pay attention to not get a value bigger than 100 % */ total_count = (orig_eq_count > neigh_rq_count ?
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: "Rafael J. Wysocki" rafael.j.wysocki@intel.com
commit 5839ee7389e893a31e4e3c9cf17b50d14103c902 upstream.
It is incorrect to call pci_restore_state() for devices in low-power states (D1-D3), as that involves the restoration of MSI setup which requires MMIO to be operational and that is only the case in D0.
However, pci_pm_thaw_noirq() may do that if the driver's "freeze" callbacks put the device into a low-power state, so fix it by making it force devices into D0 via pci_set_power_state() instead of trying to "update" their power state which is pointless.
Fixes: e60514bd4485 (PCI/PM: Restore the status of PCI devices across hibernation) Reported-by: Thomas Gleixner tglx@linutronix.de Reported-by: Maarten Lankhorst dev@mblankhorst.nl Tested-by: Thomas Gleixner tglx@linutronix.de Tested-by: Maarten Lankhorst dev@mblankhorst.nl Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Acked-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/pci/pci-driver.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -872,7 +872,12 @@ static int pci_pm_thaw_noirq(struct devi if (pci_has_legacy_pm_support(pci_dev)) return pci_legacy_resume_early(dev);
- pci_update_current_state(pci_dev, PCI_D0); + /* + * pci_restore_state() requires the device to be in D0 (because of MSI + * restoration among other things), so force it into D0 in case the + * driver's "freeze" callbacks put it into a low-power state directly. + */ + pci_set_power_state(pci_dev, PCI_D0); pci_restore_state(pci_dev);
if (drv && drv->pm && drv->pm->thaw_noirq)
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit bb82e0b4a7e96494f0c1004ce50cec3d7b5fb3d1 upstream.
The commit f6f828513290 ("pstore: pass allocated memory region back to caller") changed the check of the return value from erst_read() in erst_reader() in the following way:
if (len == -ENOENT) goto skip; - else if (len < 0) { - rc = -1; + else if (len < sizeof(*rcd)) { + rc = -EIO; goto out;
This introduced another bug: since the comparison with sizeof() is cast to unsigned, a negative len value doesn't hit any longer. As a result, when an error is returned from erst_read(), the code falls through, and it may eventually lead to some weird thing like memory corruption.
This patch adds the negative error value check more explicitly for addressing the issue.
Fixes: f6f828513290 (pstore: pass allocated memory region back to caller) Tested-by: Jerry Tang jtang@suse.com Signed-off-by: Takashi Iwai tiwai@suse.de Acked-by: Kees Cook keescook@chromium.org Reviewed-by: Borislav Petkov bp@suse.de Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/acpi/apei/erst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -1019,7 +1019,7 @@ skip: /* The record may be cleared by others, try read next record */ if (len == -ENOENT) goto skip; - else if (len < sizeof(*rcd)) { + else if (len < 0 || len < sizeof(*rcd)) { rc = -EIO; goto out; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen chenhc@lemote.com
commit c2e8fbf908afd81ad502b567a6639598f92c9b9d upstream.
The rps_resp buffer in ata_device is a DMA target, but it isn't explicitly cacheline aligned. Due to this, adjacent fields can be overwritten with stale data from memory on non-coherent architectures. As a result, the kernel is sometimes unable to communicate with an SATA device behind a SAS expander.
Fix this by ensuring that the rps_resp buffer is cacheline aligned.
This issue is similar to that fixed by Commit 84bda12af31f93 ("libata: align ap->sector_buf") and Commit 4ee34ea3a12396f35b26 ("libata: Align ata_device's id on a cacheline").
Signed-off-by: Huacai Chen chenhc@lemote.com Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- include/scsi/libsas.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -163,7 +163,6 @@ enum ata_command_set {
struct sata_device { enum ata_command_set command_set; - struct smp_resp rps_resp; /* report_phy_sata_resp */ __le16 *identify_device; __le16 *identify_packet_device;
@@ -172,6 +171,7 @@ struct sata_device {
struct ata_port *ap; struct ata_host ata_host; + struct smp_resp rps_resp ____cacheline_aligned; /* report_phy_sata_resp */ u8 fis[ATA_RESP_FIS_SIZE]; };
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Paasch cpaasch@apple.com
commit 30791ac41927ebd3e75486f9504b6d2280463bf0 upstream.
The MD5-key that belongs to a connection is identified by the peer's IP-address. When we are in tcp_v4(6)_reqsk_send_ack(), we are replying to an incoming segment from tcp_check_req() that failed the seq-number checks.
Thus, to find the correct key, we need to use the skb's saddr and not the daddr.
This bug seems to have been there since quite a while, but probably got unnoticed because the consequences are not catastrophic. We will call tcp_v4_reqsk_send_ack only to send a challenge-ACK back to the peer, thus the connection doesn't really fail.
Fixes: 9501f9722922 ("tcp md5sig: Let the caller pass appropriate key for tcp_v{4,6}_do_calc_md5_hash().") Signed-off-by: Christoph Paasch cpaasch@apple.com Reviewed-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
--- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -764,7 +764,7 @@ static void tcp_v4_reqsk_send_ack(struct tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, 0, - tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), + tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr), inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, ip_hdr(skb)->tos); } --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1116,7 +1116,7 @@ static void tcp_v6_reqsk_send_ack(struct struct request_sock *req) { tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, - tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0); + tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr), 0); }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Gleb Natapov gleb@redhat.com
commit 7f46ddbd487e0d0528d89534fdfb31d885977804 upstream.
Signed-off-by: Gleb Natapov gleb@redhat.com Reviewed-by: Chegu Vinod chegu_vinod@hp.com Tested-by: Chegu Vinod chegu_vinod@hp.com Signed-off-by: Avi Kivity avi@redhat.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/x86/kvm/lapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1022,7 +1022,7 @@ void kvm_lapic_set_base(struct kvm_vcpu vcpu->arch.apic_base = value; if (apic_x2apic_mode(apic)) { u32 id = kvm_apic_id(apic); - u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf)); + u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf)); apic_set_reg(apic, APIC_LDR, ldr); } apic->base_address = apic->vcpu->arch.apic_base &
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens heiko.carstens@de.ibm.com
commit fbbd7f1a51965b50dd12924841da0d478f3da71b upstream.
The switch_to() macro has an optimization to avoid saving and restoring register contents that aren't needed for kernel threads.
There is however the possibility that a kernel thread execve's a user space program. In such a case the execve'd process can partially see the contents of the previous process, which shouldn't be allowed.
To avoid this, simply always save and restore register contents on context switch.
Fixes: fdb6d070effba ("switch_to: dont restore/save access & fpu regs for kernel threads") Signed-off-by: Heiko Carstens heiko.carstens@de.ibm.com Signed-off-by: Martin Schwidefsky schwidefsky@de.ibm.com [bwh: Backported to 3.2: - The save/restore functions are different here - FP restore is non-lazy, so drop the comment about it being lazy - Adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/s390/include/asm/system.h | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-)
--- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h @@ -89,17 +89,13 @@ static inline void restore_access_regs(u asm volatile("lam 0,15,%0" : : "Q" (*acrs)); }
-#define switch_to(prev,next,last) do { \ - if (prev->mm) { \ - save_fp_regs(&prev->thread.fp_regs); \ - save_access_regs(&prev->thread.acrs[0]); \ - } \ - if (next->mm) { \ - restore_fp_regs(&next->thread.fp_regs); \ - restore_access_regs(&next->thread.acrs[0]); \ - update_per_regs(next); \ - } \ - prev = __switch_to(prev,next); \ +#define switch_to(prev, next, last) do { \ + save_fp_regs(&prev->thread.fp_regs); \ + save_access_regs(&prev->thread.acrs[0]); \ + restore_fp_regs(&next->thread.fp_regs); \ + restore_access_regs(&next->thread.acrs[0]); \ + update_per_regs(next); \ + prev = __switch_to(prev, next); \ } while (0)
extern void account_vtime(struct task_struct *, struct task_struct *);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Kozub zub@linux.fjfi.cvut.cz
commit 62354454625741f0569c2cbe45b2d192f8fd258e upstream.
There is another JMS567-based USB3 UAS enclosure (152d:0578) that fails with the following error:
[sda] tag#0 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [sda] tag#0 Sense Key : Illegal Request [current] [sda] tag#0 Add. Sense: Invalid field in cdb
The issue occurs both with UAS (occasionally) and mass storage (immediately after mounting a FS on a disk in the enclosure).
Enabling US_FL_BROKEN_FUA quirk solves this issue.
This patch adds an UNUSUAL_DEV with US_FL_BROKEN_FUA for the enclosure for both UAS and mass storage.
Signed-off-by: David Kozub zub@linux.fjfi.cvut.cz Acked-by: Alan Stern stern@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: - Drop uas change - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1961,6 +1961,13 @@ UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BROKEN_FUA ),
+/* Reported by David Kozub zub@linux.fjfi.cvut.cz */ +UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999, + "JMicron", + "JMS567", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BROKEN_FUA), + /* Reported by Alexandre Oliva oliva@lsd.ic.unicamp.br * JMicron responds to USN and several other SCSI ioctls with a * residue that causes subsequent I/O requests to fail. */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shuah Khan shuahkh@osg.samsung.com
commit 90120d15f4c397272aaf41077960a157fc4212bf upstream.
usbip driver is leaking socket pointer address in messages. Remove the messages that aren't useful and print sockfd in the ones that are useful for debugging.
Signed-off-by: Shuah Khan shuahkh@osg.samsung.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: adjust filenames, context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c @@ -186,8 +186,7 @@ static void stub_shutdown_connection(str * step 1? */ if (ud->tcp_socket) { - dev_dbg(&sdev->udev->dev, "shutdown tcp_socket %p\n", - ud->tcp_socket); + dev_dbg(&sdev->udev->dev, "shutdown sockfd %d\n", ud->sockfd); kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); }
--- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -346,13 +346,10 @@ int usbip_recv(struct socket *sock, void char *bp = buf; int osize = size;
- usbip_dbg_xmit("enter\n"); - - if (!sock || !buf || !size) { - pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf, - size); + if (!sock || !buf || !size) return -EINVAL; - } + + usbip_dbg_xmit("enter\n");
do { sock->sk->sk_allocation = GFP_NOIO; @@ -366,11 +363,8 @@ int usbip_recv(struct socket *sock, void msg.msg_flags = MSG_NOSIGNAL;
result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); - if (result <= 0) { - pr_debug("receive sock %p buf %p size %u ret %d total %d\n", - sock, buf, size, result, total); + if (result <= 0) goto err; - }
size -= result; buf += result; --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -811,7 +811,7 @@ static void vhci_shutdown_connection(str
/* need this? see stub_dev.c */ if (ud->tcp_socket) { - pr_debug("shutdown tcp_socket %p\n", ud->tcp_socket); + pr_debug("shutdown tcp_socket %d\n", ud->sockfd); kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Matt Wilson msw@amazon.com
commit 3bfd1300abfe3adb18e84a89d97a0e82a22124bb upstream.
This device will be used in future Amazon EC2 instances as the primary serial port (i.e., data sent to this port will be available via the GetConsoleOuput [1] EC2 API).
[1] http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetConsoleOutput.h...
Signed-off-by: Matt Wilson msw@amazon.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/tty/serial/8250_pci.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -4175,6 +4175,9 @@ static struct pci_device_id serial_pci_t { PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 }, { PCI_DEVICE(0x1601, 0xa801), .driver_data = pbn_b0_4_1250000 },
+ /* Amazon PCI serial device */ + { PCI_DEVICE(0x1d0f, 0x8250), .driver_data = pbn_b0_1_115200 }, + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Wanpeng Li wanpeng.li@hotmail.com
commit d73235d17ba63b53dc0e1051dbc10a1f1be91b71 upstream.
*** Guest State *** CR0: actual=0x0000000000000030, shadow=0x0000000060000010, gh_mask=fffffffffffffff7 CR4: actual=0x0000000000002050, shadow=0x0000000000000000, gh_mask=ffffffffffffe871 CR3 = 0x00000000fffbc000 RSP = 0x0000000000000000 RIP = 0x0000000000000000 RFLAGS=0x00000000 DR7 = 0x0000000000000400 ^^^^^^^^^^
The failed vmentry is triggered by the following testcase when ept=Y:
#include <unistd.h> #include <sys/syscall.h> #include <string.h> #include <stdint.h> #include <linux/kvm.h> #include <fcntl.h> #include <sys/ioctl.h>
long r[5]; int main() { r[2] = open("/dev/kvm", O_RDONLY); r[3] = ioctl(r[2], KVM_CREATE_VM, 0); r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7); struct kvm_regs regs = { .rflags = 0, }; ioctl(r[4], KVM_SET_REGS, ®s); ioctl(r[4], KVM_RUN, 0); }
X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1 of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails. This patch fixes it by oring X86_EFLAGS_FIXED during ioctl.
Suggested-by: Jim Mattson jmattson@google.com Reviewed-by: David Hildenbrand david@redhat.com Reviewed-by: Quan Xu quan.xu0@gmail.com Cc: Paolo Bonzini pbonzini@redhat.com Cc: Radim Krčmář rkrcmar@redhat.com Cc: Jim Mattson jmattson@google.com Signed-off-by: Wanpeng Li wanpeng.li@hotmail.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com [bwh: Backported to 3.2: use literal integer] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/x86/kvm/x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6077,7 +6077,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct #endif
kvm_rip_write(vcpu, regs->rip); - kvm_set_rflags(vcpu, regs->rflags); + kvm_set_rflags(vcpu, regs->rflags | 0x2 /*X86_EFLAGS_FIXED*/);
vcpu->arch.exception.pending = false;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen chenhc@lemote.com
commit 90addc6b3c9cda0146fbd62a08e234c2b224a80c upstream.
In non-coherent DMA mode, kernel uses cache flushing operations to maintain I/O coherency, so scsi's block queue should be aligned to the value returned by dma_get_cache_alignment(). Otherwise, If a DMA buffer and a kernel structure share a same cache line, and if the kernel structure has dirty data, cache_invalidate (no writeback) will cause data corruption.
Signed-off-by: Huacai Chen chenhc@lemote.com [hch: rebased and updated the comment and changelog] Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/scsi/scsi_lib.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1688,11 +1688,13 @@ struct request_queue *__scsi_alloc_queue q->limits.cluster = 0;
/* - * set a reasonable default alignment on word boundaries: the - * host and device may alter it using - * blk_queue_update_dma_alignment() later. + * Set a reasonable default alignment: The larger of 32-byte (dword), + * which is a common minimum for HBAs, and the minimum DMA alignment, + * which is set by the platform. + * + * Devices that require a bigger alignment can increase it later. */ - blk_queue_dma_alignment(q, 0x03); + blk_queue_dma_alignment(q, max(4, dma_get_cache_alignment()) - 1);
return q; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Sjoholm ssjoholm@mac.com
commit c654b21ede93845863597de9ad774fd30db5f2ab upstream.
Quectel BG96 is an Qualcomm MDM9206 based IoT modem, supporting both CAT-M and NB-IoT. Tested hardware is BG96 mounted on Quectel development board (EVB). The USB id is added to option.c to allow DIAG,GPS,AT and modem communication with the BG96.
Signed-off-by: Sebastian Sjoholm ssjoholm@mac.com Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -242,6 +242,7 @@ static void option_instat_callback(struc /* These Quectel products use Quectel's vendor ID */ #define QUECTEL_PRODUCT_EC21 0x0121 #define QUECTEL_PRODUCT_EC25 0x0125 +#define QUECTEL_PRODUCT_BG96 0x0296
#define CMOTECH_VENDOR_ID 0x16d8 #define CMOTECH_PRODUCT_6001 0x6001 @@ -1165,6 +1166,8 @@ static const struct usb_device_id option .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman mathias.nyman@linux.intel.com
commit e4ec40ec4b260efcca15089de4285a0a3411259b upstream.
xHC can generate two events for a short transfer if the short TRB and last TRB in the TD are not the same TRB.
The driver will handle the TD after the first short event, and remove it from its internal list. Driver then incorrectly prints a warning for the second event:
"WARN Event TRB for slot x ep y with no TDs queued"
Fix this by not printing a warning if we get a event on a empty list if the previous event was a short event.
Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/host/xhci-ring.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
--- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2396,12 +2396,16 @@ static int handle_tx_event(struct xhci_h */ if (list_empty(&ep_ring->td_list)) { /* - * A stopped endpoint may generate an extra completion - * event if the device was suspended. Don't print - * warnings. + * Don't print wanings if it's due to a stopped endpoint + * generating an extra completion event if the device + * was suspended. Or, a event for the last TRB of a + * short TD we already got a short event for. + * The short TD is already removed from the TD list. */ + if (!(trb_comp_code == COMP_STOP || - trb_comp_code == COMP_STOP_INVAL)) { + trb_comp_code == COMP_STOP_INVAL || + ep_ring->last_td_was_short)) { xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), ep_index);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu herbert@gondor.apana.org.au
commit 32b5913a931fd753faf3d4e1124b2bc2edb364da upstream.
The function raw_probe_proto_opt tries to extract the first two bytes from the user input in order to seed the IPsec lookup for ICMP packets. In doing so it's processing iovec by hand and overcomplicating things.
This patch replaces the manual iovec processing with a call to memcpy_fromiovecend.
Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/ipv4/raw.c | 50 +++++++++++--------------------------------------- 1 file changed, 11 insertions(+), 39 deletions(-)
--- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -411,48 +411,20 @@ error:
static int raw_probe_proto_opt(struct flowi4 *fl4, struct msghdr *msg) { - struct iovec *iov; - u8 __user *type = NULL; - u8 __user *code = NULL; - int probed = 0; - unsigned int i; + struct icmphdr icmph; + int err;
- if (!msg->msg_iov) + if (fl4->flowi4_proto != IPPROTO_ICMP) return 0;
- for (i = 0; i < msg->msg_iovlen; i++) { - iov = &msg->msg_iov[i]; - if (!iov) - continue; - - switch (fl4->flowi4_proto) { - case IPPROTO_ICMP: - /* check if one-byte field is readable or not. */ - if (iov->iov_base && iov->iov_len < 1) - break; - - if (!type) { - type = iov->iov_base; - /* check if code field is readable or not. */ - if (iov->iov_len > 1) - code = type + 1; - } else if (!code) - code = iov->iov_base; - - if (type && code) { - if (get_user(fl4->fl4_icmp_type, type) || - get_user(fl4->fl4_icmp_code, code)) - return -EFAULT; - probed = 1; - } - break; - default: - probed = 1; - break; - } - if (probed) - break; - } + /* We only need the first two bytes. */ + err = memcpy_fromiovecend((void *)&icmph, msg->msg_iov, 0, 2); + if (err) + return err; + + fl4->fl4_icmp_type = icmph.type; + fl4->fl4_icmp_code = icmph.code; + return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman mathias.nyman@linux.intel.com
commit 5d9b70f7d52eb14bb37861c663bae44de9521c35 upstream.
Avoid null pointer dereference if some function is walking through the devs array accessing members of a new virt_dev that is mid allocation.
Add the virt_dev to xhci->devs[i] _after_ the virt_device and all its members are properly allocated.
issue found by KASAN: null-ptr-deref in xhci_find_slot_id_by_port
"Quick analysis suggests that xhci_alloc_virt_device() is not mutex protected. If so, there is a time frame where xhci->devs[slot_id] is set but not fully initialized. Specifically, xhci->devs[i]->udev can be NULL."
Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: There is an extra failure path, so we may need to free dev->eps[0].ring] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -873,10 +873,9 @@ int xhci_alloc_virt_device(struct xhci_h return 0; }
- xhci->devs[slot_id] = kzalloc(sizeof(*xhci->devs[slot_id]), flags); - if (!xhci->devs[slot_id]) + dev = kzalloc(sizeof(*dev), flags); + if (!dev) return 0; - dev = xhci->devs[slot_id];
/* Allocate the (output) device context that will be used in the HC. */ dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags); @@ -925,9 +924,19 @@ int xhci_alloc_virt_device(struct xhci_h &xhci->dcbaa->dev_context_ptrs[slot_id], le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
+ xhci->devs[slot_id] = dev; + return 1; fail: - xhci_free_virt_device(xhci, slot_id); + + if (dev->eps[0].ring) + xhci_ring_free(xhci, dev->eps[0].ring); + if (dev->in_ctx) + xhci_free_container_ctx(xhci, dev->in_ctx); + if (dev->out_ctx) + xhci_free_container_ctx(xhci, dev->out_ctx); + kfree(dev); + return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Neukum oneukum@suse.com
commit 446f666da9f019ce2ffd03800995487e79a91462 upstream.
USBDEVFS_URB_ISO_ASAP must be accepted only for ISO endpoints. Improve sanity checking.
Reported-by: Andrey Konovalov andreyknvl@google.com Signed-off-by: Oliver Neukum oneukum@suse.com Acked-by: Alan Stern stern@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/core/devio.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
--- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1093,14 +1093,18 @@ static int proc_do_submiturb(struct dev_ unsigned int u, totlen, isofrmlen; int ret, ifnum = -1; int is_in; - - if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP | - USBDEVFS_URB_SHORT_NOT_OK | + unsigned long mask = USBDEVFS_URB_SHORT_NOT_OK | USBDEVFS_URB_BULK_CONTINUATION | USBDEVFS_URB_NO_FSBR | USBDEVFS_URB_ZERO_PACKET | - USBDEVFS_URB_NO_INTERRUPT)) - return -EINVAL; + USBDEVFS_URB_NO_INTERRUPT; + /* USBDEVFS_URB_ISO_ASAP is a special case */ + if (uurb->type == USBDEVFS_URB_TYPE_ISO) + mask |= USBDEVFS_URB_ISO_ASAP; + + if (uurb->flags & ~mask) + return -EINVAL; + if (uurb->buffer_length > 0 && !uurb->buffer) return -EINVAL; if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liran Alon liran.alon@oracle.com
commit 9b8ae63798cb97e785a667ff27e43fa6220cb734 upstream.
In case of instruction-decode failure or emulation failure, x86_emulate_instruction() will call reexecute_instruction() which will attempt to use the cr2 value passed to x86_emulate_instruction(). However, when x86_emulate_instruction() is called from emulate_instruction(), cr2 is not passed (passed as 0) and therefore it doesn't make sense to execute reexecute_instruction() logic at all.
Fixes: 51d8b66199e9 ("KVM: cleanup emulate_instruction")
Signed-off-by: Liran Alon liran.alon@oracle.com Reviewed-by: Nikita Leshenko nikita.leshchenko@oracle.com Reviewed-by: Konrad Rzeszutek Wilk konrad.wilk@oracle.com Signed-off-by: Konrad Rzeszutek Wilk konrad.wilk@oracle.com Reviewed-by: Wanpeng Li wanpeng.li@hotmail.com Signed-off-by: Radim Krčmář rkrcmar@redhat.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/x86/include/asm/kvm_host.h | 3 ++- arch/x86/kvm/vmx.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-)
--- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -701,7 +701,8 @@ int x86_emulate_instruction(struct kvm_v static inline int emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type) { - return x86_emulate_instruction(vcpu, 0, emulation_type, NULL, 0); + return x86_emulate_instruction(vcpu, 0, + emulation_type | EMULTYPE_NO_REEXECUTE, NULL, 0); }
void kvm_enable_efer_bits(u64); --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4891,7 +4891,7 @@ static int handle_invalid_guest_state(st && (kvm_get_rflags(&vmx->vcpu) & X86_EFLAGS_IF)) return handle_interrupt_window(&vmx->vcpu);
- err = emulate_instruction(vcpu, EMULTYPE_NO_REEXECUTE); + err = emulate_instruction(vcpu, 0);
if (err == EMULATE_DO_MMIO) { ret = 0;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 43a3542870328601be02fcc9d27b09db467336ef upstream.
The use of snd_BUG_ON() in ALSA sequencer timer may lead to a spurious WARN_ON() when a slave timer is deployed as its backend and a corresponding master timer stops meanwhile. The symptom was triggered by syzkaller spontaneously.
Since the NULL timer is valid there, rip off snd_BUG_ON().
Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/seq/seq_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -357,7 +357,7 @@ static int initialize_timer(struct snd_s unsigned long freq;
t = tmr->timeri->timer; - if (snd_BUG_ON(!t)) + if (!t) return -EINVAL;
freq = tmr->preferred_resolution;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dan Williams dan.j.williams@intel.com
commit 95ac7fd189b7e81a200b4d00b2bb6669b31acf3a upstream.
Commit 1e34c838 "[SCSI] libsas: remove spurious sata control register read/write" removed the routines to fake the presence of the sata control registers, now remove the unused data structure fields to kill any remaining confusion.
Acked-by: Jack Wang jack_wang@usish.com Signed-off-by: Dan Williams dan.j.williams@intel.com Signed-off-by: James Bottomley JBottomley@Parallels.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/scsi/libsas/sas_ata.c | 4 ---- include/scsi/libsas.h | 7 ------- 2 files changed, 11 deletions(-)
--- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -121,10 +121,6 @@ static void sas_ata_task_done(struct sas if (unlikely(link->eh_info.err_mask)) qc->flags |= ATA_QCFLAG_FAILED; } - - dev->sata_dev.sstatus = resp->sstatus; - dev->sata_dev.serror = resp->serror; - dev->sata_dev.scontrol = resp->scontrol; } else { ac = sas_to_ata_err(stat); if (ac) { --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -173,9 +173,6 @@ struct sata_device { struct ata_port *ap; struct ata_host ata_host; u8 fis[ATA_RESP_FIS_SIZE]; - u32 sstatus; - u32 serror; - u32 scontrol; };
/* ---------- Domain device ---------- */ @@ -492,10 +489,6 @@ enum exec_status { struct ata_task_resp { u16 frame_len; u8 ending_fis[ATA_RESP_FIS_SIZE]; /* dev to host or data-in */ - u32 sstatus; - u32 serror; - u32 scontrol; - u32 sactive; };
#define SAS_STATUS_BUF_SIZE 96
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Helge Deller deller@gmx.de
commit bcf3f1752a622f1372d3252d0fea8855d89812e7 upstream.
Diva GSP card has built-in serial AUX port and ATI graphic card which simply don't work and which both don't have external connectors. User Guides even mention that those devices shouldn't be used. So, prevent that Linux drivers try to enable those devices.
Signed-off-by: Helge Deller deller@gmx.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/parisc/lba_pci.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
--- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1603,3 +1603,36 @@ void lba_set_iregs(struct parisc_device iounmap(base_addr); }
+ +/* + * The design of the Diva management card in rp34x0 machines (rp3410, rp3440) + * seems rushed, so that many built-in components simply don't work. + * The following quirks disable the serial AUX port and the built-in ATI RV100 + * Radeon 7000 graphics card which both don't have any external connectors and + * thus are useless, and even worse, e.g. the AUX port occupies ttyS0 and as + * such makes those machines the only PARISC machines on which we can't use + * ttyS0 as boot console. + */ +static void quirk_diva_ati_card(struct pci_dev *dev) +{ + if (dev->subsystem_vendor != PCI_VENDOR_ID_HP || + dev->subsystem_device != 0x1292) + return; + + dev_info(&dev->dev, "Hiding Diva built-in ATI card"); + dev->device = 0; +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QY, + quirk_diva_ati_card); + +static void quirk_diva_aux_disable(struct pci_dev *dev) +{ + if (dev->subsystem_vendor != PCI_VENDOR_ID_HP || + dev->subsystem_device != 0x1291) + return; + + dev_info(&dev->dev, "Hiding Diva built-in AUX serial device"); + dev->device = 0; +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX, + quirk_diva_aux_disable);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Nogah Frankel nogahf@mellanox.com
commit 8afa10cbe281b10371fee5a87ab266e48d71a7f9 upstream.
Check the qmin & qmax values doesn't overflow for the given Wlog value. Check that qmin <= qmax.
Fixes: a783474591f2 ("[PKT_SCHED]: Generic RED layer") Signed-off-by: Nogah Frankel nogahf@mellanox.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: - Drop changes in sch_sfq - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/include/net/red.h +++ b/include/net/red.h @@ -124,6 +124,17 @@ static inline u32 red_rmask(u8 Plog) return Plog < 32 ? ((1 << Plog) - 1) : ~0UL; }
+static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog) +{ + if (fls(qth_min) + Wlog > 32) + return false; + if (fls(qth_max) + Wlog > 32) + return false; + if (qth_max < qth_min) + return false; + return true; +} + static inline void red_set_parms(struct red_parms *p, u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog, u8 Scell_log, u8 *stab) --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -479,6 +479,9 @@ static int choke_change(struct Qdisc *sc
ctl = nla_data(tb[TCA_CHOKE_PARMS]);
+ if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) + return -EINVAL; + if (ctl->limit > CHOKE_MAX_QUEUE) return -EINVAL;
--- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -384,6 +384,9 @@ static inline int gred_change_vq(struct struct gred_sched *table = qdisc_priv(sch); struct gred_sched_data *q;
+ if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) + return -EINVAL; + if (table->tab[dp] == NULL) { table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC); if (table->tab[dp] == NULL) --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -189,6 +189,8 @@ static int red_change(struct Qdisc *sch, return -EINVAL;
ctl = nla_data(tb[TCA_RED_PARMS]); + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) + return -EINVAL;
if (ctl->limit > 0) { child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Martin Kelly mkelly@xevo.com
commit 7a31ced3de06e9878e4f9c3abe8f87d9344d8144 upstream.
In mcba_usb, we have observed that when you unplug the device, the driver will endlessly resubmit failing URBs, which can cause CPU stalls. This issue is fixed in mcba_usb by catching the codes seen on device disconnect (-EPIPE and -EPROTO).
This driver also resubmits in the case of -EPIPE and -EPROTO, so fix it in the same way.
Signed-off-by: Martin Kelly mkelly@xevo.com Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/net/can/usb/esd_usb2.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -393,6 +393,8 @@ static void esd_usb2_read_bulk_callback( break;
case -ENOENT: + case -EPIPE: + case -EPROTO: case -ESHUTDOWN: return;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shuah Khan shuahkh@osg.samsung.com
commit 248a22044366f588d46754c54dfe29ffe4f8b4df upstream.
Remove and/or change debug, info. and error messages to not print kernel pointer addresses.
Signed-off-by: Shuah Khan shuahkh@osg.samsung.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: - Drop change in stub_complete() - Adjust filenames, context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/staging/usbip/stub_main.c | 5 +++-- drivers/staging/usbip/stub_rx.c | 7 ++----- drivers/staging/usbip/stub_tx.c | 6 +++--- 3 files changed, 8 insertions(+), 10 deletions(-)
--- a/drivers/staging/usbip/stub_main.c +++ b/drivers/staging/usbip/stub_main.c @@ -227,11 +227,12 @@ void stub_device_cleanup_urbs(struct stu struct stub_priv *priv; struct urb *urb;
- dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev); + dev_dbg(&sdev->udev->dev, "Stub device cleaning up urbs\n");
while ((priv = stub_priv_pop(sdev))) { urb = priv->urb; - dev_dbg(&sdev->udev->dev, "free urb %p\n", urb); + dev_dbg(&sdev->udev->dev, "free urb seqnum %lu\n", + priv->seqnum); usb_kill_urb(urb);
kmem_cache_free(stub_priv_cache, priv); --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -239,9 +239,6 @@ static int stub_recv_cmd_unlink(struct s if (priv->seqnum == pdu->u.cmd_unlink.seqnum) { int ret;
- dev_info(&priv->urb->dev->dev, "unlink urb %p\n", - priv->urb); - /* * This matched urb is not completed yet (i.e., be in * flight in usb hcd hardware/driver). Now we are @@ -280,8 +277,8 @@ static int stub_recv_cmd_unlink(struct s ret = usb_unlink_urb(priv->urb); if (ret != -EINPROGRESS) dev_err(&priv->urb->dev->dev, - "failed to unlink a urb %p, ret %d\n", - priv->urb, ret); + "failed to unlink a urb # %lu, ret %d\n", + priv->seqnum, ret); return 0; } } --- a/drivers/staging/usbip/stub_tx.c +++ b/drivers/staging/usbip/stub_tx.c @@ -201,8 +201,8 @@ static int stub_send_ret_submit(struct s
/* 1. setup usbip_header */ setup_ret_submit_pdu(&pdu_header, urb); - usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n", - pdu_header.base.seqnum, urb); + usbip_dbg_stub_tx("setup txdata seqnum: %d\n", + pdu_header.base.seqnum); /*usbip_dump_header(pdu_header);*/ usbip_header_correct_endian(&pdu_header, 1);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Robert Lippert roblip@gmail.com
commit bd467e4eababe4c04272c1e646f066db02734c79 upstream.
Power values in the 100s of watt range can easily blow past 32bit math limits when processing everything in microwatts.
Use 64bit math instead to avoid these issues on common 32bit ARM BMC platforms.
Fixes: 442aba78728e ("hwmon: PMBus device driver") Signed-off-by: Robert Lippert rlippert@google.com Signed-off-by: Guenter Roeck linux@roeck-us.net [bwh: Backported to 3.2: use integer literals instead of S16_{MIN,MAX}] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/hwmon/pmbus/pmbus_core.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-)
--- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -19,6 +19,7 @@ */
#include <linux/kernel.h> +#include <linux/math64.h> #include <linux/module.h> #include <linux/init.h> #include <linux/err.h> @@ -475,8 +476,8 @@ static long pmbus_reg2data_linear(struct static long pmbus_reg2data_direct(struct pmbus_data *data, struct pmbus_sensor *sensor) { - long val = (s16) sensor->data; - long m, b, R; + s64 b, val = (s16)sensor->data; + s32 m, R;
m = data->info->m[sensor->class]; b = data->info->b[sensor->class]; @@ -504,11 +505,12 @@ static long pmbus_reg2data_direct(struct R--; } while (R < 0) { - val = DIV_ROUND_CLOSEST(val, 10); + val = div_s64(val + 5LL, 10L); /* round closest */ R++; }
- return (val - b) / m; + val = div_s64(val - b, m); + return clamp_val(val, LONG_MIN, LONG_MAX); }
/* @@ -620,7 +622,8 @@ static u16 pmbus_data2reg_linear(struct static u16 pmbus_data2reg_direct(struct pmbus_data *data, enum pmbus_sensor_classes class, long val) { - long m, b, R; + s64 b, val64 = val; + s32 m, R;
m = data->info->m[class]; b = data->info->b[class]; @@ -637,18 +640,18 @@ static u16 pmbus_data2reg_direct(struct R -= 3; /* Adjust R and b for data in milli-units */ b *= 1000; } - val = val * m + b; + val64 = val64 * m + b;
while (R > 0) { - val *= 10; + val64 *= 10; R--; } while (R < 0) { - val = DIV_ROUND_CLOSEST(val, 10); + val64 = div_s64(val64 + 5LL, 10L); /* round closest */ R++; }
- return val; + return (u16)clamp_val(val64, -32768, 32767); }
static u16 pmbus_data2reg_vid(struct pmbus_data *data,
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Colin Ian King colin.king@canonical.com
commit 1d5a31582ef046d3b233f0da1a68ae26519b2f0a upstream.
The variable temp is incorrectly being updated, instead it should be offset otherwise the loop just reads the same capability value and loops forever. Thanks to Alan Stern for pointing out the correct fix to my original fix. Fix also cleans up clang warning:
drivers/usb/host/ehci-dbg.c:840:4: warning: Value stored to 'temp' is never read
Fixes: d49d43174400 ("USB: misc ehci updates") Signed-off-by: Colin Ian King colin.king@canonical.com Acked-by: Alan Stern stern@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/host/ehci-dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -785,7 +785,7 @@ static ssize_t fill_registers_buffer(str default: /* unknown */ break; } - temp = (cap >> 8) & 0xff; + offset = (cap >> 8) & 0xff; } } #endif
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Thompson daniel.thompson@linaro.org
commit c07d35338081d107e57cf37572d8cc931a8e32e2 upstream.
kallsyms_symbol_next() returns a boolean (true on success). Currently kdb_read() tests the return value with an inequality that unconditionally evaluates to true.
This is fixed in the obvious way and, since the conditional branch is supposed to be unreachable, we also add a WARN_ON().
Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Daniel Thompson daniel.thompson@linaro.org Signed-off-by: Jason Wessel jason.wessel@windriver.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- kernel/debug/kdb/kdb_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -349,7 +349,7 @@ poll_again: } kdb_printf("\n"); for (i = 0; i < count; i++) { - if (kallsyms_symbol_next(p_tmp, i) < 0) + if (WARN_ON(!kallsyms_symbol_next(p_tmp, i))) break; kdb_printf("%s ", p_tmp); *(p_tmp + len) = '\0';
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Martin Kelly mkelly@xevo.com
commit bd352e1adfe0d02d3ea7c8e3fb19183dc317e679 upstream.
In mcba_usb, we have observed that when you unplug the device, the driver will endlessly resubmit failing URBs, which can cause CPU stalls. This issue is fixed in mcba_usb by catching the codes seen on device disconnect (-EPIPE and -EPROTO).
This driver also resubmits in the case of -EPIPE and -EPROTO, so fix it in the same way.
Signed-off-by: Martin Kelly mkelly@xevo.com Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/net/can/usb/ems_usb.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -292,6 +292,8 @@ static void ems_usb_read_interrupt_callb
case -ECONNRESET: /* unlink */ case -ENOENT: + case -EPIPE: + case -EPROTO: case -ESHUTDOWN: return;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
This is the revised backport of the upstream commit b3defb791b26ea0683a93a4f49c77ec45ec96f10
We had another backport (e.g. 623e5c8ae32b in 4.4.115), but it applies the new mutex also to the code paths that are invoked via faked kernel-to-kernel ioctls. As reported recently, this leads to a deadlock at suspend (or other scenarios triggering the kernel sequencer client).
This patch addresses the issue by taking the mutex only in the code paths invoked by user-space, just like the original fix patch does.
Reported-and-tested-by: Andres Bertens abertensu@yahoo.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/seq/seq_clientmgr.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
--- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2189,7 +2189,6 @@ static int snd_seq_do_ioctl(struct snd_s void __user *arg) { struct seq_ioctl_table *p; - int ret;
switch (cmd) { case SNDRV_SEQ_IOCTL_PVERSION: @@ -2203,12 +2202,8 @@ static int snd_seq_do_ioctl(struct snd_s if (! arg) return -EFAULT; for (p = ioctl_tables; p->cmd; p++) { - if (p->cmd == cmd) { - mutex_lock(&client->ioctl_mutex); - ret = p->func(client, arg); - mutex_unlock(&client->ioctl_mutex); - return ret; - } + if (p->cmd == cmd) + return p->func(client, arg); } snd_printd("seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); @@ -2219,11 +2214,15 @@ static int snd_seq_do_ioctl(struct snd_s static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct snd_seq_client *client = file->private_data; + long ret;
if (snd_BUG_ON(!client)) return -ENXIO; - return snd_seq_do_ioctl(client, cmd, (void __user *) arg); + mutex_lock(&client->ioctl_mutex); + ret = snd_seq_do_ioctl(client, cmd, (void __user *) arg); + mutex_unlock(&client->ioctl_mutex); + return ret; }
#ifdef CONFIG_COMPAT
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig hch@lst.de
commit 860dd4424f344400b491b212ee4acb3a358ba9d9 upstream.
Provide the dummy version of dma_get_cache_alignment that always returns 1 even if CONFIG_HAS_DMA is not set, so that drivers and subsystems can use it without ifdefs.
Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com [bwh: Backported to 3.2: Also delete the conflicting declaration in <asm-generic/dma-mapping-broken.h>] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -130,7 +130,6 @@ static inline void *dma_zalloc_coherent( return ret; }
-#ifdef CONFIG_HAS_DMA static inline int dma_get_cache_alignment(void) { #ifdef ARCH_DMA_MINALIGN @@ -138,7 +137,6 @@ static inline int dma_get_cache_alignmen #endif return 1; } -#endif
/* flags for the coherent memory api */ #define DMA_MEMORY_MAP 0x01 --- a/include/asm-generic/dma-mapping-broken.h +++ b/include/asm-generic/dma-mapping-broken.h @@ -69,9 +69,6 @@ dma_supported(struct device *dev, u64 ma extern int dma_set_mask(struct device *dev, u64 mask);
-extern int -dma_get_cache_alignment(void); - extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit c1cfd9025cc394fd137a01159d74335c5ac978ce upstream.
The rawmidi also allows to obtaining the information via ioctl of ctl API. It means that user can issue an ioctl to the rawmidi device even when it's being removed as long as the control device is present. Although the code has some protection via the global register_mutex, its range is limited to the search of the corresponding rawmidi object, and the mutex is already unlocked at accessing the rawmidi object. This may lead to a use-after-free.
For avoiding it, this patch widens the application of register_mutex to the whole snd_rawmidi_info_select() function. We have another mutex per rawmidi object, but this operation isn't very hot path, so it shouldn't matter from the performance POV.
Signed-off-by: Takashi Iwai tiwai@suse.de [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/rawmidi.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
--- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -575,15 +575,14 @@ static int snd_rawmidi_info_user(struct return 0; }
-int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info) +static int __snd_rawmidi_info_select(struct snd_card *card, + struct snd_rawmidi_info *info) { struct snd_rawmidi *rmidi; struct snd_rawmidi_str *pstr; struct snd_rawmidi_substream *substream;
- mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, info->device); - mutex_unlock(®ister_mutex); if (!rmidi) return -ENXIO; if (info->stream < 0 || info->stream > 1) @@ -600,6 +599,16 @@ int snd_rawmidi_info_select(struct snd_c return -ENXIO; }
+int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info) +{ + int ret; + + mutex_lock(®ister_mutex); + ret = __snd_rawmidi_info_select(card, info); + mutex_unlock(®ister_mutex); + return ret; +} + static int snd_rawmidi_info_select_user(struct snd_card *card, struct snd_rawmidi_info __user *_info) {
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: "monty_pavel@sina.com" monty_pavel@sina.com
commit 7e6358d244e4706fe612a77b9c36519a33600ac0 upstream.
A NULL pointer is seen if two concurrent "vgchange -ay -K <vg name>" processes race to load the dm-thin-pool module:
PID: 25992 TASK: ffff883cd7d23500 CPU: 4 COMMAND: "vgchange" #0 [ffff883cd743d600] machine_kexec at ffffffff81038fa9 0000001 [ffff883cd743d660] crash_kexec at ffffffff810c5992 0000002 [ffff883cd743d730] oops_end at ffffffff81515c90 0000003 [ffff883cd743d760] no_context at ffffffff81049f1b 0000004 [ffff883cd743d7b0] __bad_area_nosemaphore at ffffffff8104a1a5 0000005 [ffff883cd743d800] bad_area at ffffffff8104a2ce 0000006 [ffff883cd743d830] __do_page_fault at ffffffff8104aa6f 0000007 [ffff883cd743d950] do_page_fault at ffffffff81517bae 0000008 [ffff883cd743d980] page_fault at ffffffff81514f95 [exception RIP: kmem_cache_alloc+108] RIP: ffffffff8116ef3c RSP: ffff883cd743da38 RFLAGS: 00010046 RAX: 0000000000000004 RBX: ffffffff81121b90 RCX: ffff881bf1e78cc0 RDX: 0000000000000000 RSI: 00000000000000d0 RDI: 0000000000000000 RBP: ffff883cd743da68 R8: ffff881bf1a4eb00 R9: 0000000080042000 R10: 0000000000002000 R11: 0000000000000000 R12: 00000000000000d0 R13: 0000000000000000 R14: 00000000000000d0 R15: 0000000000000246 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 0000009 [ffff883cd743da70] mempool_alloc_slab at ffffffff81121ba5 0000010 [ffff883cd743da80] mempool_create_node at ffffffff81122083 0000011 [ffff883cd743dad0] mempool_create at ffffffff811220f4 0000012 [ffff883cd743dae0] pool_ctr at ffffffffa08de049 [dm_thin_pool] 0000013 [ffff883cd743dbd0] dm_table_add_target at ffffffffa0005f2f [dm_mod] 0000014 [ffff883cd743dc30] table_load at ffffffffa0008ba9 [dm_mod] 0000015 [ffff883cd743dc90] ctl_ioctl at ffffffffa0009dc4 [dm_mod]
The race results in a NULL pointer because:
Process A (vgchange -ay -K): a. send DM_LIST_VERSIONS_CMD ioctl; b. pool_target not registered; c. modprobe dm_thin_pool and wait until end.
Process B (vgchange -ay -K): a. send DM_LIST_VERSIONS_CMD ioctl; b. pool_target registered; c. table_load->dm_table_add_target->pool_ctr; d. _new_mapping_cache is NULL and panic. Note: 1. process A and process B are two concurrent processes. 2. pool_target can be detected by process B but _new_mapping_cache initialization has not ended.
To fix dm-thin-pool, and other targets (cache, multipath, and snapshot) with the same problem, simply dm_register_target() after all resources created during module init (as labelled with __init) are finished.
Signed-off-by: monty monty_pavel@sina.com Signed-off-by: Mike Snitzer snitzer@redhat.com [bwh: Backported to 3.2: - Drop changes in dm-cache (non-existent) and dm-thin (doesn't have this bug) - In dm-snap, reorder cleanup of tracked_chunk_cache too - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1658,13 +1658,6 @@ static int __init dm_multipath_init(void if (!_mpio_cache) return -ENOMEM;
- r = dm_register_target(&multipath_target); - if (r < 0) { - DMERR("register failed %d", r); - r = -EINVAL; - goto bad_register_target; - } - kmultipathd = alloc_workqueue("kmpathd", WQ_MEM_RECLAIM, 0); if (!kmultipathd) { DMERR("failed to create workqueue kmpathd"); @@ -1686,17 +1679,24 @@ static int __init dm_multipath_init(void goto bad_alloc_kmpath_handlerd; }
+ r = dm_register_target(&multipath_target); + if (r < 0) { + DMERR("register failed %d", r); + r = -EINVAL; + goto bad_register_target; + } + DMINFO("version %u.%u.%u loaded", multipath_target.version[0], multipath_target.version[1], multipath_target.version[2]);
return 0;
+bad_register_target: + destroy_workqueue(kmpath_handlerd); bad_alloc_kmpath_handlerd: destroy_workqueue(kmultipathd); bad_alloc_kmultipathd: - dm_unregister_target(&multipath_target); -bad_register_target: kmem_cache_destroy(_mpio_cache);
return r; --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -2293,24 +2293,6 @@ static int __init dm_snapshot_init(void) return r; }
- r = dm_register_target(&snapshot_target); - if (r < 0) { - DMERR("snapshot target register failed %d", r); - goto bad_register_snapshot_target; - } - - r = dm_register_target(&origin_target); - if (r < 0) { - DMERR("Origin target register failed %d", r); - goto bad_register_origin_target; - } - - r = dm_register_target(&merge_target); - if (r < 0) { - DMERR("Merge target register failed %d", r); - goto bad_register_merge_target; - } - r = init_origin_hash(); if (r) { DMERR("init_origin_hash failed."); @@ -2338,8 +2320,32 @@ static int __init dm_snapshot_init(void) goto bad_tracked_chunk_cache; }
+ r = dm_register_target(&snapshot_target); + if (r < 0) { + DMERR("snapshot target register failed %d", r); + goto bad_register_snapshot_target; + } + + r = dm_register_target(&origin_target); + if (r < 0) { + DMERR("Origin target register failed %d", r); + goto bad_register_origin_target; + } + + r = dm_register_target(&merge_target); + if (r < 0) { + DMERR("Merge target register failed %d", r); + goto bad_register_merge_target; + } + return 0;
+bad_register_merge_target: + dm_unregister_target(&origin_target); +bad_register_origin_target: + dm_unregister_target(&snapshot_target); +bad_register_snapshot_target: + kmem_cache_destroy(tracked_chunk_cache); bad_tracked_chunk_cache: kmem_cache_destroy(pending_cache); bad_pending_cache: @@ -2347,12 +2353,6 @@ bad_pending_cache: bad_exception_cache: exit_origin_hash(); bad_origin_hash: - dm_unregister_target(&merge_target); -bad_register_merge_target: - dm_unregister_target(&origin_target); -bad_register_origin_target: - dm_unregister_target(&snapshot_target); -bad_register_snapshot_target: dm_exception_store_exit();
return r;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jaejoong Kim climbbb.kim@gmail.com
commit 251552a2b0d454badc8f486e6d79100970c744b0 upstream.
The snd_usb_copy_string_desc() retrieves the usb string corresponding to the index number through the usb_string(). The problem is that the usb_string() returns the length of the string (>= 0) when successful, but it can also return a negative value about the error case or status of usb_control_msg().
If iClockSource is '0' as shown below, usb_string() will returns -EINVAL. This will result in '0' being inserted into buf[-22], and the following KASAN out-of-bound error message will be output.
AudioControl Interface Descriptor: bLength 8 bDescriptorType 36 bDescriptorSubtype 10 (CLOCK_SOURCE) bClockID 1 bmAttributes 0x07 Internal programmable Clock (synced to SOF) bmControls 0x07 Clock Frequency Control (read/write) Clock Validity Control (read-only) bAssocTerminal 0 iClockSource 0
To fix it, check usb_string()'return value and bail out.
================================================================== BUG: KASAN: stack-out-of-bounds in parse_audio_unit+0x1327/0x1960 [snd_usb_audio] Write of size 1 at addr ffff88007e66735a by task systemd-udevd/18376
CPU: 0 PID: 18376 Comm: systemd-udevd Not tainted 4.13.0+ #3 Hardware name: LG Electronics 15N540-RFLGL/White Tip Mountain, BIOS 15N5 Call Trace: dump_stack+0x63/0x8d print_address_description+0x70/0x290 ? parse_audio_unit+0x1327/0x1960 [snd_usb_audio] kasan_report+0x265/0x350 __asan_store1+0x4a/0x50 parse_audio_unit+0x1327/0x1960 [snd_usb_audio] ? save_stack+0xb5/0xd0 ? save_stack_trace+0x1b/0x20 ? save_stack+0x46/0xd0 ? kasan_kmalloc+0xad/0xe0 ? kmem_cache_alloc_trace+0xff/0x230 ? snd_usb_create_mixer+0xb0/0x4b0 [snd_usb_audio] ? usb_audio_probe+0x4de/0xf40 [snd_usb_audio] ? usb_probe_interface+0x1f5/0x440 ? driver_probe_device+0x3ed/0x660 ? build_feature_ctl+0xb10/0xb10 [snd_usb_audio] ? save_stack_trace+0x1b/0x20 ? init_object+0x69/0xa0 ? snd_usb_find_csint_desc+0xa8/0xf0 [snd_usb_audio] snd_usb_mixer_controls+0x1dc/0x370 [snd_usb_audio] ? build_audio_procunit+0x890/0x890 [snd_usb_audio] ? snd_usb_create_mixer+0xb0/0x4b0 [snd_usb_audio] ? kmem_cache_alloc_trace+0xff/0x230 ? usb_ifnum_to_if+0xbd/0xf0 snd_usb_create_mixer+0x25b/0x4b0 [snd_usb_audio] ? snd_usb_create_stream+0x255/0x2c0 [snd_usb_audio] usb_audio_probe+0x4de/0xf40 [snd_usb_audio] ? snd_usb_autosuspend.part.7+0x30/0x30 [snd_usb_audio] ? __pm_runtime_idle+0x90/0x90 ? kernfs_activate+0xa6/0xc0 ? usb_match_one_id_intf+0xdc/0x130 ? __pm_runtime_set_status+0x2d4/0x450 usb_probe_interface+0x1f5/0x440
Signed-off-by: Jaejoong Kim climbbb.kim@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/usb/mixer.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -197,6 +197,10 @@ static void *find_audio_control_unit(str static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen) { int len = usb_string(state->chip->dev, index, buf, maxlen - 1); + + if (len < 0) + return 0; + buf[len] = 0; return len; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu herbert@gondor.apana.org.au
commit c008ba5bdc9fa830e1a349b20b0be5a137bdef7a upstream.
Ever since raw_probe_proto_opt was added it had the problem of causing the user iov to be read twice, once during the probe for the protocol header and once again in ip_append_data.
This is a potential security problem since it means that whatever we're probing may be invalid. This patch plugs the hole by firstly advancing the iov so we don't read the same spot again, and secondly saving what we read the first time around for use by ip_append_data.
Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/ipv4/raw.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 8 deletions(-)
--- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -78,6 +78,16 @@ #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/compat.h> +#include <linux/uio.h> + +struct raw_frag_vec { + struct iovec *iov; + union { + struct icmphdr icmph; + char c[1]; + } hdr; + int hlen; +};
static struct raw_hashinfo raw_v4_hashinfo = { .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock), @@ -409,25 +419,57 @@ error: return err; }
-static int raw_probe_proto_opt(struct flowi4 *fl4, struct msghdr *msg) +static int raw_probe_proto_opt(struct raw_frag_vec *rfv, struct flowi4 *fl4) { - struct icmphdr icmph; int err;
if (fl4->flowi4_proto != IPPROTO_ICMP) return 0;
/* We only need the first two bytes. */ - err = memcpy_fromiovecend((void *)&icmph, msg->msg_iov, 0, 2); + rfv->hlen = 2; + + err = memcpy_fromiovec(rfv->hdr.c, rfv->iov, rfv->hlen); if (err) return err;
- fl4->fl4_icmp_type = icmph.type; - fl4->fl4_icmp_code = icmph.code; + fl4->fl4_icmp_type = rfv->hdr.icmph.type; + fl4->fl4_icmp_code = rfv->hdr.icmph.code;
return 0; }
+static int raw_getfrag(void *from, char *to, int offset, int len, int odd, + struct sk_buff *skb) +{ + struct raw_frag_vec *rfv = from; + + if (offset < rfv->hlen) { + int copy = min(rfv->hlen - offset, len); + + if (skb->ip_summed == CHECKSUM_PARTIAL) + memcpy(to, rfv->hdr.c + offset, copy); + else + skb->csum = csum_block_add( + skb->csum, + csum_partial_copy_nocheck(rfv->hdr.c + offset, + to, copy, 0), + odd); + + odd = 0; + offset += copy; + to += copy; + len -= copy; + + if (!len) + return 0; + } + + offset -= rfv->hlen; + + return ip_generic_getfrag(rfv->iov, to, offset, len, odd, skb); +} + static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) { @@ -441,6 +483,7 @@ static int raw_sendmsg(struct kiocb *ioc u8 tos; int err; struct ip_options_data opt_copy; + struct raw_frag_vec rfv;
err = -EMSGSIZE; if (len > 0xFFFF) @@ -547,7 +590,10 @@ static int raw_sendmsg(struct kiocb *ioc daddr, saddr, 0, 0);
if (!inet->hdrincl) { - err = raw_probe_proto_opt(&fl4, msg); + rfv.iov = msg->msg_iov; + rfv.hlen = 0; + + err = raw_probe_proto_opt(&rfv, &fl4); if (err) goto done; } @@ -576,8 +622,8 @@ back_from_confirm: if (!ipc.addr) ipc.addr = fl4.daddr; lock_sock(sk); - err = ip_append_data(sk, &fl4, ip_generic_getfrag, - msg->msg_iov, len, 0, + err = ip_append_data(sk, &fl4, raw_getfrag, + &rfv, len, 0, &ipc, &rt, msg->msg_flags); if (err) ip_flush_pending_frames(sk);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: SZ Lin (林上智) sz.lin@moxa.com
commit 3920bb713038810f25770e7545b79f204685c8f2 upstream.
This patch adds support for YUGA CLM920-NC5 PID 0x9625 USB modem to option driver.
Interface layout: 0: QCDM/DIAG 1: ADB 2: MODEM 3: AT 4: RMNET
Signed-off-by: Taiyi Wu taiyity.wu@moxa.com Signed-off-by: SZ Lin (林上智) sz.lin@moxa.com Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/serial/option.c | 9 +++++++++ 1 file changed, 9 insertions(+)
--- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -237,6 +237,8 @@ static void option_instat_callback(struc /* These Quectel products use Qualcomm's vendor ID */ #define QUECTEL_PRODUCT_UC20 0x9003 #define QUECTEL_PRODUCT_UC15 0x9090 +/* These Yuga products use Qualcomm's vendor ID */ +#define YUGA_PRODUCT_CLM920_NC5 0x9625
#define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ @@ -657,6 +659,10 @@ static const struct option_blacklist_inf .reserved = BIT(1) | BIT(2) | BIT(3), };
+static const struct option_blacklist_info yuga_clm920_nc5_blacklist = { + .reserved = BIT(1) | BIT(4), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -1161,6 +1167,9 @@ static const struct usb_device_id option { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + /* Yuga products use Qualcomm vendor ID */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, YUGA_PRODUCT_CLM920_NC5), + .driver_info = (kernel_ulong_t)&yuga_clm920_nc5_blacklist }, /* Quectel products using Quectel vendor ID */ { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21), .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heiner Kallweit hkallweit1@gmail.com
commit d9bcd462daf34aebb8de9ad7f76de0198bb5a0f0 upstream.
So far we completely rely on the caller to provide valid arguments. To be on the safe side perform an own sanity check.
Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Signed-off-by: Bartosz Golaszewski brgl@bgdev.pl Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/misc/eeprom/at24.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -274,6 +274,9 @@ static ssize_t at24_read(struct at24_dat if (unlikely(!count)) return count;
+ if (off + count > at24->chip.byte_len) + return -EINVAL; + /* * Read data from chip, protecting against concurrent updates * from this host, but not from other I2C masters. @@ -396,6 +399,9 @@ static ssize_t at24_write(struct at24_da if (unlikely(!count)) return count;
+ if (off + count > at24->chip.byte_len) + return -EINVAL; + /* * Write data to chip, protecting against concurrent updates * from this host, but not from other I2C masters.
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Thiago Rafael Becker thiago.becker@gmail.com
commit bdcf0a423ea1c40bbb40e7ee483b50fc8aa3d758 upstream.
In testing, we found that nfsd threads may call set_groups in parallel for the same entry cached in auth.unix.gid, racing in the call of groups_sort, corrupting the groups for that entry and leading to permission denials for the client.
This patch: - Make groups_sort globally visible. - Move the call to groups_sort to the modifiers of group_info - Remove the call to groups_sort from set_groups
Link: http://lkml.kernel.org/r/20171211151420.18655-1-thiago.becker@gmail.com Signed-off-by: Thiago Rafael Becker thiago.becker@gmail.com Reviewed-by: Matthew Wilcox mawilcox@microsoft.com Reviewed-by: NeilBrown neilb@suse.com Acked-by: "J. Bruce Fields" bfields@fieldses.org Cc: Al Viro viro@zeniv.linux.org.uk Cc: Martin Schwidefsky schwidefsky@de.ibm.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org [bwh: Backported to 3.2: - Drop change in gss_rpc_xdr.c - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -242,6 +242,7 @@ asmlinkage long sys32_setgroups16(int gi return retval; }
+ groups_sort(group_info); retval = set_current_groups(group_info); put_group_info(group_info);
--- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c @@ -60,6 +60,9 @@ int nfsd_setuser(struct svc_rqst *rqstp, GROUP_AT(gi, i) = exp->ex_anon_gid; else GROUP_AT(gi, i) = GROUP_AT(rqgi, i); + + /* Each thread allocates its own gi, no race */ + groups_sort(gi); } } else { gi = get_group_info(rqgi); --- a/include/linux/cred.h +++ b/include/linux/cred.h @@ -67,6 +67,7 @@ extern void groups_free(struct group_inf extern int set_current_groups(struct group_info *); extern int set_groups(struct cred *, struct group_info *); extern int groups_search(const struct group_info *, gid_t); +extern void groups_sort(struct group_info *);
/* access the groups "array" with this macro */ #define GROUP_AT(gi, i) \ --- a/kernel/groups.c +++ b/kernel/groups.c @@ -103,7 +103,7 @@ static int groups_from_user(struct group }
/* a simple Shell sort */ -static void groups_sort(struct group_info *group_info) +void groups_sort(struct group_info *group_info) { int base, max, stride; int gidsetsize = group_info->ngroups; @@ -130,6 +130,7 @@ static void groups_sort(struct group_inf stride /= 3; } } +EXPORT_SYMBOL(groups_sort);
/* a simple bsearch */ int groups_search(const struct group_info *group_info, gid_t grp) @@ -164,7 +165,6 @@ int groups_search(const struct group_inf int set_groups(struct cred *new, struct group_info *group_info) { put_group_info(new->group_info); - groups_sort(group_info); get_group_info(group_info); new->group_info = group_info; return 0; @@ -247,6 +247,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsi return retval; }
+ groups_sort(group_info); retval = set_current_groups(group_info); put_group_info(group_info);
--- a/kernel/uid16.c +++ b/kernel/uid16.c @@ -203,6 +203,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidset return retval; }
+ groups_sort(group_info); retval = set_current_groups(group_info); put_group_info(group_info);
--- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -477,6 +477,7 @@ static int rsc_parse(struct cache_detail goto out; GROUP_AT(rsci.cred.cr_group_info, i) = gid; } + groups_sort(rsci.cred.cr_group_info);
/* mech name */ len = qword_get(&mesg, buf, mlen); --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -539,6 +539,7 @@ static int unix_gid_parse(struct cache_d GROUP_AT(ug.gi, i) = gid; }
+ groups_sort(ug.gi); ugp = unix_gid_lookup(uid); if (ugp) { struct cache_head *ch; @@ -806,6 +807,7 @@ svcauth_unix_accept(struct svc_rqst *rqs return SVC_CLOSE; for (i = 0; i < slen; i++) GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); + groups_sort(cred->cr_group_info); if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { *authp = rpc_autherr_badverf; return SVC_DENIED;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Robb Glasser rglasser@google.com
commit 362bca57f5d78220f8b5907b875961af9436e229 upstream.
When the device descriptor is closed, the `substream->runtime` pointer is freed. But another thread may be in the ioctl handler, case SNDRV_CTL_IOCTL_PCM_INFO. This case calls snd_pcm_info_user() which calls snd_pcm_info() which accesses the now freed `substream->runtime`.
Note: this fixes CVE-2017-0861
Signed-off-by: Robb Glasser rglasser@google.com Signed-off-by: Nick Desaulniers ndesaulniers@google.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/pcm.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -145,7 +145,9 @@ static int snd_pcm_control_ioctl(struct err = -ENXIO; goto _error; } + mutex_lock(&pcm->open_mutex); err = snd_pcm_info_user(substream, info); + mutex_unlock(&pcm->open_mutex); _error: mutex_unlock(®ister_mutex); return err;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet edumazet@google.com
commit 15fe076edea787807a7cdc168df832544b58eba6 upstream.
syzbot reported crashes [1] and provided a C repro easing bug hunting.
When/if packet_do_bind() calls __unregister_prot_hook() and releases po->bind_lock, another thread can run packet_notifier() and process an NETDEV_UP event.
This calls register_prot_hook() and hooks again the socket right before first thread is able to grab again po->bind_lock.
Fixes this issue by temporarily setting po->num to 0, as suggested by David Miller.
[1] dev_remove_pack: ffff8801bf16fa80 not found ------------[ cut here ]------------ kernel BUG at net/core/dev.c:7945! ( BUG_ON(!list_empty(&dev->ptype_all)); ) invalid opcode: 0000 [#1] SMP KASAN Dumping ftrace buffer: (ftrace buffer empty) Modules linked in: device syz0 entered promiscuous mode CPU: 0 PID: 3161 Comm: syzkaller404108 Not tainted 4.14.0+ #190 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 task: ffff8801cc57a500 task.stack: ffff8801cc588000 RIP: 0010:netdev_run_todo+0x772/0xae0 net/core/dev.c:7945 RSP: 0018:ffff8801cc58f598 EFLAGS: 00010293 RAX: ffff8801cc57a500 RBX: dffffc0000000000 RCX: ffffffff841f75b2 RDX: 0000000000000000 RSI: 1ffff100398b1ede RDI: ffff8801bf1f8810 device syz0 entered promiscuous mode RBP: ffff8801cc58f898 R08: 0000000000000001 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff8801bf1f8cd8 R13: ffff8801cc58f870 R14: ffff8801bf1f8780 R15: ffff8801cc58f7f0 FS: 0000000001716880(0000) GS:ffff8801db400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020b13000 CR3: 0000000005e25000 CR4: 00000000001406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: rtnl_unlock+0xe/0x10 net/core/rtnetlink.c:106 tun_detach drivers/net/tun.c:670 [inline] tun_chr_close+0x49/0x60 drivers/net/tun.c:2845 __fput+0x333/0x7f0 fs/file_table.c:210 ____fput+0x15/0x20 fs/file_table.c:244 task_work_run+0x199/0x270 kernel/task_work.c:113 exit_task_work include/linux/task_work.h:22 [inline] do_exit+0x9bb/0x1ae0 kernel/exit.c:865 do_group_exit+0x149/0x400 kernel/exit.c:968 SYSC_exit_group kernel/exit.c:979 [inline] SyS_exit_group+0x1d/0x20 kernel/exit.c:977 entry_SYSCALL_64_fastpath+0x1f/0x96 RIP: 0033:0x44ad19
Fixes: 30f7ea1c2b5f ("packet: race condition in packet_bind") Signed-off-by: Eric Dumazet edumazet@google.com Reported-by: syzbot syzkaller@googlegroups.com Cc: Francesco Ruggeri fruggeri@aristanetworks.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: adjust context, indentation] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/packet/af_packet.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2516,6 +2516,10 @@ static int packet_do_bind(struct sock *s
if (po->running) { rcu_read_unlock(); + /* prevents packet_notifier() from calling + * register_prot_hook() + */ + po->num = 0; __unregister_prot_hook(sk, true); rcu_read_lock(); dev_curr = po->prot_hook.dev; @@ -2523,6 +2527,7 @@ static int packet_do_bind(struct sock *s unlisted = !dev_get_by_index_rcu(sock_net(sk), dev->ifindex); } + BUG_ON(po->running); po->num = protocol; po->prot_hook.type = protocol;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Borisov nborisov@suse.com
commit c8bcbfbd239ed60a6562964b58034ac8a25f4c31 upstream.
The name char array passed to btrfs_search_path_in_tree is of size BTRFS_INO_LOOKUP_PATH_MAX (4080). So the actual accessible char indexes are in the range of [0, 4079]. Currently the code uses the define but this represents an off-by-one.
Implications:
Size of btrfs_ioctl_ino_lookup_args is 4096, so the new byte will be written to extra space, not some padding that could be provided by the allocator.
btrfs-progs store the arguments on stack, but kernel does own copy of the ioctl buffer and the off-by-one overwrite does not affect userspace, but the ending 0 might be lost.
Kernel ioctl buffer is allocated dynamically so we're overwriting somebody else's memory, and the ioctl is privileged if args.objectid is not 256. Which is in most cases, but resolving a subvolume stored in another directory will trigger that path.
Before this patch the buffer was one byte larger, but then the -1 was not added.
Fixes: ac8e9819d71f907 ("Btrfs: add search and inode lookup ioctls") Signed-off-by: Nikolay Borisov nborisov@suse.com Reviewed-by: David Sterba dsterba@suse.com [ added implications ] Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- fs/btrfs/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1751,7 +1751,7 @@ static noinline int btrfs_search_path_in if (!path) return -ENOMEM;
- ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX]; + ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX - 1];
key.objectid = tree_id; key.type = BTRFS_ROOT_ITEM_KEY;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik jbacik@fb.com
commit 8e138e0d92c6c9d3d481674fb14e3439b495be37 upstream.
We discovered a box that had double allocations, and suspected the space cache may be to blame. While auditing the write out path I noticed that if we've already setup the space cache we will just carry on. This means that any error we hit after cache_save_setup before we go to actually write the cache out we won't reset the inode generation, so whatever was already written will be considered correct, except it'll be stale. Fix this by _always_ resetting the generation on the block group inode, this way we only ever have valid or invalid cache.
With this patch I was no longer able to reproduce cache corruption with dm-log-writes and my bpf error injection tool.
Signed-off-by: Josef Bacik jbacik@fb.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- fs/btrfs/extent-tree.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
--- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2759,13 +2759,6 @@ again: goto again; }
- /* We've already setup this transaction, go ahead and exit */ - if (block_group->cache_generation == trans->transid && - i_size_read(inode)) { - dcs = BTRFS_DC_SETUP; - goto out_put; - } - /* * We want to set the generation to 0, that way if anything goes wrong * from here on out we know not to trust this cache when we load up next @@ -2775,6 +2768,13 @@ again: ret = btrfs_update_inode(trans, root, inode); WARN_ON(ret);
+ /* We've already setup this transaction, go ahead and exit */ + if (block_group->cache_generation == trans->transid && + i_size_read(inode)) { + dcs = BTRFS_DC_SETUP; + goto out_put; + } + if (i_size_read(inode) > 0) { ret = btrfs_truncate_free_space_cache(root, trans, path, inode);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov nikolay@cumulusnetworks.com
commit 84aeb437ab98a2bce3d4b2111c79723aedfceb33 upstream.
The early call to br_stp_change_bridge_id in bridge's newlink can cause a memory leak if an error occurs during the newlink because the fdb entries are not cleaned up if a different lladdr was specified, also another minor issue is that it generates fdb notifications with ifindex = 0. Another unrelated memory leak is the bridge sysfs entries which get added on NETDEV_REGISTER event, but are not cleaned up in the newlink error path. To remove this special case the call to br_stp_change_bridge_id is done after netdev register and we cleanup the bridge on changelink error via br_dev_delete to plug all leaks.
This patch makes netlink bridge destruction on newlink error the same as dellink and ioctl del which is necessary since at that point we have a fully initialized bridge device.
To reproduce the issue: $ ip l add br0 address 00:11:22:33:44:55 type bridge group_fwd_mask 1 RTNETLINK answers: Invalid argument
$ rmmod bridge [ 1822.142525] ============================================================================= [ 1822.143640] BUG bridge_fdb_cache (Tainted: G O ): Objects remaining in bridge_fdb_cache on __kmem_cache_shutdown() [ 1822.144821] -----------------------------------------------------------------------------
[ 1822.145990] Disabling lock debugging due to kernel taint [ 1822.146732] INFO: Slab 0x0000000092a844b2 objects=32 used=2 fp=0x00000000fef011b0 flags=0x1ffff8000000100 [ 1822.147700] CPU: 2 PID: 13584 Comm: rmmod Tainted: G B O 4.15.0-rc2+ #87 [ 1822.148578] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014 [ 1822.150008] Call Trace: [ 1822.150510] dump_stack+0x78/0xa9 [ 1822.151156] slab_err+0xb1/0xd3 [ 1822.151834] ? __kmalloc+0x1bb/0x1ce [ 1822.152546] __kmem_cache_shutdown+0x151/0x28b [ 1822.153395] shutdown_cache+0x13/0x144 [ 1822.154126] kmem_cache_destroy+0x1c0/0x1fb [ 1822.154669] SyS_delete_module+0x194/0x244 [ 1822.155199] ? trace_hardirqs_on_thunk+0x1a/0x1c [ 1822.155773] entry_SYSCALL_64_fastpath+0x23/0x9a [ 1822.156343] RIP: 0033:0x7f929bd38b17 [ 1822.156859] RSP: 002b:00007ffd160e9a98 EFLAGS: 00000202 ORIG_RAX: 00000000000000b0 [ 1822.157728] RAX: ffffffffffffffda RBX: 00005578316ba090 RCX: 00007f929bd38b17 [ 1822.158422] RDX: 00007f929bd9ec60 RSI: 0000000000000800 RDI: 00005578316ba0f0 [ 1822.159114] RBP: 0000000000000003 R08: 00007f929bff5f20 R09: 00007ffd160e8a11 [ 1822.159808] R10: 00007ffd160e9860 R11: 0000000000000202 R12: 00007ffd160e8a80 [ 1822.160513] R13: 0000000000000000 R14: 0000000000000000 R15: 00005578316ba090 [ 1822.161278] INFO: Object 0x000000007645de29 @offset=0 [ 1822.161666] INFO: Object 0x00000000d5df2ab5 @offset=128
Fixes: 30313a3d5794 ("bridge: Handle IFLA_ADDRESS correctly when creating bridge device") Fixes: 5b8d5429daa0 ("bridge: netlink: register netdevice before executing changelink") Signed-off-by: Nikolay Aleksandrov nikolay@cumulusnetworks.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: register_netdevice() was the last thing done in br_dev_newlink(), so no extra cleanup is needed] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -215,6 +215,11 @@ static int br_dev_newlink(struct net *sr struct nlattr *tb[], struct nlattr *data[]) { struct net_bridge *br = netdev_priv(dev); + int err; + + err = register_netdevice(dev); + if (err) + return err;
if (tb[IFLA_ADDRESS]) { spin_lock_bh(&br->lock); @@ -222,7 +227,7 @@ static int br_dev_newlink(struct net *sr spin_unlock_bh(&br->lock); }
- return register_netdevice(dev); + return 0; }
struct rtnl_link_ops br_link_ops __read_mostly = {
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu herbert@gondor.apana.org.au
commit acf568ee859f098279eadf551612f103afdacb4e upstream.
This is an old bugbear of mine:
https://www.mail-archive.com/netdev@vger.kernel.org/msg03894.html
By crafting special packets, it is possible to cause recursion in our kernel when processing transport-mode packets at levels that are only limited by packet size.
The easiest one is with DNAT, but an even worse one is where UDP encapsulation is used in which case you just have to insert an UDP encapsulation header in between each level of recursion.
This patch avoids this problem by reinjecting tranport-mode packets through a tasklet.
Fixes: b05e106698d9 ("[IPV4/6]: Netfilter IPsec input hooks") Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Steffen Klassert steffen.klassert@secunet.com [bwh: Backported to 3.2: - netfilter finish callbacks only receive an sk_buff pointer - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1439,6 +1439,7 @@ extern int xfrm_prepare_input(struct xfr extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type); extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr); +int xfrm_trans_queue(struct sk_buff *skb, int (*finish)(struct sk_buff *)); extern int xfrm_output_resume(struct sk_buff *skb, int err); extern int xfrm_output(struct sk_buff *skb); extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb); --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -22,6 +22,11 @@ int xfrm4_extract_input(struct xfrm_stat return xfrm4_extract_header(skb); }
+static int xfrm4_rcv_encap_finish2(struct sk_buff *skb) +{ + return dst_input(skb); +} + static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) { if (skb_dst(skb) == NULL) { @@ -31,7 +36,11 @@ static inline int xfrm4_rcv_encap_finish iph->tos, skb->dev)) goto drop; } - return dst_input(skb); + + if (xfrm_trans_queue(skb, xfrm4_rcv_encap_finish2)) + goto drop; + + return 0; drop: kfree_skb(skb); return NET_RX_DROP; --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -29,6 +29,13 @@ int xfrm6_rcv_spi(struct sk_buff *skb, i } EXPORT_SYMBOL(xfrm6_rcv_spi);
+static int xfrm6_transport_finish2(struct sk_buff *skb) +{ + if (xfrm_trans_queue(skb, ip6_rcv_finish)) + __kfree_skb(skb); + return -1; +} + int xfrm6_transport_finish(struct sk_buff *skb, int async) { skb_network_header(skb)[IP6CB(skb)->nhoff] = @@ -43,7 +50,7 @@ int xfrm6_transport_finish(struct sk_buf __skb_push(skb, skb->data - skb_network_header(skb));
NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, - ip6_rcv_finish); + xfrm6_transport_finish2); return -1; }
--- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -7,15 +7,31 @@ * */
+#include <linux/bottom_half.h> +#include <linux/interrupt.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/netdevice.h> +#include <linux/percpu.h> #include <net/dst.h> #include <net/ip.h> #include <net/xfrm.h>
+struct xfrm_trans_tasklet { + struct tasklet_struct tasklet; + struct sk_buff_head queue; +}; + +struct xfrm_trans_cb { + int (*finish)(struct sk_buff *skb); +}; + +#define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0])) + static struct kmem_cache *secpath_cachep __read_mostly;
+static DEFINE_PER_CPU(struct xfrm_trans_tasklet, xfrm_trans_tasklet); + void __secpath_destroy(struct sec_path *sp) { int i; @@ -285,10 +301,50 @@ int xfrm_input_resume(struct sk_buff *sk } EXPORT_SYMBOL(xfrm_input_resume);
+static void xfrm_trans_reinject(unsigned long data) +{ + struct xfrm_trans_tasklet *trans = (void *)data; + struct sk_buff_head queue; + struct sk_buff *skb; + + __skb_queue_head_init(&queue); + skb_queue_splice_init(&trans->queue, &queue); + + while ((skb = __skb_dequeue(&queue))) + XFRM_TRANS_SKB_CB(skb)->finish(skb); +} + +int xfrm_trans_queue(struct sk_buff *skb, int (*finish)(struct sk_buff *)) +{ + struct xfrm_trans_tasklet *trans; + + trans = this_cpu_ptr(&xfrm_trans_tasklet); + + if (skb_queue_len(&trans->queue) >= netdev_max_backlog) + return -ENOBUFS; + + XFRM_TRANS_SKB_CB(skb)->finish = finish; + skb_queue_tail(&trans->queue, skb); + tasklet_schedule(&trans->tasklet); + return 0; +} +EXPORT_SYMBOL(xfrm_trans_queue); + void __init xfrm_input_init(void) { + int i; + secpath_cachep = kmem_cache_create("secpath_cache", sizeof(struct sec_path), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + + for_each_possible_cpu(i) { + struct xfrm_trans_tasklet *trans; + + trans = &per_cpu(xfrm_trans_tasklet, i); + __skb_queue_head_init(&trans->queue); + tasklet_init(&trans->tasklet, xfrm_trans_reinject, + (unsigned long)trans); + } }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Max Schulze max.schulze@posteo.de
commit c6a36ad383559a60a249aa6016cebf3cb8b6c485 upstream.
Add AIRBUS_DS_P8GR device IDs to ftdi_sio driver.
Signed-off-by: Max Schulze max.schulze@posteo.de Signed-off-by: Johan Hovold johan@kernel.org [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 7 insertions(+)
--- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1037,6 +1037,7 @@ static struct usb_device_id id_table_com .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) }, { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) }, + { USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -899,6 +899,12 @@ #define ICPDAS_I7563U_PID 0x0105
/* + * Airbus Defence and Space + */ +#define AIRBUS_DS_VID 0x1e8e /* Vendor ID */ +#define AIRBUS_DS_P8GR 0x6001 /* Tetra P8GR */ + +/* * RT Systems programming cables for various ham radios */ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Tianyu Lan lantianyu1986@gmail.com
commit 37b95951c58fdf08dc10afa9d02066ed9f176fb5 upstream.
kvm_valid_sregs() should use X86_CR0_PG and X86_CR4_PAE to check bit status rather than X86_CR0_PG_BIT and X86_CR4_PAE_BIT. This patch is to fix it.
Fixes: f29810335965a(KVM/x86: Check input paging mode when cs.l is set) Reported-by: Jeremi Piotrowski jeremi.piotrowski@gmail.com Cc: Paolo Bonzini pbonzini@redhat.com Cc: Radim Krčmář rkrcmar@redhat.com Signed-off-by: Tianyu Lan Tianyu.Lan@microsoft.com Signed-off-by: Radim Krčmář rkrcmar@redhat.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/x86/kvm/x86.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6174,13 +6174,13 @@ EXPORT_SYMBOL_GPL(kvm_task_switch);
int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) { - if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG_BIT)) { + if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG)) { /* * When EFER.LME and CR0.PG are set, the processor is in * 64-bit mode (though maybe in a 32-bit code segment). * CR4.PAE and EFER.LMA must be set. */ - if (!(sregs->cr4 & X86_CR4_PAE_BIT) + if (!(sregs->cr4 & X86_CR4_PAE) || !(sregs->efer & EFER_LMA)) return -EINVAL; } else {
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Christian Holl cyborgx1@gmail.com
commit d14ac576d10f865970bb1324d337e5e24d79aaf4 upstream.
This adds the ELV ALC 8xxx Battery Charging device to the list of USB IDs of drivers/usb/serial/cp210x.c
Signed-off-by: Christian Holl cyborgx1@gmail.com Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -177,6 +177,7 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */ + { USB_DEVICE(0x18EF, 0xE030) }, /* ELV ALC 8xxx Battery Charger */ { USB_DEVICE(0x18EF, 0xE032) }, /* ELV TFD500 Data Logger */ { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@google.com
commit 9a00674213a3f00394f4e3221b88f2d21fc05789 upstream.
syzkaller triggered a NULL pointer dereference in crypto_remove_spawns() via a program that repeatedly and concurrently requests AEADs "authenc(cmac(des3_ede-asm),pcbc-aes-aesni)" and hashes "cmac(des3_ede)" through AF_ALG, where the hashes are requested as "untested" (CRYPTO_ALG_TESTED is set in ->salg_mask but clear in ->salg_feat; this causes the template to be instantiated for every request).
Although AF_ALG users really shouldn't be able to request an "untested" algorithm, the NULL pointer dereference is actually caused by a longstanding race condition where crypto_remove_spawns() can encounter an instance which has had spawn(s) "grabbed" but hasn't yet been registered, resulting in ->cra_users still being NULL.
We probably should properly initialize ->cra_users earlier, but that would require updating many templates individually. For now just fix the bug in a simple way that can easily be backported: make crypto_remove_spawns() treat a NULL ->cra_users list as empty.
Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Eric Biggers ebiggers@google.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Ben Hutchings ben@decadent.org.uk --- crypto/algapi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
--- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -163,6 +163,18 @@ void crypto_remove_spawns(struct crypto_
spawn->alg = NULL; spawns = &inst->alg.cra_users; + + /* + * We may encounter an unregistered instance here, since + * an instance's spawns are set up prior to the instance + * being registered. An unregistered instance will have + * NULL ->cra_users.next, since ->cra_users isn't + * properly initialized until registration. But an + * unregistered instance cannot have any users, so treat + * it the same as ->cra_users being empty. + */ + if (spawns->next == NULL) + break; } } while ((spawns = crypto_more_spawns(alg, &stack, &top, &secondary_spawns)));
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Joe Thornber thornber@redhat.com
commit bc68d0a43560e950850fc69b58f0f8254b28f6d6 upstream.
When inserting a new key/value pair into a btree we walk down the spine of btree nodes performing the following 2 operations:
i) space for a new entry ii) adjusting the first key entry if the new key is lower than any in the node.
If the _root_ node is full, the function btree_split_beneath() allocates 2 new nodes, and redistibutes the root nodes entries between them. The root node is left with 2 entries corresponding to the 2 new nodes.
btree_split_beneath() then adjusts the spine to point to one of the two new children. This means the first key is never adjusted if the new key was lower, ie. operation (ii) gets missed out. This can result in the new key being 'lost' for a period; until another low valued key is inserted that will uncover it.
This is a serious bug, and quite hard to make trigger in normal use. A reproducing test case ("thin create devices-in-reverse-order") is available as part of the thin-provision-tools project: https://github.com/jthornber/thin-provisioning-tools/blob/master/functional-...
Fix the issue by changing btree_split_beneath() so it no longer adjusts the spine. Instead it unlocks both the new nodes, and lets the main loop in btree_insert_raw() relock the appropriate one and make any neccessary adjustments.
Reported-by: Monty Pavel monty_pavel@sina.com Signed-off-by: Joe Thornber thornber@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/md/persistent-data/dm-btree.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-)
--- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -568,23 +568,8 @@ static int btree_split_beneath(struct sh pn->keys[1] = rn->keys[0]; memcpy_disk(value_ptr(pn, 1, sizeof(__le64)), &val, sizeof(__le64));
- /* - * rejig the spine. This is ugly, since it knows too - * much about the spine - */ - if (s->nodes[0] != new_parent) { - unlock_block(s->info, s->nodes[0]); - s->nodes[0] = new_parent; - } - if (key < le64_to_cpu(rn->keys[0])) { - unlock_block(s->info, right); - s->nodes[1] = left; - } else { - unlock_block(s->info, left); - s->nodes[1] = right; - } - s->count = 2; - + unlock_block(s->info, left); + unlock_block(s->info, right); return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu herbert@gondor.apana.org.au
commit bcfd09f7837f5240c30fd2f52ee7293516641faa upstream.
Currently esp will happily create an xfrm state with an unknown encap type for IPv4, without setting the necessary state parameters. This patch fixes it by returning -EINVAL.
There is a similar problem in IPv6 where if the mode is unknown we will skip initialisation while returning zero. However, this is harmless as the mode has already been checked further up the stack. This patch removes this anomaly by aligning the IPv6 behaviour with IPv4 and treating unknown modes (which cannot actually happen) as transport mode.
Fixes: 38320c70d282 ("[IPSEC]: Use crypto_aead and authenc in ESP") Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/ipv4/esp4.c | 1 + net/ipv6/esp6.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-)
--- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -658,6 +658,7 @@ static int esp_init_state(struct xfrm_st
switch (encap->encap_type) { default: + err = -EINVAL; goto error; case UDP_ENCAP_ESPINUDP: x->props.header_len += sizeof(struct udphdr); --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -606,13 +606,12 @@ static int esp6_init_state(struct xfrm_s x->props.header_len += IPV4_BEET_PHMAXLEN + (sizeof(struct ipv6hdr) - sizeof(struct iphdr)); break; + default: case XFRM_MODE_TRANSPORT: break; case XFRM_MODE_TUNNEL: x->props.header_len += sizeof(struct ipv6hdr); break; - default: - goto error; }
align = ALIGN(crypto_aead_blocksize(aead), 4);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 23b19b7b50fe1867da8d431eea9cd3e4b6328c2c upstream.
muldiv32() contains a snd_BUG_ON() (which is morphed as WARN_ON() with debug option) for checking the case of 0 / 0. This would be helpful if this happens only as a logical error; however, since the hw refine is performed with any data set provided by user, the inconsistent values that can trigger such a condition might be passed easily. Actually, syzbot caught this by passing some zero'ed old hw_params ioctl.
So, having snd_BUG_ON() there is simply superfluous and rather harmful to give unnecessary confusions. Let's get rid of it.
Reported-by: syzbot+7e6ee55011deeebce15d@syzkaller.appspotmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/pcm_lib.c | 1 - 1 file changed, 1 deletion(-)
--- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -590,7 +590,6 @@ static inline unsigned int muldiv32(unsi { u_int64_t n = (u_int64_t) a * b; if (c == 0) { - snd_BUG_ON(!n); *r = 0; return UINT_MAX; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg johannes.berg@intel.com
commit 59b179b48ce2a6076448a44531242ac2b3f6cef2 upstream.
syzbot reported a warning from rfkill_alloc(), and after a while I think that the reason is that it was doing fault injection and the dev_set_name() failed, leaving the name NULL, and we didn't check the return value and got to rfkill_alloc() with a NULL name. Since we really don't want a NULL name, we ought to check the return value.
Fixes: fb28ad35906a ("net: struct device - replace bus_id with dev_name(), dev_set_name()") Reported-by: syzbot+1ddfb3357e1d7bb5b5d3@syzkaller.appspotmail.com Signed-off-by: Johannes Berg johannes.berg@intel.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -329,6 +329,7 @@ struct wiphy *wiphy_new(const struct cfg
struct cfg80211_registered_device *rdev; int alloc_size; + int rv;
WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key)); WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc)); @@ -362,7 +363,11 @@ struct wiphy *wiphy_new(const struct cfg mutex_unlock(&cfg80211_mutex);
/* give it a proper name */ - dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); + rv = dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); + if (rv < 0) { + kfree(rdev); + return NULL; + }
mutex_init(&rdev->mtx); mutex_init(&rdev->devlist_mtx);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Denys Vlasenko dvlasenk@redhat.com
commit 3876488444e71238e287459c39d7692b6f718c3e upstream.
Suggested by Andy.
Suggested-by: Andy Lutomirski luto@amacapital.net Signed-off-by: Denys Vlasenko dvlasenk@redhat.com Acked-by: Linus Torvalds torvalds@linux-foundation.org Cc: Alexei Starovoitov ast@plumgrid.com Cc: Borislav Petkov bp@alien8.de Cc: Frederic Weisbecker fweisbec@gmail.com Cc: H. Peter Anvin hpa@zytor.com Cc: Kees Cook keescook@chromium.org Cc: Oleg Nesterov oleg@redhat.com Cc: Steven Rostedt rostedt@goodmis.org Cc: Will Drewry wad@chromium.org Link: http://lkml.kernel.org/r/1425912738-559-1-git-send-email-dvlasenk@redhat.com Signed-off-by: Ingo Molnar mingo@kernel.org [bwh: Backported to 3.2: - There is no definition in vfio.h to move - Put the definition inside the #ifdef __KERNEL__ section] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/include/linux/stddef.h +++ b/include/linux/stddef.h @@ -23,6 +23,16 @@ enum { #else #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #endif + +/** + * offsetofend(TYPE, MEMBER) + * + * @TYPE: The type of the structure + * @MEMBER: The member within the structure to get the end offset of + */ +#define offsetofend(TYPE, MEMBER) \ + (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER)) + #endif /* __KERNEL__ */
#endif
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Geert Uytterhoeven geert@linux-m68k.org
commit a6b202979661eb32646048aeaad7be7b70c2cd22 upstream.
Commit acdc0d5ef9dd ('m32r: fix breakage from "m32r: use generic ptrace_resume code"') tried to fix a problem in commit e34112e3966fc ("m32r: use generic ptrace_resume code") by returning values in a function returning void, causing:
arch/m32r/kernel/ptrace.c: In function 'user_enable_single_step': arch/m32r/kernel/ptrace.c:594:3: warning: 'return' with a value, in function returning void [enabled by default] arch/m32r/kernel/ptrace.c:598:3: warning: 'return' with a value, in function returning void [enabled by default] arch/m32r/kernel/ptrace.c:601:3: warning: 'return' with a value, in function returning void [enabled by default] arch/m32r/kernel/ptrace.c:604:2: warning: 'return' with a value, in function returning void [enabled by default]
Remove the unneeded return values.
Signed-off-by: Geert Uytterhoeven geert@linux-m68k.org Cc: Al Viro viro@zeniv.linux.org.uk Cc: Christoph Hellwig hch@lst.de Cc: Hirokazu Takata takata@linux-m32r.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/m32r/kernel/ptrace.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
--- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -592,17 +592,16 @@ void user_enable_single_step(struct task
if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) != sizeof(insn)) - return -EIO; + return;
compute_next_pc(insn, pc, &next_pc, child); if (next_pc & 0x80000000) - return -EIO; + return;
if (embed_debug_trap(child, next_pc)) - return -EIO; + return;
invalidate_cache(); - return 0; }
void user_disable_single_step(struct task_struct *child)
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream.
There is nothing wrong with using an unknown buffer type. So stop spamming the kernel log whenever this happens. The kernel will just return -EINVAL to signal this.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 4 ---- 1 file changed, 4 deletions(-)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -175,8 +175,6 @@ static int __get_v4l2_format32(struct v4 return -EFAULT; return 0; default: - printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", - kp->type); return -EINVAL; } } @@ -226,8 +224,6 @@ static int __put_v4l2_format32(struct v4 return -EFAULT; return 0; default: - printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", - kp->type); return -EINVAL; } }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 9685347aa0a5c2869058ca6ab79fd8e93084a67f upstream.
The aloop runtime object and its assignment in the cable are left even when opening a substream fails. This doesn't mean any memory leak, but it still keeps the invalid pointer that may be referred by the another side of the cable spontaneously, which is a potential Oops cause.
Clean up the cable assignment and the empty cable upon the error path properly.
Fixes: 597603d615d2 ("ALSA: introduce the snd-aloop module for the PCM loopback") Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/drivers/aloop.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-)
--- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -648,12 +648,31 @@ static int rule_channels(struct snd_pcm_ return snd_interval_refine(hw_param_interval(params, rule->var), &t); }
+static void free_cable(struct snd_pcm_substream *substream) +{ + struct loopback *loopback = substream->private_data; + int dev = get_cable_index(substream); + struct loopback_cable *cable; + + cable = loopback->cables[substream->number][dev]; + if (!cable) + return; + if (cable->streams[!substream->stream]) { + /* other stream is still alive */ + cable->streams[substream->stream] = NULL; + } else { + /* free the cable */ + loopback->cables[substream->number][dev] = NULL; + kfree(cable); + } +} + static int loopback_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct loopback *loopback = substream->private_data; struct loopback_pcm *dpcm; - struct loopback_cable *cable; + struct loopback_cable *cable = NULL; int err = 0; int dev = get_cable_index(substream);
@@ -673,7 +692,6 @@ static int loopback_open(struct snd_pcm_ if (!cable) { cable = kzalloc(sizeof(*cable), GFP_KERNEL); if (!cable) { - kfree(dpcm); err = -ENOMEM; goto unlock; } @@ -715,6 +733,10 @@ static int loopback_open(struct snd_pcm_ else runtime->hw = cable->hw; unlock: + if (err < 0) { + free_cable(substream); + kfree(dpcm); + } mutex_unlock(&loopback->cable_lock); return err; } @@ -723,20 +745,10 @@ static int loopback_close(struct snd_pcm { struct loopback *loopback = substream->private_data; struct loopback_pcm *dpcm = substream->runtime->private_data; - struct loopback_cable *cable; - int dev = get_cable_index(substream);
loopback_timer_stop(dpcm); mutex_lock(&loopback->cable_lock); - cable = loopback->cables[substream->number][dev]; - if (cable->streams[!substream->stream]) { - /* other stream is still alive */ - cable->streams[substream->stream] = NULL; - } else { - /* free the cable */ - loopback->cables[substream->number][dev] = NULL; - kfree(cable); - } + free_cable(substream); mutex_unlock(&loopback->cable_lock); return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Andrew Honig ahonig@google.com
commit 75f139aaf896d6fdeec2e468ddfa4b2fe469bf40 upstream.
This adds a memory barrier when performing a lookup into the vmcs_field_to_offset_table. This is related to CVE-2017-5753.
Signed-off-by: Andrew Honig ahonig@google.com Reviewed-by: Jim Mattson jmattson@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -573,8 +573,18 @@ static const int max_vmcs_field = ARRAY_
static inline short vmcs_field_to_offset(unsigned long field) { - if (field >= max_vmcs_field || vmcs_field_to_offset_table[field] == 0) + if (field >= max_vmcs_field) return -1; + + /* + * FIXME: Mitigation for CVE-2017-5753. To be replaced with a + * generic mechanism. + */ + asm("lfence"); + + if (vmcs_field_to_offset_table[field] == 0) + return -1; + return vmcs_field_to_offset_table[field]; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Sergei Shtylyov sergei.shtylyov@cogentembedded.com
commit 195e2addbce09e5afbc766efc1e6567c9ce840d3 upstream.
The 'sh_eth' driver's probe() method would fail on the SolutionEngine7710 board and crash on SolutionEngine7712 board as the platform code is hopelessly behind the driver's platform data -- it passes the PHY address instead of 'struct sh_eth_plat_data *'; pass the latter to the driver in order to fix the bug...
Fixes: 71557a37adb5 ("[netdrvr] sh_eth: Add SH7619 support") Signed-off-by: Sergei Shtylyov sergei.shtylyov@cogentembedded.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/sh/boards/mach-se/770x/setup.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
--- a/arch/sh/boards/mach-se/770x/setup.c +++ b/arch/sh/boards/mach-se/770x/setup.c @@ -8,6 +8,7 @@ */ #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/sh_eth.h> #include <mach-se/mach/se.h> #include <mach-se/mach/mrshpc.h> #include <asm/machvec.h> @@ -114,6 +115,11 @@ static struct platform_device heartbeat_ #if defined(CONFIG_CPU_SUBTYPE_SH7710) ||\ defined(CONFIG_CPU_SUBTYPE_SH7712) /* SH771X Ethernet driver */ +static struct sh_eth_plat_data sh_eth_plat = { + .phy = PHY_ID, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + static struct resource sh_eth0_resources[] = { [0] = { .start = SH_ETH0_BASE, @@ -131,7 +137,7 @@ static struct platform_device sh_eth0_de .name = "sh-eth", .id = 0, .dev = { - .platform_data = PHY_ID, + .platform_data = &sh_eth_plat, }, .num_resources = ARRAY_SIZE(sh_eth0_resources), .resource = sh_eth0_resources, @@ -154,7 +160,7 @@ static struct platform_device sh_eth1_de .name = "sh-eth", .id = 1, .dev = { - .platform_data = PHY_ID, + .platform_data = &sh_eth_plat, }, .num_resources = ARRAY_SIZE(sh_eth1_resources), .resource = sh_eth1_resources,
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Tiffany Lin tiffany.lin@mediatek.com
commit baf43c6eace43868e490f18560287fa3481b2159 upstream.
In v4l2-compliance utility, test VIDIOC_CREATE_BUFS will check whether reserved filed of v4l2_create_buffers filled with zero Reserved field is filled with zero in v4l_create_bufs. This patch copy reserved field of v4l2_create_buffer from kernel space to user space
Signed-off-by: Tiffany Lin tiffany.lin@mediatek.com Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Signed-off-by: Mauro Carvalho Chehab mchehab@osg.samsung.com [bwh: Backported to 3.2: adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -267,7 +267,8 @@ static int put_v4l2_format32(struct v4l2 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || - copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format))) + copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) || + copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) return -EFAULT; return __put_v4l2_format32(&kp->format, &up->format); }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Pete Zaitcev zaitcev@redhat.com
commit 46eb14a6e1585d99c1b9f58d0e7389082a5f466b upstream.
Automated tests triggered this by opening usbmon and accessing the mmap while simultaneously resizing the buffers. This bug was with us since 2006, because typically applications only size the buffers once and thus avoid racing. Reported by Kirill A. Shutemov.
Reported-by: syzbot+f9831b881b3e849829fc@syzkaller.appspotmail.com Signed-off-by: Pete Zaitcev zaitcev@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/mon/mon_bin.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1000,7 +1000,9 @@ static long mon_bin_ioctl(struct file *f break;
case MON_IOCQ_RING_SIZE: + mutex_lock(&rp->fetch_lock); ret = rp->b_size; + mutex_unlock(&rp->fetch_lock); break;
case MON_IOCT_RING_SIZE: @@ -1227,12 +1229,16 @@ static int mon_bin_vma_fault(struct vm_a unsigned long offset, chunk_idx; struct page *pageptr;
+ mutex_lock(&rp->fetch_lock); offset = vmf->pgoff << PAGE_SHIFT; - if (offset >= rp->b_size) + if (offset >= rp->b_size) { + mutex_unlock(&rp->fetch_lock); return VM_FAULT_SIGBUS; + } chunk_idx = offset / CHUNK_SIZE; pageptr = rp->b_vec[chunk_idx].pg; get_page(pageptr); + mutex_unlock(&rp->fetch_lock); vmf->page = pageptr; return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit 8ae632b11775254c5e555ee8c42b7d19baeb1473 upstream.
A lot of these warnings are caused by the fact that we don't generally use __user in videodev2.h. Normally the video_usercopy function will copy anything pointed to by pointers into kernel space, so having __user in the struct will only cause lots of warnings in the drivers. But the flip side of that is that you need to add __force casts here.
drivers/media/v4l2-core/v4l2-compat-ioctl32.c:337:26: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:337:30: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:338:31: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:338:49: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:343:21: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:346:21: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:349:35: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:349:46: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:352:35: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:352:54: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:363:26: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:363:32: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:364:31: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:364:51: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:371:35: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:371:56: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:376:35: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:376:48: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:430:30: warning: incorrect type in assignment (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:433:48: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:433:56: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:501:24: warning: incorrect type in assignment (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:507:48: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:507:56: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:565:18: warning: incorrect type in assignment (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:670:22: warning: incorrect type in assignment (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:680:29: warning: incorrect type in assignment (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:692:55: warning: incorrect type in initializer (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:773:18: warning: incorrect type in assignment (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:786:30: warning: incorrect type in argument 1 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:786:44: warning: incorrect type in argument 2 (different address spaces) drivers/media/v4l2-core/v4l2-compat-ioctl32.c:674:37: warning: dereference of noderef expression drivers/media/v4l2-core/v4l2-compat-ioctl32.c:718:37: warning: dereference of noderef expression
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Signed-off-by: Mauro Carvalho Chehab m.chehab@samsung.com [bwh: Backported to 3.2: - Drop changes in {get,put}_v4l2_edid32() - Adjust filename, context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -334,7 +334,7 @@ struct v4l2_buffer32 { __u32 reserved; };
-static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, +static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, enum v4l2_memory memory) { void __user *up_pln; @@ -360,7 +360,7 @@ static int get_v4l2_plane32(struct v4l2_ return 0; }
-static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, +static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, enum v4l2_memory memory) { if (copy_in_user(up32, up, 2 * sizeof(__u32)) || @@ -426,7 +426,7 @@ static int get_v4l2_buffer32(struct v4l2 * by passing a very big num_planes value */ uplane = compat_alloc_user_space(num_planes * sizeof(struct v4l2_plane)); - kp->m.planes = uplane; + kp->m.planes = (__force struct v4l2_plane *)uplane;
while (--num_planes >= 0) { ret = get_v4l2_plane32(uplane, uplane32, kp->memory); @@ -493,7 +493,7 @@ static int put_v4l2_buffer32(struct v4l2 if (num_planes == 0) return 0;
- uplane = kp->m.planes; + uplane = (__force struct v4l2_plane __user *)kp->m.planes; if (get_user(p, &up->m.planes)) return -EFAULT; uplane32 = compat_ptr(p); @@ -543,7 +543,7 @@ static int get_v4l2_framebuffer32(struct get_user(kp->capability, &up->capability) || get_user(kp->flags, &up->flags)) return -EFAULT; - kp->base = compat_ptr(tmp); + kp->base = (__force void *)compat_ptr(tmp); get_v4l2_pix_format(&kp->fmt, &up->fmt); return 0; } @@ -649,11 +649,15 @@ static int get_v4l2_ext_controls32(struc n * sizeof(struct v4l2_ext_control32))) return -EFAULT; kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); - kp->controls = kcontrols; + kp->controls = (__force struct v4l2_ext_control *)kcontrols; while (--n >= 0) { + u32 id; + if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols))) return -EFAULT; - if (ctrl_is_pointer(kcontrols->id)) { + if (get_user(id, &kcontrols->id)) + return -EFAULT; + if (ctrl_is_pointer(id)) { void __user *s;
if (get_user(p, &ucontrols->string)) @@ -671,7 +675,8 @@ static int get_v4l2_ext_controls32(struc static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) { struct v4l2_ext_control32 __user *ucontrols; - struct v4l2_ext_control __user *kcontrols = kp->controls; + struct v4l2_ext_control __user *kcontrols = + (__force struct v4l2_ext_control __user *)kp->controls; int n = kp->count; compat_caddr_t p;
@@ -693,11 +698,14 @@ static int put_v4l2_ext_controls32(struc
while (--n >= 0) { unsigned size = sizeof(*ucontrols); + u32 id;
+ if (get_user(id, &kcontrols->id)) + return -EFAULT; /* Do not modify the pointer when copying a pointer control. The contents of the pointer was changed, not the pointer itself. */ - if (ctrl_is_pointer(kcontrols->id)) + if (ctrl_is_pointer(id)) size -= sizeof(ucontrols->value64); if (copy_in_user(ucontrols, kcontrols, size)) return -EFAULT;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Mentz danielmentz@google.com
commit a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a upstream.
The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit equivalent. It converts 32-bit data structures into its 64-bit equivalents and needs to provide the data to the 64-bit ioctl in user space memory which is commonly allocated using compat_alloc_user_space().
However, due to how that function is implemented, it can only be called a single time for every syscall invocation.
Supposedly to avoid this limitation, the existing code uses a mix of memory from the kernel stack and memory allocated through compat_alloc_user_space().
Under normal circumstances, this would not work, because the 64-bit ioctl expects all pointers to point to user space memory. As a workaround, set_fs(KERNEL_DS) is called to temporarily disable this extra safety check and allow kernel pointers. However, this might introduce a security vulnerability: The result of the 32-bit to 64-bit conversion is writeable by user space because the output buffer has been allocated via compat_alloc_user_space(). A malicious user space process could then manipulate pointers inside this output buffer, and due to the previous set_fs(KERNEL_DS) call, functions like get_user() or put_user() no longer prevent kernel memory access.
The new approach is to pre-calculate the total amount of user space memory that is needed, allocate it using compat_alloc_user_space() and then divide up the allocated memory to accommodate all data structures that need to be converted.
An alternative approach would have been to retain the union type karg that they allocated on the kernel stack in do_video_ioctl(), copy all data from user space into karg and then back to user space. However, we decided against this approach because it does not align with other compat syscall implementations. Instead, we tried to replicate the get_user/put_user pairs as found in other places in the kernel:
if (get_user(clipcount, &up->clipcount) || put_user(clipcount, &kp->clipcount)) return -EFAULT;
Notes from hans.verkuil@cisco.com:
This patch was taken from: https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953...
Clearly nobody could be bothered to upstream this patch or at minimum tell us :-( We only heard about this a week ago.
This patch was rebased and cleaned up. Compared to the original I also swapped the order of the convert_in_user arguments so that they matched copy_in_user. It was hard to review otherwise. I also replaced the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
Fixes: 6b5a9492ca ("v4l: introduce string control support.")
Signed-off-by: Daniel Mentz danielmentz@google.com Co-developed-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com [bwh: Rebased on top of some earlier fixes] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -13,12 +13,13 @@ omap2cam-objs := omap24xxcam.o omap24xxc videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
+ifeq ($(CONFIG_COMPAT),y) + videodev-objs += v4l2-compat-ioctl32.o +endif + # V4L2 core modules
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o -ifeq ($(CONFIG_COMPAT),y) - obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o -endif
obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -23,6 +23,14 @@
#ifdef CONFIG_COMPAT
+/* Use the same argument order as copy_in_user */ +#define assign_in_user(to, from) \ +({ \ + typeof(*from) __assign_tmp; \ + \ + get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \ +}) + static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = -ENOIOCTLCMD; @@ -36,12 +44,12 @@ static long native_ioctl(struct file *fi
struct v4l2_clip32 { struct v4l2_rect c; - compat_caddr_t next; + compat_caddr_t next; };
struct v4l2_window32 { struct v4l2_rect w; - enum v4l2_field field; + __u32 field; /* enum v4l2_field */ __u32 chromakey; compat_caddr_t clips; /* actually struct v4l2_clip32 * */ __u32 clipcount; @@ -49,37 +57,41 @@ struct v4l2_window32 { __u8 global_alpha; };
-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +static int get_v4l2_window32(struct v4l2_window __user *kp, + struct v4l2_window32 __user *up, + void __user *aux_buf, u32 aux_space) { struct v4l2_clip32 __user *uclips; struct v4l2_clip __user *kclips; compat_caddr_t p; - u32 n; + u32 clipcount;
if (!access_ok(VERIFY_READ, up, sizeof(*up)) || - copy_from_user(&kp->w, &up->w, sizeof(up->w)) || - get_user(kp->field, &up->field) || - get_user(kp->chromakey, &up->chromakey) || - get_user(kp->clipcount, &up->clipcount) || - get_user(kp->global_alpha, &up->global_alpha)) + copy_in_user(&kp->w, &up->w, sizeof(up->w)) || + assign_in_user(&kp->field, &up->field) || + assign_in_user(&kp->chromakey, &up->chromakey) || + assign_in_user(&kp->global_alpha, &up->global_alpha) || + get_user(clipcount, &up->clipcount) || + put_user(clipcount, &kp->clipcount)) return -EFAULT; - if (kp->clipcount > 2048) + if (clipcount > 2048) return -EINVAL; - if (!kp->clipcount) { - kp->clips = NULL; - return 0; - } + if (!clipcount) + return put_user(NULL, &kp->clips);
- n = kp->clipcount; if (get_user(p, &up->clips)) return -EFAULT; uclips = compat_ptr(p); - kclips = compat_alloc_user_space(n * sizeof(*kclips)); - kp->clips = kclips; - while (n--) { + if (aux_space < clipcount * sizeof(*kclips)) + return -EFAULT; + kclips = aux_buf; + if (put_user(kclips, &kp->clips)) + return -EFAULT; + + while (clipcount--) { if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) return -EFAULT; - if (put_user(n ? kclips + 1 : NULL, &kclips->next)) + if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next)) return -EFAULT; uclips++; kclips++; @@ -87,27 +99,28 @@ static int get_v4l2_window32(struct v4l2 return 0; }
-static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +static int put_v4l2_window32(struct v4l2_window __user *kp, + struct v4l2_window32 __user *up) { struct v4l2_clip __user *kclips = kp->clips; struct v4l2_clip32 __user *uclips; - u32 n = kp->clipcount; compat_caddr_t p; + u32 clipcount;
- if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || - put_user(kp->field, &up->field) || - put_user(kp->chromakey, &up->chromakey) || - put_user(kp->clipcount, &up->clipcount) || - put_user(kp->global_alpha, &up->global_alpha)) + if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) || + assign_in_user(&up->field, &kp->field) || + assign_in_user(&up->chromakey, &kp->chromakey) || + assign_in_user(&up->global_alpha, &kp->global_alpha) || + get_user(clipcount, &kp->clipcount) || + put_user(clipcount, &up->clipcount)) return -EFAULT; - - if (!kp->clipcount) + if (!clipcount) return 0;
if (get_user(p, &up->clips)) return -EFAULT; uclips = compat_ptr(p); - while (n--) { + while (clipcount--) { if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c))) return -EFAULT; uclips++; @@ -145,101 +158,150 @@ struct v4l2_create_buffers32 { __u32 reserved[8]; };
-static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) +static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size) { - if (get_user(kp->type, &up->type)) + u32 type; + + if (get_user(type, &up->type)) return -EFAULT;
- switch (kp->type) { + switch (type) { + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: { + u32 clipcount; + + if (get_user(clipcount, &up->fmt.win.clipcount)) + return -EFAULT; + if (clipcount > 2048) + return -EINVAL; + *size = clipcount * sizeof(struct v4l2_clip); + return 0; + } + default: + *size = 0; + return 0; + } +} + +static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size) +{ + if (!access_ok(VERIFY_READ, up, sizeof(*up))) + return -EFAULT; + return __bufsize_v4l2_format(up, size); +} + +static int __get_v4l2_format32(struct v4l2_format __user *kp, + struct v4l2_format32 __user *up, + void __user *aux_buf, u32 aux_space) +{ + u32 type; + + if (get_user(type, &up->type) || put_user(type, &kp->type)) + return -EFAULT; + + switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return copy_from_user(&kp->fmt.pix, &up->fmt.pix, - sizeof(kp->fmt.pix)) ? -EFAULT : 0; + return copy_in_user(&kp->fmt.pix, &up->fmt.pix, + sizeof(kp->fmt.pix)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return copy_from_user(&kp->fmt.pix_mp, &up->fmt.pix_mp, - sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; + return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp, + sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); + return get_v4l2_window32(&kp->fmt.win, &up->fmt.win, + aux_buf, aux_space); case V4L2_BUF_TYPE_VBI_CAPTURE: case V4L2_BUF_TYPE_VBI_OUTPUT: - return copy_from_user(&kp->fmt.vbi, &up->fmt.vbi, - sizeof(kp->fmt.vbi)) ? -EFAULT : 0; + return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi, + sizeof(kp->fmt.vbi)) ? -EFAULT : 0; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - return copy_from_user(&kp->fmt.sliced, &up->fmt.sliced, - sizeof(kp->fmt.sliced)) ? -EFAULT : 0; - case V4L2_BUF_TYPE_PRIVATE: - if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data))) - return -EFAULT; - return 0; + return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced, + sizeof(kp->fmt.sliced)) ? -EFAULT : 0; default: return -EINVAL; } }
-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) +static int get_v4l2_format32(struct v4l2_format __user *kp, + struct v4l2_format32 __user *up, + void __user *aux_buf, u32 aux_space) { if (!access_ok(VERIFY_READ, up, sizeof(*up))) return -EFAULT; - return __get_v4l2_format32(kp, up); + return __get_v4l2_format32(kp, up, aux_buf, aux_space); }
-static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) +static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up, + u32 *size) +{ + if (!access_ok(VERIFY_READ, up, sizeof(*up))) + return -EFAULT; + return __bufsize_v4l2_format(&up->format, size); +} + +static int get_v4l2_create32(struct v4l2_create_buffers __user *kp, + struct v4l2_create_buffers32 __user *up, + void __user *aux_buf, u32 aux_space) { if (!access_ok(VERIFY_READ, up, sizeof(*up)) || - copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format))) + copy_in_user(kp, up, + offsetof(struct v4l2_create_buffers32, format))) return -EFAULT; - return __get_v4l2_format32(&kp->format, &up->format); + return __get_v4l2_format32(&kp->format, &up->format, + aux_buf, aux_space); }
-static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) +static int __put_v4l2_format32(struct v4l2_format __user *kp, + struct v4l2_format32 __user *up) { - if (put_user(kp->type, &up->type)) + u32 type; + + if (get_user(type, &kp->type)) return -EFAULT;
- switch (kp->type) { + switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return copy_to_user(&up->fmt.pix, &kp->fmt.pix, + return copy_in_user(&up->fmt.pix, &kp->fmt.pix, sizeof(kp->fmt.pix)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return copy_to_user(&up->fmt.pix_mp, &kp->fmt.pix_mp, + return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp, sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); case V4L2_BUF_TYPE_VBI_CAPTURE: case V4L2_BUF_TYPE_VBI_OUTPUT: - return copy_to_user(&up->fmt.vbi, &kp->fmt.vbi, + return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi, sizeof(kp->fmt.vbi)) ? -EFAULT : 0; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - return copy_to_user(&up->fmt.sliced, &kp->fmt.sliced, + return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced, sizeof(kp->fmt.sliced)) ? -EFAULT : 0; - case V4L2_BUF_TYPE_PRIVATE: - if (copy_to_user(up, kp, sizeof(up->fmt.raw_data))) - return -EFAULT; - return 0; default: return -EINVAL; } }
-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) +static int put_v4l2_format32(struct v4l2_format __user *kp, + struct v4l2_format32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) return -EFAULT; return __put_v4l2_format32(kp, up); }
-static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) +static int put_v4l2_create32(struct v4l2_create_buffers __user *kp, + struct v4l2_create_buffers32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) || - copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) + copy_in_user(up, kp, + offsetof(struct v4l2_create_buffers32, format)) || + copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved))) return -EFAULT; return __put_v4l2_format32(&kp->format, &up->format); } @@ -253,24 +315,27 @@ struct v4l2_standard32 { __u32 reserved[4]; };
-static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) +static int get_v4l2_standard32(struct v4l2_standard __user *kp, + struct v4l2_standard32 __user *up) { /* other fields are not set by the user, nor used by the driver */ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || - get_user(kp->index, &up->index)) + assign_in_user(&kp->index, &up->index)) return -EFAULT; return 0; }
-static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) +static int put_v4l2_standard32(struct v4l2_standard __user *kp, + struct v4l2_standard32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - put_user(kp->index, &up->index) || - put_user(kp->id, &up->id) || - copy_to_user(up->name, kp->name, sizeof(up->name)) || - copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || - put_user(kp->framelines, &up->framelines) || - copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) + assign_in_user(&up->index, &kp->index) || + assign_in_user(&up->id, &kp->id) || + copy_in_user(up->name, kp->name, sizeof(up->name)) || + copy_in_user(&up->frameperiod, &kp->frameperiod, + sizeof(up->frameperiod)) || + assign_in_user(&up->framelines, &kp->framelines) || + copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved))) return -EFAULT; return 0; } @@ -308,11 +373,11 @@ struct v4l2_buffer32 { __u32 reserved; };
-static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, +static int get_v4l2_plane32(struct v4l2_plane __user *up, + struct v4l2_plane32 __user *up32, enum v4l2_memory memory) { - void __user *up_pln; - compat_long_t p; + compat_ulong_t p;
if (copy_in_user(up, up32, 2 * sizeof(__u32)) || copy_in_user(&up->data_offset, &up32->data_offset, @@ -327,10 +392,8 @@ static int get_v4l2_plane32(struct v4l2_ return -EFAULT; break; case V4L2_MEMORY_USERPTR: - if (get_user(p, &up32->m.userptr)) - return -EFAULT; - up_pln = compat_ptr(p); - if (put_user((unsigned long)up_pln, &up->m.userptr)) + if (get_user(p, &up32->m.userptr) || + put_user((unsigned long)compat_ptr(p), &up->m.userptr)) return -EFAULT; break; } @@ -338,7 +401,8 @@ static int get_v4l2_plane32(struct v4l2_ return 0; }
-static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, +static int put_v4l2_plane32(struct v4l2_plane __user *up, + struct v4l2_plane32 __user *up32, enum v4l2_memory memory) { unsigned long p; @@ -366,40 +430,75 @@ static int put_v4l2_plane32(struct v4l2_ return 0; }
-static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) +static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size) { + u32 type; + u32 length; + + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || + get_user(type, &up->type) || + get_user(length, &up->length)) + return -EFAULT; + + if (V4L2_TYPE_IS_MULTIPLANAR(type)) { + if (length > VIDEO_MAX_PLANES) + return -EINVAL; + + /* + * We don't really care if userspace decides to kill itself + * by passing a very big length value + */ + *size = length * sizeof(struct v4l2_plane); + } else { + *size = 0; + } + return 0; +} + +static int get_v4l2_buffer32(struct v4l2_buffer __user *kp, + struct v4l2_buffer32 __user *up, + void __user *aux_buf, u32 aux_space) +{ + u32 type; + u32 length; + enum v4l2_memory memory; struct v4l2_plane32 __user *uplane32; struct v4l2_plane __user *uplane; compat_caddr_t p; - int num_planes; int ret;
if (!access_ok(VERIFY_READ, up, sizeof(*up)) || - get_user(kp->index, &up->index) || - get_user(kp->type, &up->type) || - get_user(kp->flags, &up->flags) || - get_user(kp->memory, &up->memory) || - get_user(kp->input, &up->input)) - return -EFAULT; - - if (V4L2_TYPE_IS_OUTPUT(kp->type)) - if (get_user(kp->bytesused, &up->bytesused) || - get_user(kp->field, &up->field) || - get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || - get_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec)) + assign_in_user(&kp->index, &up->index) || + get_user(type, &up->type) || + put_user(type, &kp->type) || + assign_in_user(&kp->flags, &up->flags) || + get_user(memory, &up->memory) || + put_user(memory, &kp->memory) || + get_user(length, &up->length) || + put_user(length, &kp->length)) + return -EFAULT; + + if (V4L2_TYPE_IS_OUTPUT(type)) + if (assign_in_user(&kp->bytesused, &up->bytesused) || + assign_in_user(&kp->field, &up->field) || + assign_in_user(&kp->timestamp.tv_sec, + &up->timestamp.tv_sec) || + assign_in_user(&kp->timestamp.tv_usec, + &up->timestamp.tv_usec)) return -EFAULT;
- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { - if (get_user(kp->length, &up->length)) - return -EFAULT; + if (V4L2_TYPE_IS_MULTIPLANAR(type)) { + u32 num_planes = length;
- num_planes = kp->length; if (num_planes == 0) { - kp->m.planes = NULL; - /* num_planes == 0 is legal, e.g. when userspace doesn't - * need planes array on DQBUF*/ - return 0; + /* + * num_planes == 0 is legal, e.g. when userspace doesn't + * need planes array on DQBUF + */ + return put_user(NULL, &kp->m.planes); } + if (num_planes > VIDEO_MAX_PLANES) + return -EINVAL;
if (get_user(p, &up->m.planes)) return -EFAULT; @@ -409,103 +508,107 @@ static int get_v4l2_buffer32(struct v4l2 num_planes * sizeof(*uplane32))) return -EFAULT;
- /* We don't really care if userspace decides to kill itself - * by passing a very big num_planes value */ - uplane = compat_alloc_user_space(num_planes * - sizeof(*uplane)); - kp->m.planes = (__force struct v4l2_plane *)uplane; + /* + * We don't really care if userspace decides to kill itself + * by passing a very big num_planes value + */ + if (aux_space < num_planes * sizeof(*uplane)) + return -EFAULT; + + uplane = aux_buf; + if (put_user((__force struct v4l2_plane *)uplane, + &kp->m.planes)) + return -EFAULT;
- while (--num_planes >= 0) { - ret = get_v4l2_plane32(uplane, uplane32, kp->memory); + while (num_planes--) { + ret = get_v4l2_plane32(uplane, uplane32, memory); if (ret) return ret; - ++uplane; - ++uplane32; + uplane++; + uplane32++; } } else { - switch (kp->memory) { + switch (memory) { case V4L2_MEMORY_MMAP: - if (get_user(kp->length, &up->length) || - get_user(kp->m.offset, &up->m.offset)) + case V4L2_MEMORY_OVERLAY: + if (assign_in_user(&kp->m.offset, &up->m.offset)) return -EFAULT; break; - case V4L2_MEMORY_USERPTR: - { - compat_long_t tmp; - - if (get_user(kp->length, &up->length) || - get_user(tmp, &up->m.userptr)) - return -EFAULT; + case V4L2_MEMORY_USERPTR: { + compat_ulong_t userptr;
- kp->m.userptr = (unsigned long)compat_ptr(tmp); - } - break; - case V4L2_MEMORY_OVERLAY: - if (get_user(kp->m.offset, &up->m.offset)) + if (get_user(userptr, &up->m.userptr) || + put_user((unsigned long)compat_ptr(userptr), + &kp->m.userptr)) return -EFAULT; break; } + } }
return 0; }
-static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) +static int put_v4l2_buffer32(struct v4l2_buffer __user *kp, + struct v4l2_buffer32 __user *up) { + u32 type; + u32 length; + enum v4l2_memory memory; struct v4l2_plane32 __user *uplane32; struct v4l2_plane __user *uplane; compat_caddr_t p; - int num_planes; int ret;
if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - put_user(kp->index, &up->index) || - put_user(kp->type, &up->type) || - put_user(kp->flags, &up->flags) || - put_user(kp->memory, &up->memory) || - put_user(kp->input, &up->input)) - return -EFAULT; - - if (put_user(kp->bytesused, &up->bytesused) || - put_user(kp->field, &up->field) || - put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || - put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || - copy_to_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) || - put_user(kp->sequence, &up->sequence) || - put_user(kp->reserved, &up->reserved)) + assign_in_user(&up->index, &kp->index) || + get_user(type, &kp->type) || + put_user(type, &up->type) || + assign_in_user(&up->flags, &kp->flags) || + get_user(memory, &kp->memory) || + put_user(memory, &up->memory)) + return -EFAULT; + + if (assign_in_user(&up->bytesused, &kp->bytesused) || + assign_in_user(&up->field, &kp->field) || + assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) || + assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) || + copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) || + assign_in_user(&up->sequence, &kp->sequence) || + assign_in_user(&up->input, &kp->input) || + assign_in_user(&up->reserved, &kp->reserved) || + get_user(length, &kp->length) || + put_user(length, &up->length)) return -EFAULT;
- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { - num_planes = kp->length; + if (V4L2_TYPE_IS_MULTIPLANAR(type)) { + u32 num_planes = length; + if (num_planes == 0) return 0;
- uplane = (__force struct v4l2_plane __user *)kp->m.planes; + if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes))) + return -EFAULT; if (get_user(p, &up->m.planes)) return -EFAULT; uplane32 = compat_ptr(p);
- while (--num_planes >= 0) { - ret = put_v4l2_plane32(uplane, uplane32, kp->memory); + while (num_planes--) { + ret = put_v4l2_plane32(uplane, uplane32, memory); if (ret) return ret; ++uplane; ++uplane32; } } else { - switch (kp->memory) { + switch (memory) { case V4L2_MEMORY_MMAP: - if (put_user(kp->length, &up->length) || - put_user(kp->m.offset, &up->m.offset)) + case V4L2_MEMORY_OVERLAY: + if (assign_in_user(&up->m.offset, &kp->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: - if (put_user(kp->length, &up->length) || - put_user(kp->m.userptr, &up->m.userptr)) - return -EFAULT; - break; - case V4L2_MEMORY_OVERLAY: - if (put_user(kp->m.offset, &up->m.offset)) + if (assign_in_user(&up->m.userptr, &kp->m.userptr)) return -EFAULT; break; } @@ -517,33 +620,45 @@ static int put_v4l2_buffer32(struct v4l2 struct v4l2_framebuffer32 { __u32 capability; __u32 flags; - compat_caddr_t base; - struct v4l2_pix_format fmt; + compat_caddr_t base; + struct { + __u32 width; + __u32 height; + __u32 pixelformat; + __u32 field; + __u32 bytesperline; + __u32 sizeimage; + __u32 colorspace; + __u32 priv; + } fmt; };
-static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) +static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp, + struct v4l2_framebuffer32 __user *up) { - u32 tmp; + compat_caddr_t tmp;
if (!access_ok(VERIFY_READ, up, sizeof(*up)) || get_user(tmp, &up->base) || - get_user(kp->capability, &up->capability) || - get_user(kp->flags, &up->flags) || - copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt))) + put_user((__force void *)compat_ptr(tmp), &kp->base) || + assign_in_user(&kp->capability, &up->capability) || + assign_in_user(&kp->flags, &up->flags) || + copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt))) return -EFAULT; - kp->base = (__force void *)compat_ptr(tmp); return 0; }
-static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) +static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp, + struct v4l2_framebuffer32 __user *up) { - u32 tmp = (u32)((unsigned long)kp->base); + void *base;
if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - put_user(tmp, &up->base) || - put_user(kp->capability, &up->capability) || - put_user(kp->flags, &up->flags) || - copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt))) + get_user(base, &kp->base) || + put_user(ptr_to_compat(base), &up->base) || + assign_in_user(&up->capability, &kp->capability) || + assign_in_user(&up->flags, &kp->flags) || + copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt))) return -EFAULT; return 0; } @@ -560,18 +675,22 @@ struct v4l2_input32 { __u32 reserved[3]; };
-/* The 64-bit v4l2_input struct has extra padding at the end of the struct. - Otherwise it is identical to the 32-bit version. */ -static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) +/* + * The 64-bit v4l2_input struct has extra padding at the end of the struct. + * Otherwise it is identical to the 32-bit version. + */ +static inline int get_v4l2_input32(struct v4l2_input __user *kp, + struct v4l2_input32 __user *up) { - if (copy_from_user(kp, up, sizeof(*up))) + if (copy_in_user(kp, up, sizeof(*up))) return -EFAULT; return 0; }
-static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) +static inline int put_v4l2_input32(struct v4l2_input __user *kp, + struct v4l2_input32 __user *up) { - if (copy_to_user(up, kp, sizeof(*up))) + if (copy_in_user(up, kp, sizeof(*up))) return -EFAULT; return 0; } @@ -618,40 +737,64 @@ static inline bool ctrl_is_pointer(struc return false; }
+static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up, + u32 *size) +{ + u32 count; + + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || + get_user(count, &up->count)) + return -EFAULT; + if (count > V4L2_CID_MAX_CTRLS) + return -EINVAL; + *size = count * sizeof(struct v4l2_ext_control); + return 0; +} + static int get_v4l2_ext_controls32(struct file *file, - struct v4l2_ext_controls *kp, - struct v4l2_ext_controls32 __user *up) + struct v4l2_ext_controls __user *kp, + struct v4l2_ext_controls32 __user *up, + void __user *aux_buf, u32 aux_space) { struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols; - int n; + u32 count; + u32 n; compat_caddr_t p;
if (!access_ok(VERIFY_READ, up, sizeof(*up)) || - get_user(kp->ctrl_class, &up->ctrl_class) || - get_user(kp->count, &up->count) || - get_user(kp->error_idx, &up->error_idx) || - copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) - return -EFAULT; - n = kp->count; - if (n == 0) { - kp->controls = NULL; - return 0; - } + assign_in_user(&kp->ctrl_class, &up->ctrl_class) || + get_user(count, &up->count) || + put_user(count, &kp->count) || + assign_in_user(&kp->error_idx, &up->error_idx) || + copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved))) + return -EFAULT; + + if (count == 0) + return put_user(NULL, &kp->controls); + if (count > V4L2_CID_MAX_CTRLS) + return -EINVAL; if (get_user(p, &up->controls)) return -EFAULT; ucontrols = compat_ptr(p); - if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(*ucontrols))) + if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols))) + return -EFAULT; + if (aux_space < count * sizeof(*kcontrols)) + return -EFAULT; + kcontrols = aux_buf; + if (put_user((__force struct v4l2_ext_control *)kcontrols, + &kp->controls)) return -EFAULT; - kcontrols = compat_alloc_user_space(n * sizeof(*kcontrols)); - kp->controls = (__force struct v4l2_ext_control *)kcontrols; - while (--n >= 0) { + + for (n = 0; n < count; n++) { u32 id;
if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols))) return -EFAULT; + if (get_user(id, &kcontrols->id)) return -EFAULT; + if (ctrl_is_pointer(file, id)) { void __user *s;
@@ -668,43 +811,54 @@ static int get_v4l2_ext_controls32(struc }
static int put_v4l2_ext_controls32(struct file *file, - struct v4l2_ext_controls *kp, + struct v4l2_ext_controls __user *kp, struct v4l2_ext_controls32 __user *up) { struct v4l2_ext_control32 __user *ucontrols; - struct v4l2_ext_control __user *kcontrols = - (__force struct v4l2_ext_control __user *)kp->controls; - int n = kp->count; + struct v4l2_ext_control __user *kcontrols; + u32 count; + u32 n; compat_caddr_t p;
if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - put_user(kp->ctrl_class, &up->ctrl_class) || - put_user(kp->count, &up->count) || - put_user(kp->error_idx, &up->error_idx) || - copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) + assign_in_user(&up->ctrl_class, &kp->ctrl_class) || + get_user(count, &kp->count) || + put_user(count, &up->count) || + assign_in_user(&up->error_idx, &kp->error_idx) || + copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) || + get_user(kcontrols, &kp->controls)) return -EFAULT; - if (!kp->count) - return 0;
+ if (!count) + return 0; if (get_user(p, &up->controls)) return -EFAULT; ucontrols = compat_ptr(p); - if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(*ucontrols))) + if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols))) return -EFAULT;
- while (--n >= 0) { - unsigned size = sizeof(*ucontrols); + for (n = 0; n < count; n++) { + unsigned int size = sizeof(*ucontrols); u32 id;
- if (get_user(id, &kcontrols->id)) + if (get_user(id, &kcontrols->id) || + put_user(id, &ucontrols->id) || + assign_in_user(&ucontrols->size, &kcontrols->size) || + copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2, + sizeof(ucontrols->reserved2))) return -EFAULT; - /* Do not modify the pointer when copying a pointer control. - The contents of the pointer was changed, not the pointer - itself. */ + + /* + * Do not modify the pointer when copying a pointer control. + * The contents of the pointer was changed, not the pointer + * itself. + */ if (ctrl_is_pointer(file, id)) size -= sizeof(ucontrols->value64); + if (copy_in_user(ucontrols, kcontrols, size)) return -EFAULT; + ucontrols++; kcontrols++; } @@ -724,16 +878,18 @@ struct v4l2_event32 { __u32 reserved[8]; };
-static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up) +static int put_v4l2_event32(struct v4l2_event __user *kp, + struct v4l2_event32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - put_user(kp->type, &up->type) || - copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || - put_user(kp->pending, &up->pending) || - put_user(kp->sequence, &up->sequence) || - put_compat_timespec(&kp->timestamp, &up->timestamp) || - put_user(kp->id, &up->id) || - copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) + assign_in_user(&up->type, &kp->type) || + copy_in_user(&up->u, &kp->u, sizeof(kp->u)) || + assign_in_user(&up->pending, &kp->pending) || + assign_in_user(&up->sequence, &kp->sequence) || + assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) || + assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) || + assign_in_user(&up->id, &kp->id) || + copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved))) return -EFAULT; return 0; } @@ -747,7 +903,7 @@ static int put_v4l2_event32(struct v4l2_ #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) -#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) +#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) @@ -763,21 +919,23 @@ static int put_v4l2_event32(struct v4l2_ #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32) #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
+static int alloc_userspace(unsigned int size, u32 aux_space, + void __user **up_native) +{ + *up_native = compat_alloc_user_space(size + aux_space); + if (!*up_native) + return -ENOMEM; + if (clear_user(*up_native, size)) + return -EFAULT; + return 0; +} + static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - union { - struct v4l2_format v2f; - struct v4l2_buffer v2b; - struct v4l2_framebuffer v2fb; - struct v4l2_input v2i; - struct v4l2_standard v2s; - struct v4l2_ext_controls v2ecs; - struct v4l2_event v2ev; - struct v4l2_create_buffers v2crt; - unsigned long vx; - int vi; - } karg; void __user *up = compat_ptr(arg); + void __user *up_native = NULL; + void __user *aux_buf; + u32 aux_space; int compatible_arg = 1; long err = 0;
@@ -814,24 +972,44 @@ static long do_video_ioctl(struct file * case VIDIOC_STREAMOFF: case VIDIOC_S_INPUT: case VIDIOC_S_OUTPUT: - err = get_user(karg.vi, (s32 __user *)up); + err = alloc_userspace(sizeof(unsigned int), 0, &up_native); + if (!err && assign_in_user((unsigned int __user *)up_native, + (compat_uint_t __user *)up)) + err = -EFAULT; compatible_arg = 0; break;
case VIDIOC_G_INPUT: case VIDIOC_G_OUTPUT: + err = alloc_userspace(sizeof(unsigned int), 0, &up_native); compatible_arg = 0; break;
case VIDIOC_G_FMT: case VIDIOC_S_FMT: case VIDIOC_TRY_FMT: - err = get_v4l2_format32(&karg.v2f, up); + err = bufsize_v4l2_format(up, &aux_space); + if (!err) + err = alloc_userspace(sizeof(struct v4l2_format), + aux_space, &up_native); + if (!err) { + aux_buf = up_native + sizeof(struct v4l2_format); + err = get_v4l2_format32(up_native, up, + aux_buf, aux_space); + } compatible_arg = 0; break;
case VIDIOC_CREATE_BUFS: - err = get_v4l2_create32(&karg.v2crt, up); + err = bufsize_v4l2_create(up, &aux_space); + if (!err) + err = alloc_userspace(sizeof(struct v4l2_create_buffers), + aux_space, &up_native); + if (!err) { + aux_buf = up_native + sizeof(struct v4l2_create_buffers); + err = get_v4l2_create32(up_native, up, + aux_buf, aux_space); + } compatible_arg = 0; break;
@@ -839,36 +1017,63 @@ static long do_video_ioctl(struct file * case VIDIOC_QUERYBUF: case VIDIOC_QBUF: case VIDIOC_DQBUF: - err = get_v4l2_buffer32(&karg.v2b, up); + err = bufsize_v4l2_buffer(up, &aux_space); + if (!err) + err = alloc_userspace(sizeof(struct v4l2_buffer), + aux_space, &up_native); + if (!err) { + aux_buf = up_native + sizeof(struct v4l2_buffer); + err = get_v4l2_buffer32(up_native, up, + aux_buf, aux_space); + } compatible_arg = 0; break;
case VIDIOC_S_FBUF: - err = get_v4l2_framebuffer32(&karg.v2fb, up); + err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, + &up_native); + if (!err) + err = get_v4l2_framebuffer32(up_native, up); compatible_arg = 0; break;
case VIDIOC_G_FBUF: + err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, + &up_native); compatible_arg = 0; break;
case VIDIOC_ENUMSTD: - err = get_v4l2_standard32(&karg.v2s, up); + err = alloc_userspace(sizeof(struct v4l2_standard), 0, + &up_native); + if (!err) + err = get_v4l2_standard32(up_native, up); compatible_arg = 0; break;
case VIDIOC_ENUMINPUT: - err = get_v4l2_input32(&karg.v2i, up); + err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native); + if (!err) + err = get_v4l2_input32(up_native, up); compatible_arg = 0; break;
case VIDIOC_G_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: - err = get_v4l2_ext_controls32(file, &karg.v2ecs, up); + err = bufsize_v4l2_ext_controls(up, &aux_space); + if (!err) + err = alloc_userspace(sizeof(struct v4l2_ext_controls), + aux_space, &up_native); + if (!err) { + aux_buf = up_native + sizeof(struct v4l2_ext_controls); + err = get_v4l2_ext_controls32(file, up_native, up, + aux_buf, aux_space); + } compatible_arg = 0; break; case VIDIOC_DQEVENT: + err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native); compatible_arg = 0; break; } @@ -877,25 +1082,22 @@ static long do_video_ioctl(struct file *
if (compatible_arg) err = native_ioctl(file, cmd, (unsigned long)up); - else { - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - err = native_ioctl(file, cmd, (unsigned long)&karg); - set_fs(old_fs); - } + else + err = native_ioctl(file, cmd, (unsigned long)up_native);
if (err == -ENOTTY) return err;
- /* Special case: even after an error we need to put the - results back for these ioctls since the error_idx will - contain information on which control failed. */ + /* + * Special case: even after an error we need to put the + * results back for these ioctls since the error_idx will + * contain information on which control failed. + */ switch (cmd) { case VIDIOC_G_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: - if (put_v4l2_ext_controls32(file, &karg.v2ecs, up)) + if (put_v4l2_ext_controls32(file, up_native, up)) err = -EFAULT; break; } @@ -907,40 +1109,42 @@ static long do_video_ioctl(struct file * case VIDIOC_S_OUTPUT: case VIDIOC_G_INPUT: case VIDIOC_G_OUTPUT: - err = put_user(((s32)karg.vi), (s32 __user *)up); + if (assign_in_user((compat_uint_t __user *)up, + ((unsigned int __user *)up_native))) + err = -EFAULT; break;
case VIDIOC_G_FBUF: - err = put_v4l2_framebuffer32(&karg.v2fb, up); + err = put_v4l2_framebuffer32(up_native, up); break;
case VIDIOC_DQEVENT: - err = put_v4l2_event32(&karg.v2ev, up); + err = put_v4l2_event32(up_native, up); break;
case VIDIOC_G_FMT: case VIDIOC_S_FMT: case VIDIOC_TRY_FMT: - err = put_v4l2_format32(&karg.v2f, up); + err = put_v4l2_format32(up_native, up); break;
case VIDIOC_CREATE_BUFS: - err = put_v4l2_create32(&karg.v2crt, up); + err = put_v4l2_create32(up_native, up); break;
case VIDIOC_PREPARE_BUF: case VIDIOC_QUERYBUF: case VIDIOC_QBUF: case VIDIOC_DQBUF: - err = put_v4l2_buffer32(&karg.v2b, up); + err = put_v4l2_buffer32(up_native, up); break;
case VIDIOC_ENUMSTD: - err = put_v4l2_standard32(&karg.v2s, up); + err = put_v4l2_standard32(up_native, up); break;
case VIDIOC_ENUMINPUT: - err = put_v4l2_input32(&karg.v2i, up); + err = put_v4l2_input32(up_native, up); break; } return err;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit b8c601e8af2d08f733d74defa8465303391bb930 upstream.
ctrl_is_pointer just hardcoded two known string controls, but that caused problems when using e.g. custom controls that use a pointer for the payload.
Reimplement this function: it now finds the v4l2_ctrl (if the driver uses the control framework) or it calls vidioc_query_ext_ctrl (if the driver implements that directly).
In both cases it can now check if the control is a pointer control or not.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com [bwh: Rebased on top of some earlier fixes] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -17,6 +17,9 @@ #include <linux/videodev2.h> #include <linux/module.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-dev.h> +#include <media/v4l2-fh.h> +#include <media/v4l2-ctrls.h>
#ifdef CONFIG_COMPAT
@@ -572,24 +575,32 @@ struct v4l2_ext_control32 { }; } __attribute__ ((packed));
-/* The following function really belong in v4l2-common, but that causes - a circular dependency between modules. We need to think about this, but - for now this will do. */ - -/* Return non-zero if this control is a pointer type. Currently only - type STRING is a pointer type. */ -static inline int ctrl_is_pointer(u32 id) -{ - switch (id) { - case V4L2_CID_RDS_TX_PS_NAME: - case V4L2_CID_RDS_TX_RADIO_TEXT: - return 1; - default: - return 0; +/* Return true if this control is a pointer type. */ +static inline bool ctrl_is_pointer(struct file *file, u32 id) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_fh *fh = NULL; + struct v4l2_ctrl_handler *hdl = NULL; + + if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) + fh = file->private_data; + + if (fh && fh->ctrl_handler) + hdl = fh->ctrl_handler; + else if (vdev->ctrl_handler) + hdl = vdev->ctrl_handler; + + if (hdl) { + struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id); + + return ctrl && ctrl->type == V4L2_CTRL_TYPE_STRING; } + return false; }
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) +static int get_v4l2_ext_controls32(struct file *file, + struct v4l2_ext_controls *kp, + struct v4l2_ext_controls32 __user *up) { struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols; @@ -621,7 +632,7 @@ static int get_v4l2_ext_controls32(struc return -EFAULT; if (get_user(id, &kcontrols->id)) return -EFAULT; - if (ctrl_is_pointer(id)) { + if (ctrl_is_pointer(file, id)) { void __user *s;
if (get_user(p, &ucontrols->string)) @@ -636,7 +647,9 @@ static int get_v4l2_ext_controls32(struc return 0; }
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) +static int put_v4l2_ext_controls32(struct file *file, + struct v4l2_ext_controls *kp, + struct v4l2_ext_controls32 __user *up) { struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols = @@ -668,7 +681,7 @@ static int put_v4l2_ext_controls32(struc /* Do not modify the pointer when copying a pointer control. The contents of the pointer was changed, not the pointer itself. */ - if (ctrl_is_pointer(id)) + if (ctrl_is_pointer(file, id)) size -= sizeof(ucontrols->value64); if (copy_in_user(ucontrols, kcontrols, size)) return -EFAULT; @@ -832,7 +845,7 @@ static long do_video_ioctl(struct file * case VIDIOC_G_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: - err = get_v4l2_ext_controls32(&karg.v2ecs, up); + err = get_v4l2_ext_controls32(file, &karg.v2ecs, up); compatible_arg = 0; break; case VIDIOC_DQEVENT: @@ -859,7 +872,7 @@ static long do_video_ioctl(struct file * case VIDIOC_G_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: - if (put_v4l2_ext_controls32(&karg.v2ecs, up)) + if (put_v4l2_ext_controls32(file, &karg.v2ecs, up)) err = -EFAULT; break; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner tglx@linutronix.de
commit d5421ea43d30701e03cadc56a38854c36a8b4433 upstream.
The hrtimer interrupt code contains a hang detection and mitigation mechanism, which prevents that a long delayed hrtimer interrupt causes a continous retriggering of interrupts which prevent the system from making progress. If a hang is detected then the timer hardware is programmed with a certain delay into the future and a flag is set in the hrtimer cpu base which prevents newly enqueued timers from reprogramming the timer hardware prior to the chosen delay. The subsequent hrtimer interrupt after the delay clears the flag and resumes normal operation.
If such a hang happens in the last hrtimer interrupt before a CPU is unplugged then the hang_detected flag is set and stays that way when the CPU is plugged in again. At that point the timer hardware is not armed and it cannot be armed because the hang_detected flag is still active, so nothing clears that flag. As a consequence the CPU does not receive hrtimer interrupts and no timers expire on that CPU which results in RCU stalls and other malfunctions.
Clear the flag along with some other less critical members of the hrtimer cpu base to ensure starting from a clean state when a CPU is plugged in.
Thanks to Paul, Sebastian and Anna-Maria for their help to get down to the root cause of that hard to reproduce heisenbug. Once understood it's trivial and certainly justifies a brown paperbag.
Fixes: 41d2e4949377 ("hrtimer: Tune hrtimer_interrupt hang logic") Reported-by: Paul E. McKenney paulmck@linux.vnet.ibm.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Cc: Peter Zijlstra peterz@infradead.org Cc: Sebastian Sewior bigeasy@linutronix.de Cc: Anna-Maria Gleixner anna-maria@linutronix.de Link: https://lkml.kernel.org/r/alpine.DEB.2.20.1801261447590.2067@nanos [bwh: Backported to 3.2: - There's no next_timer field to reset - Adjust filename, context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- kernel/hrtimer.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -657,6 +657,7 @@ static int hrtimer_reprogram(struct hrti static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { base->expires_next.tv64 = KTIME_MAX; + base->hang_detected = 0; base->hres_active = 0; }
@@ -1702,6 +1703,7 @@ static void __cpuinit init_hrtimers_cpu( timerqueue_init_head(&cpu_base->clock_base[i].active); }
+ cpu_base->active_bases = 0; hrtimer_init_hres(cpu_base); }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream.
Instead of doing sizeof(struct foo) use sizeof(*up). There even were cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved), which is very dangerous when the size of the reserved array changes.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com [bwh: Rebased on top of some earlier fixes] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -47,7 +47,7 @@ struct v4l2_window32 {
static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || copy_from_user(&kp->w, &up->w, sizeof(up->w)) || get_user(kp->field, &up->field) || get_user(kp->chromakey, &up->chromakey) || @@ -64,7 +64,7 @@ static int get_v4l2_window32(struct v4l2 if (get_user(p, &up->clips)) return -EFAULT; uclips = compat_ptr(p); - kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); + kclips = compat_alloc_user_space(n * sizeof(*kclips)); kp->clips = kclips; while (--n >= 0) { if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) @@ -156,14 +156,14 @@ static int __get_v4l2_format32(struct v4
static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32))) + if (!access_ok(VERIFY_READ, up, sizeof(*up))) return -EFAULT; return __get_v4l2_format32(kp, up); }
static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format))) return -EFAULT; return __get_v4l2_format32(&kp->format, &up->format); @@ -207,14 +207,14 @@ static int __put_v4l2_format32(struct v4
static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32))) + if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) return -EFAULT; return __put_v4l2_format32(kp, up); }
static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || + if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) || copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) return -EFAULT; @@ -233,7 +233,7 @@ struct v4l2_standard32 { static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) { /* other fields are not set by the user, nor used by the driver */ - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || get_user(kp->index, &up->index)) return -EFAULT; return 0; @@ -241,13 +241,13 @@ static int get_v4l2_standard32(struct v4
static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || + if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || put_user(kp->index, &up->index) || put_user(kp->id, &up->id) || - copy_to_user(up->name, kp->name, 24) || + copy_to_user(up->name, kp->name, sizeof(up->name)) || copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || put_user(kp->framelines, &up->framelines) || - copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) + copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) return -EFAULT; return 0; } @@ -293,7 +293,7 @@ static int get_v4l2_plane32(struct v4l2_
if (copy_in_user(up, up32, 2 * sizeof(__u32)) || copy_in_user(&up->data_offset, &up32->data_offset, - sizeof(__u32))) + sizeof(up->data_offset))) return -EFAULT;
if (memory == V4L2_MEMORY_USERPTR) { @@ -304,7 +304,7 @@ static int get_v4l2_plane32(struct v4l2_ return -EFAULT; } else { if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, - sizeof(__u32))) + sizeof(up32->m.mem_offset))) return -EFAULT; }
@@ -316,14 +316,14 @@ static int put_v4l2_plane32(struct v4l2_ { if (copy_in_user(up32, up, 2 * sizeof(__u32)) || copy_in_user(&up32->data_offset, &up->data_offset, - sizeof(__u32))) + sizeof(up->data_offset))) return -EFAULT;
/* For MMAP, driver might've set up the offset, so copy it back. * USERPTR stays the same (was userspace-provided), so no copying. */ if (memory == V4L2_MEMORY_MMAP) if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, - sizeof(__u32))) + sizeof(up->m.mem_offset))) return -EFAULT;
return 0; @@ -337,7 +337,7 @@ static int get_v4l2_buffer32(struct v4l2 int num_planes; int ret;
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || get_user(kp->index, &up->index) || get_user(kp->type, &up->type) || get_user(kp->flags, &up->flags) || @@ -349,8 +349,7 @@ static int get_v4l2_buffer32(struct v4l2 if (get_user(kp->bytesused, &up->bytesused) || get_user(kp->field, &up->field) || get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || - get_user(kp->timestamp.tv_usec, - &up->timestamp.tv_usec)) + get_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec)) return -EFAULT;
if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { @@ -370,13 +369,13 @@ static int get_v4l2_buffer32(struct v4l2
uplane32 = compat_ptr(p); if (!access_ok(VERIFY_READ, uplane32, - num_planes * sizeof(struct v4l2_plane32))) + num_planes * sizeof(*uplane32))) return -EFAULT;
/* We don't really care if userspace decides to kill itself * by passing a very big num_planes value */ uplane = compat_alloc_user_space(num_planes * - sizeof(struct v4l2_plane)); + sizeof(*uplane)); kp->m.planes = (__force struct v4l2_plane *)uplane;
while (--num_planes >= 0) { @@ -422,7 +421,7 @@ static int put_v4l2_buffer32(struct v4l2 int num_planes; int ret;
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || + if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || put_user(kp->index, &up->index) || put_user(kp->type, &up->type) || put_user(kp->flags, &up->flags) || @@ -434,7 +433,7 @@ static int put_v4l2_buffer32(struct v4l2 put_user(kp->field, &up->field) || put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || - copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || + copy_to_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) || put_user(kp->sequence, &up->sequence) || put_user(kp->reserved, &up->reserved)) return -EFAULT; @@ -489,7 +488,7 @@ static int get_v4l2_framebuffer32(struct { u32 tmp;
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || get_user(tmp, &up->base) || get_user(kp->capability, &up->capability) || get_user(kp->flags, &up->flags) || @@ -503,7 +502,7 @@ static int put_v4l2_framebuffer32(struct { u32 tmp = (u32)((unsigned long)kp->base);
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || + if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || put_user(tmp, &up->base) || put_user(kp->capability, &up->capability) || put_user(kp->flags, &up->flags) || @@ -528,14 +527,14 @@ struct v4l2_input32 { Otherwise it is identical to the 32-bit version. */ static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) { - if (copy_from_user(kp, up, sizeof(struct v4l2_input32))) + if (copy_from_user(kp, up, sizeof(*up))) return -EFAULT; return 0; }
static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) { - if (copy_to_user(up, kp, sizeof(struct v4l2_input32))) + if (copy_to_user(up, kp, sizeof(*up))) return -EFAULT; return 0; } @@ -583,7 +582,7 @@ static int get_v4l2_ext_controls32(struc int n; compat_caddr_t p;
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || get_user(kp->ctrl_class, &up->ctrl_class) || get_user(kp->count, &up->count) || get_user(kp->error_idx, &up->error_idx) || @@ -597,10 +596,9 @@ static int get_v4l2_ext_controls32(struc if (get_user(p, &up->controls)) return -EFAULT; ucontrols = compat_ptr(p); - if (!access_ok(VERIFY_READ, ucontrols, - n * sizeof(struct v4l2_ext_control32))) + if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(*ucontrols))) return -EFAULT; - kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); + kcontrols = compat_alloc_user_space(n * sizeof(*kcontrols)); kp->controls = (__force struct v4l2_ext_control *)kcontrols; while (--n >= 0) { u32 id; @@ -632,7 +630,7 @@ static int put_v4l2_ext_controls32(struc int n = kp->count; compat_caddr_t p;
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || + if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || put_user(kp->ctrl_class, &up->ctrl_class) || put_user(kp->count, &up->count) || put_user(kp->error_idx, &up->error_idx) || @@ -644,8 +642,7 @@ static int put_v4l2_ext_controls32(struc if (get_user(p, &up->controls)) return -EFAULT; ucontrols = compat_ptr(p); - if (!access_ok(VERIFY_WRITE, ucontrols, - n * sizeof(struct v4l2_ext_control32))) + if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(*ucontrols))) return -EFAULT;
while (--n >= 0) { @@ -682,14 +679,14 @@ struct v4l2_event32 {
static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) || + if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || put_user(kp->type, &up->type) || copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || put_user(kp->pending, &up->pending) || put_user(kp->sequence, &up->sequence) || put_compat_timespec(&kp->timestamp, &up->timestamp) || put_user(kp->id, &up->id) || - copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) + copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) return -EFAULT; return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Kevin Cernekee cernekee@chromium.org
commit a46182b00290839fa3fa159d54fd3237bd8669f0 upstream.
Closing a multicast socket after the final IPv4 address is deleted from an interface can generate a membership report that uses the source IP from a different interface. The following test script, run from an isolated netns, reproduces the issue:
#!/bin/bash
ip link add dummy0 type dummy ip link add dummy1 type dummy ip link set dummy0 up ip link set dummy1 up ip addr add 10.1.1.1/24 dev dummy0 ip addr add 192.168.99.99/24 dev dummy1
tcpdump -U -i dummy0 & socat EXEC:"sleep 2" \ UDP4-DATAGRAM:239.101.1.68:8889,ip-add-membership=239.0.1.68:10.1.1.1 &
sleep 1 ip addr del 10.1.1.1/24 dev dummy0 sleep 5 kill %tcpdump
RFC 3376 specifies that the report must be sent with a valid IP source address from the destination subnet, or from address 0.0.0.0. Add an extra check to make sure this is the case.
Signed-off-by: Kevin Cernekee cernekee@chromium.org Reviewed-by: Andrew Lunn andrew@lunn.ch Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/ipv4/igmp.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
--- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -89,6 +89,7 @@ #include <linux/if_arp.h> #include <linux/rtnetlink.h> #include <linux/times.h> +#include <linux/byteorder/generic.h>
#include <net/net_namespace.h> #include <net/arp.h> @@ -299,6 +300,23 @@ igmp_scount(struct ip_mc_list *pmc, int return scount; }
+/* source address selection per RFC 3376 section 4.2.13 */ +static __be32 igmpv3_get_srcaddr(struct net_device *dev, + const struct flowi4 *fl4) +{ + struct in_device *in_dev = __in_dev_get_rcu(dev); + + if (!in_dev) + return htonl(INADDR_ANY); + + for_ifa(in_dev) { + if (inet_ifa_match(fl4->saddr, ifa)) + return fl4->saddr; + } endfor_ifa(in_dev); + + return htonl(INADDR_ANY); +} + static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu) { struct sk_buff *skb; @@ -345,7 +363,7 @@ static struct sk_buff *igmpv3_newpack(st pip->frag_off = htons(IP_DF); pip->ttl = 1; pip->daddr = fl4.daddr; - pip->saddr = fl4.saddr; + pip->saddr = igmpv3_get_srcaddr(dev, &fl4); pip->protocol = IPPROTO_IGMP; pip->tot_len = 0; /* filled in later */ ip_select_ident(skb, NULL);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Anshuman Khandual khandual@linux.vnet.ibm.com
commit 4991c09c7c812dba13ea9be79a68b4565bb1fa4e upstream.
While testing on a large CPU system, detected the following RCU stall many times over the span of the workload. This problem is solved by adding a cond_resched() in the change_pmd_range() function.
INFO: rcu_sched detected stalls on CPUs/tasks: 154-....: (670 ticks this GP) idle=022/140000000000000/0 softirq=2825/2825 fqs=612 (detected by 955, t=6002 jiffies, g=4486, c=4485, q=90864) Sending NMI from CPU 955 to CPUs 154: NMI backtrace for cpu 154 CPU: 154 PID: 147071 Comm: workload Not tainted 4.15.0-rc3+ #3 NIP: c0000000000b3f64 LR: c0000000000b33d4 CTR: 000000000000aa18 REGS: 00000000a4b0fb44 TRAP: 0501 Not tainted (4.15.0-rc3+) MSR: 8000000000009033 <SF,EE,ME,IR,DR,RI,LE> CR: 22422082 XER: 00000000 CFAR: 00000000006cf8f0 SOFTE: 1 GPR00: 0010000000000000 c00003ef9b1cb8c0 c0000000010cc600 0000000000000000 GPR04: 8e0000018c32b200 40017b3858fd6e00 8e0000018c32b208 40017b3858fd6e00 GPR08: 8e0000018c32b210 40017b3858fd6e00 8e0000018c32b218 40017b3858fd6e00 GPR12: ffffffffffffffff c00000000fb25100 NIP [c0000000000b3f64] plpar_hcall9+0x44/0x7c LR [c0000000000b33d4] pSeries_lpar_flush_hash_range+0x384/0x420 Call Trace: flush_hash_range+0x48/0x100 __flush_tlb_pending+0x44/0xd0 hpte_need_flush+0x408/0x470 change_protection_range+0xaac/0xf10 change_prot_numa+0x30/0xb0 task_numa_work+0x2d0/0x3e0 task_work_run+0x130/0x190 do_notify_resume+0x118/0x120 ret_from_except_lite+0x70/0x74 Instruction dump: 60000000 f8810028 7ca42b78 7cc53378 7ce63b78 7d074378 7d284b78 7d495378 e9410060 e9610068 e9810070 44000022 <7d806378> e9810028 f88c0000 f8ac0008
Link: http://lkml.kernel.org/r/20171214140551.5794-1-khandual@linux.vnet.ibm.com Signed-off-by: Anshuman Khandual khandual@linux.vnet.ibm.com Suggested-by: Nicholas Piggin npiggin@gmail.com Acked-by: Michal Hocko mhocko@suse.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- mm/mprotect.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -92,13 +92,15 @@ static inline void change_pmd_range(stru if (next - addr != HPAGE_PMD_SIZE) split_huge_page_pmd(vma->vm_mm, pmd); else if (change_huge_pmd(vma, pmd, addr, newprot)) - continue; + goto next; /* fall through */ } if (pmd_none_or_clear_bad(pmd)) - continue; + goto next; change_pte_range(vma->vm_mm, pmd, addr, next, newprot, dirty_accountable); +next: + cond_resched(); } while (pmd++, addr = next, addr != end); }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds torvalds@linux-foundation.org
commit 966031f340185eddd05affcf72b740549f056348 upstream.
We added support for EXTPROC back in 2010 in commit 26df6d13406d ("tty: Add EXTPROC support for LINEMODE") and the intent was to allow it to override some (all?) ICANON behavior. Quoting from that original commit message:
There is a new bit in the termios local flag word, EXTPROC. When this bit is set, several aspects of the terminal driver are disabled. Input line editing, character echo, and mapping of signals are all disabled. This allows the telnetd to turn off these functions when in linemode, but still keep track of what state the user wants the terminal to be in.
but the problem turns out that "several aspects of the terminal driver are disabled" is a bit ambiguous, and you can really confuse the n_tty layer by setting EXTPROC and then causing some of the ICANON invariants to no longer be maintained.
This fixes at least one such case (TIOCINQ) becoming unhappy because of the confusion over whether ICANON really means ICANON when EXTPROC is set.
This basically makes TIOCINQ match the case of read: if EXTPROC is set, we ignore ICANON. Also, make sure to reset the ICANON state ie EXTPROC changes, not just if ICANON changes.
Fixes: 26df6d13406d ("tty: Add EXTPROC support for LINEMODE") Reported-by: Tetsuo Handa penguin-kernel@i-love.sakura.ne.jp Reported-by: syzkaller syzkaller@googlegroups.com Cc: Jiri Slaby jslaby@suse.com Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/tty/n_tty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1459,7 +1459,7 @@ static void n_tty_set_termios(struct tty BUG_ON(!tty);
if (old) - canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON; + canon_change = (old->c_lflag ^ tty->termios->c_lflag) & (ICANON | EXTPROC); if (canon_change) { memset(&tty->read_flags, 0, sizeof tty->read_flags); tty->canon_head = tty->read_tail; @@ -2096,7 +2096,7 @@ static int n_tty_ioctl(struct tty_struct case TIOCINQ: /* FIXME: Locking */ retval = tty->read_cnt; - if (L_ICANON(tty)) + if (L_ICANON(tty) && !L_EXTPROC(tty)) retval = inq_canon(tty); return put_user(retval, (unsigned int __user *) arg); default:
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Lan Tianyu tianyu.lan@intel.com
commit f29810335965ac1f7bcb501ee2af5f039f792416 upstream.
Reported by syzkaller: WARNING: CPU: 0 PID: 27962 at arch/x86/kvm/emulate.c:5631 x86_emulate_insn+0x557/0x15f0 [kvm] Modules linked in: kvm_intel kvm [last unloaded: kvm] CPU: 0 PID: 27962 Comm: syz-executor Tainted: G B W 4.15.0-rc2-next-20171208+ #32 Hardware name: Intel Corporation S1200SP/S1200SP, BIOS S1200SP.86B.01.03.0006.040720161253 04/07/2016 RIP: 0010:x86_emulate_insn+0x557/0x15f0 [kvm] RSP: 0018:ffff8807234476d0 EFLAGS: 00010282 RAX: 0000000000000000 RBX: ffff88072d0237a0 RCX: ffffffffa0065c4d RDX: 1ffff100e5a046f9 RSI: 0000000000000003 RDI: ffff88072d0237c8 RBP: ffff880723447728 R08: ffff88072d020000 R09: ffffffffa008d240 R10: 0000000000000002 R11: ffffed00e7d87db3 R12: ffff88072d0237c8 R13: ffff88072d023870 R14: ffff88072d0238c2 R15: ffffffffa008d080 FS: 00007f8a68666700(0000) GS:ffff880802200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000002009506c CR3: 000000071fec4005 CR4: 00000000003626f0 Call Trace: x86_emulate_instruction+0x3bc/0xb70 [kvm] ? reexecute_instruction.part.162+0x130/0x130 [kvm] vmx_handle_exit+0x46d/0x14f0 [kvm_intel] ? trace_event_raw_event_kvm_entry+0xe7/0x150 [kvm] ? handle_vmfunc+0x2f0/0x2f0 [kvm_intel] ? wait_lapic_expire+0x25/0x270 [kvm] vcpu_enter_guest+0x720/0x1ef0 [kvm] ...
When CS.L is set, vcpu should run in the 64 bit paging mode. Current kvm set_sregs function doesn't have such check when userspace inputs sreg values. This will lead unexpected behavior. This patch is to add checks for CS.L, EFER.LME, EFER.LMA and CR4.PAE when get SREG inputs from userspace in order to avoid unexpected behavior.
Suggested-by: Paolo Bonzini pbonzini@redhat.com Reported-by: Dmitry Vyukov dvyukov@google.com Cc: Paolo Bonzini pbonzini@redhat.com Cc: Radim Krčmář rkrcmar@redhat.com Cc: Dmitry Vyukov dvyukov@google.com Cc: Jim Mattson jmattson@google.com Signed-off-by: Tianyu Lan tianyu.lan@intel.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/x86/kvm/x86.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
--- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6172,6 +6172,29 @@ int kvm_task_switch(struct kvm_vcpu *vcp } EXPORT_SYMBOL_GPL(kvm_task_switch);
+int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) +{ + if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG_BIT)) { + /* + * When EFER.LME and CR0.PG are set, the processor is in + * 64-bit mode (though maybe in a 32-bit code segment). + * CR4.PAE and EFER.LMA must be set. + */ + if (!(sregs->cr4 & X86_CR4_PAE_BIT) + || !(sregs->efer & EFER_LMA)) + return -EINVAL; + } else { + /* + * Not in 64-bit mode: EFER.LMA is clear and the code + * segment cannot be 64-bit. + */ + if (sregs->efer & EFER_LMA || sregs->cs.l) + return -EINVAL; + } + + return 0; +} + int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) { @@ -6182,6 +6205,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) return -EINVAL;
+ if (kvm_valid_sregs(vcpu, sregs)) + return -EINVAL; + dt.size = sregs->idt.limit; dt.address = sregs->idt.base; kvm_x86_ops->set_idt(vcpu, &dt);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shuah Khan shuahkh@osg.samsung.com
commit e1346fd87c71a1f61de1fe476ec8df1425ac931c upstream.
usbip_dump_usb_device() and usbip_dump_urb() print kernel addresses. Remove kernel addresses from usb device and urb debug msgs and improve the message content.
Instead of printing parent device and bus addresses, print parent device and bus names.
Signed-off-by: Shuah Khan shuahkh@osg.samsung.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [bwh: Backported to 3.2: adjust filename, context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -115,7 +115,7 @@ static void usbip_dump_usb_device(struct break; }
- pr_debug("tt %p, ttport %d\n", udev->tt, udev->ttport); + pr_debug("tt hub ttport %d\n", udev->ttport);
dev_dbg(dev, " "); for (i = 0; i < 16; i++) @@ -148,11 +148,8 @@ static void usbip_dump_usb_device(struct } pr_debug("\n");
- dev_dbg(dev, "parent %p, bus %p\n", udev->parent, udev->bus); - - dev_dbg(dev, "descriptor %p, config %p, actconfig %p, " - "rawdescriptors %p\n", &udev->descriptor, udev->config, - udev->actconfig, udev->rawdescriptors); + dev_dbg(dev, "parent %s, bus %s\n", dev_name(&udev->parent->dev), + udev->bus->bus_name);
dev_dbg(dev, "have_langid %d, string_langid %d\n", udev->have_langid, udev->string_langid); @@ -261,9 +258,6 @@ void usbip_dump_urb(struct urb *urb)
dev = &urb->dev->dev;
- dev_dbg(dev, " urb :%p\n", urb); - dev_dbg(dev, " dev :%p\n", urb->dev); - usbip_dump_usb_device(urb->dev);
dev_dbg(dev, " pipe :%08x ", urb->pipe); @@ -272,11 +266,9 @@ void usbip_dump_urb(struct urb *urb)
dev_dbg(dev, " status :%d\n", urb->status); dev_dbg(dev, " transfer_flags :%08X\n", urb->transfer_flags); - dev_dbg(dev, " transfer_buffer :%p\n", urb->transfer_buffer); dev_dbg(dev, " transfer_buffer_length:%d\n", urb->transfer_buffer_length); dev_dbg(dev, " actual_length :%d\n", urb->actual_length); - dev_dbg(dev, " setup_packet :%p\n", urb->setup_packet);
if (urb->setup_packet && usb_pipetype(urb->pipe) == PIPE_CONTROL) usbip_dump_usb_ctrlrequest( @@ -286,8 +278,6 @@ void usbip_dump_urb(struct urb *urb) dev_dbg(dev, " number_of_packets :%d\n", urb->number_of_packets); dev_dbg(dev, " interval :%d\n", urb->interval); dev_dbg(dev, " error_count :%d\n", urb->error_count); - dev_dbg(dev, " context :%p\n", urb->context); - dev_dbg(dev, " complete :%p\n", urb->complete); } EXPORT_SYMBOL_GPL(usbip_dump_urb);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit b7b957d429f601d6d1942122b339474f31191d75 upstream.
The indentation of this source is all over the place. Fix this. This patch only changes whitespace.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com [bwh: Rebased on top of some earlier fixes] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -48,11 +48,11 @@ struct v4l2_window32 { static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || - copy_from_user(&kp->w, &up->w, sizeof(up->w)) || - get_user(kp->field, &up->field) || - get_user(kp->chromakey, &up->chromakey) || - get_user(kp->clipcount, &up->clipcount)) - return -EFAULT; + copy_from_user(&kp->w, &up->w, sizeof(up->w)) || + get_user(kp->field, &up->field) || + get_user(kp->chromakey, &up->chromakey) || + get_user(kp->clipcount, &up->clipcount)) + return -EFAULT; if (kp->clipcount > 2048) return -EINVAL; if (kp->clipcount) { @@ -82,10 +82,10 @@ static int get_v4l2_window32(struct v4l2 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || - put_user(kp->field, &up->field) || - put_user(kp->chromakey, &up->chromakey) || - put_user(kp->clipcount, &up->clipcount)) - return -EFAULT; + put_user(kp->field, &up->field) || + put_user(kp->chromakey, &up->chromakey) || + put_user(kp->clipcount, &up->clipcount)) + return -EFAULT; return 0; }
@@ -97,7 +97,7 @@ static inline int get_v4l2_pix_format(st }
static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, - struct v4l2_pix_format_mplane __user *up) + struct v4l2_pix_format_mplane __user *up) { if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane))) return -EFAULT; @@ -112,7 +112,7 @@ static inline int put_v4l2_pix_format(st }
static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, - struct v4l2_pix_format_mplane __user *up) + struct v4l2_pix_format_mplane __user *up) { if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane))) return -EFAULT; @@ -204,7 +204,7 @@ static int __get_v4l2_format32(struct v4 return 0; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", - kp->type); + kp->type); return -EINVAL; } } @@ -252,7 +252,7 @@ static int __put_v4l2_format32(struct v4 return 0; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", - kp->type); + kp->type); return -EINVAL; } } @@ -286,7 +286,7 @@ static int get_v4l2_standard32(struct v4 { /* other fields are not set by the user, nor used by the driver */ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || - get_user(kp->index, &up->index)) + get_user(kp->index, &up->index)) return -EFAULT; return 0; } @@ -294,13 +294,13 @@ static int get_v4l2_standard32(struct v4 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || - put_user(kp->index, &up->index) || - put_user(kp->id, &up->id) || - copy_to_user(up->name, kp->name, 24) || - copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || - put_user(kp->framelines, &up->framelines) || - copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) - return -EFAULT; + put_user(kp->index, &up->index) || + put_user(kp->id, &up->id) || + copy_to_user(up->name, kp->name, 24) || + copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || + put_user(kp->framelines, &up->framelines) || + copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) + return -EFAULT; return 0; }
@@ -338,14 +338,14 @@ struct v4l2_buffer32 { };
static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, - enum v4l2_memory memory) + enum v4l2_memory memory) { void __user *up_pln; compat_long_t p;
if (copy_in_user(up, up32, 2 * sizeof(__u32)) || - copy_in_user(&up->data_offset, &up32->data_offset, - sizeof(__u32))) + copy_in_user(&up->data_offset, &up32->data_offset, + sizeof(__u32))) return -EFAULT;
if (memory == V4L2_MEMORY_USERPTR) { @@ -356,7 +356,7 @@ static int get_v4l2_plane32(struct v4l2_ return -EFAULT; } else { if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, - sizeof(__u32))) + sizeof(__u32))) return -EFAULT; }
@@ -364,18 +364,18 @@ static int get_v4l2_plane32(struct v4l2_ }
static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, - enum v4l2_memory memory) + enum v4l2_memory memory) { if (copy_in_user(up32, up, 2 * sizeof(__u32)) || - copy_in_user(&up32->data_offset, &up->data_offset, - sizeof(__u32))) + copy_in_user(&up32->data_offset, &up->data_offset, + sizeof(__u32))) return -EFAULT;
/* For MMAP, driver might've set up the offset, so copy it back. * USERPTR stays the same (was userspace-provided), so no copying. */ if (memory == V4L2_MEMORY_MMAP) if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, - sizeof(__u32))) + sizeof(__u32))) return -EFAULT;
return 0; @@ -390,19 +390,19 @@ static int get_v4l2_buffer32(struct v4l2 int ret;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || - get_user(kp->index, &up->index) || - get_user(kp->type, &up->type) || - get_user(kp->flags, &up->flags) || - get_user(kp->memory, &up->memory) || - get_user(kp->input, &up->input)) - return -EFAULT; + get_user(kp->index, &up->index) || + get_user(kp->type, &up->type) || + get_user(kp->flags, &up->flags) || + get_user(kp->memory, &up->memory) || + get_user(kp->input, &up->input)) + return -EFAULT;
if (V4L2_TYPE_IS_OUTPUT(kp->type)) if (get_user(kp->bytesused, &up->bytesused) || - get_user(kp->field, &up->field) || - get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || - get_user(kp->timestamp.tv_usec, - &up->timestamp.tv_usec)) + get_user(kp->field, &up->field) || + get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || + get_user(kp->timestamp.tv_usec, + &up->timestamp.tv_usec)) return -EFAULT;
if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { @@ -422,13 +422,13 @@ static int get_v4l2_buffer32(struct v4l2
uplane32 = compat_ptr(p); if (!access_ok(VERIFY_READ, uplane32, - num_planes * sizeof(struct v4l2_plane32))) + num_planes * sizeof(struct v4l2_plane32))) return -EFAULT;
/* We don't really care if userspace decides to kill itself * by passing a very big num_planes value */ uplane = compat_alloc_user_space(num_planes * - sizeof(struct v4l2_plane)); + sizeof(struct v4l2_plane)); kp->m.planes = (__force struct v4l2_plane *)uplane;
while (--num_planes >= 0) { @@ -442,18 +442,18 @@ static int get_v4l2_buffer32(struct v4l2 switch (kp->memory) { case V4L2_MEMORY_MMAP: if (get_user(kp->length, &up->length) || - get_user(kp->m.offset, &up->m.offset)) + get_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: { - compat_long_t tmp; + compat_long_t tmp;
- if (get_user(kp->length, &up->length) || - get_user(tmp, &up->m.userptr)) - return -EFAULT; + if (get_user(kp->length, &up->length) || + get_user(tmp, &up->m.userptr)) + return -EFAULT;
- kp->m.userptr = (unsigned long)compat_ptr(tmp); + kp->m.userptr = (unsigned long)compat_ptr(tmp); } break; case V4L2_MEMORY_OVERLAY: @@ -475,21 +475,21 @@ static int put_v4l2_buffer32(struct v4l2 int ret;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || - put_user(kp->index, &up->index) || - put_user(kp->type, &up->type) || - put_user(kp->flags, &up->flags) || - put_user(kp->memory, &up->memory) || - put_user(kp->input, &up->input)) - return -EFAULT; + put_user(kp->index, &up->index) || + put_user(kp->type, &up->type) || + put_user(kp->flags, &up->flags) || + put_user(kp->memory, &up->memory) || + put_user(kp->input, &up->input)) + return -EFAULT;
if (put_user(kp->bytesused, &up->bytesused) || - put_user(kp->field, &up->field) || - put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || - put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || - copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || - put_user(kp->sequence, &up->sequence) || - put_user(kp->reserved, &up->reserved)) - return -EFAULT; + put_user(kp->field, &up->field) || + put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || + put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || + copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || + put_user(kp->sequence, &up->sequence) || + put_user(kp->reserved, &up->reserved)) + return -EFAULT;
if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { num_planes = kp->length; @@ -512,12 +512,12 @@ static int put_v4l2_buffer32(struct v4l2 switch (kp->memory) { case V4L2_MEMORY_MMAP: if (put_user(kp->length, &up->length) || - put_user(kp->m.offset, &up->m.offset)) + put_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: if (put_user(kp->length, &up->length) || - put_user(kp->m.userptr, &up->m.userptr)) + put_user(kp->m.userptr, &up->m.userptr)) return -EFAULT; break; case V4L2_MEMORY_OVERLAY: @@ -542,10 +542,10 @@ static int get_v4l2_framebuffer32(struct u32 tmp;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || - get_user(tmp, &up->base) || - get_user(kp->capability, &up->capability) || - get_user(kp->flags, &up->flags)) - return -EFAULT; + get_user(tmp, &up->base) || + get_user(kp->capability, &up->capability) || + get_user(kp->flags, &up->flags)) + return -EFAULT; kp->base = (__force void *)compat_ptr(tmp); get_v4l2_pix_format(&kp->fmt, &up->fmt); return 0; @@ -556,10 +556,10 @@ static int put_v4l2_framebuffer32(struct u32 tmp = (u32)((unsigned long)kp->base);
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || - put_user(tmp, &up->base) || - put_user(kp->capability, &up->capability) || - put_user(kp->flags, &up->flags)) - return -EFAULT; + put_user(tmp, &up->base) || + put_user(kp->capability, &up->capability) || + put_user(kp->flags, &up->flags)) + return -EFAULT; put_v4l2_pix_format(&kp->fmt, &up->fmt); return 0; } @@ -593,11 +593,11 @@ static inline int put_v4l2_input32(struc }
struct v4l2_ext_controls32 { - __u32 ctrl_class; - __u32 count; - __u32 error_idx; - __u32 reserved[2]; - compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ };
struct v4l2_ext_control32 { @@ -636,11 +636,11 @@ static int get_v4l2_ext_controls32(struc compat_caddr_t p;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || - get_user(kp->ctrl_class, &up->ctrl_class) || - get_user(kp->count, &up->count) || - get_user(kp->error_idx, &up->error_idx) || - copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) - return -EFAULT; + get_user(kp->ctrl_class, &up->ctrl_class) || + get_user(kp->count, &up->count) || + get_user(kp->error_idx, &up->error_idx) || + copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) + return -EFAULT; n = kp->count; if (n == 0) { kp->controls = NULL; @@ -650,7 +650,7 @@ static int get_v4l2_ext_controls32(struc return -EFAULT; ucontrols = compat_ptr(p); if (!access_ok(VERIFY_READ, ucontrols, - n * sizeof(struct v4l2_ext_control32))) + n * sizeof(struct v4l2_ext_control32))) return -EFAULT; kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); kp->controls = (__force struct v4l2_ext_control *)kcontrols; @@ -685,11 +685,11 @@ static int put_v4l2_ext_controls32(struc compat_caddr_t p;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || - put_user(kp->ctrl_class, &up->ctrl_class) || - put_user(kp->count, &up->count) || - put_user(kp->error_idx, &up->error_idx) || - copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) - return -EFAULT; + put_user(kp->ctrl_class, &up->ctrl_class) || + put_user(kp->count, &up->count) || + put_user(kp->error_idx, &up->error_idx) || + copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) + return -EFAULT; if (!kp->count) return 0;
@@ -697,7 +697,7 @@ static int put_v4l2_ext_controls32(struc return -EFAULT; ucontrols = compat_ptr(p); if (!access_ok(VERIFY_WRITE, ucontrols, - n * sizeof(struct v4l2_ext_control32))) + n * sizeof(struct v4l2_ext_control32))) return -EFAULT;
while (--n >= 0) { @@ -735,14 +735,14 @@ struct v4l2_event32 { static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) || - put_user(kp->type, &up->type) || - copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || - put_user(kp->pending, &up->pending) || - put_user(kp->sequence, &up->sequence) || - put_compat_timespec(&kp->timestamp, &up->timestamp) || - put_user(kp->id, &up->id) || - copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) - return -EFAULT; + put_user(kp->type, &up->type) || + copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || + put_user(kp->pending, &up->pending) || + put_user(kp->sequence, &up->sequence) || + put_compat_timespec(&kp->timestamp, &up->timestamp) || + put_user(kp->id, &up->id) || + copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) + return -EFAULT; return 0; }
@@ -1040,8 +1040,8 @@ long v4l2_compat_ioctl32(struct file *fi
default: printk(KERN_WARNING "compat_ioctl32: " - "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", - _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); + "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", + _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); break; } return ret;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner tglx@linutronix.de
commit 6f41c34d69eb005e7848716bbcafc979b35037d5 upstream.
The machine check idtentry uses an indirect branch directly from the low level code. This evades the speculation protection.
Replace it by a direct call into C code and issue the indirect call there so the compiler can apply the proper speculation protection.
Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by:Borislav Petkov bp@alien8.de Reviewed-by: David Woodhouse dwmw@amazon.co.uk Niced-by: Peter Zijlstra peterz@infradead.org Link: https://lkml.kernel.org/r/alpine.DEB.2.20.1801181626290.1847@nanos [bwh: Backported to 3.2: - Don't use dotraplinkage - Adjust filename, context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/x86/include/asm/traps.h | 1 + arch/x86/kernel/cpu/mcheck/mce.c | 5 +++++ arch/x86/kernel/entry_64.S | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-)
--- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h @@ -69,6 +69,7 @@ dotraplinkage void do_simd_coprocessor_e #ifdef CONFIG_X86_32 dotraplinkage void do_iret_error(struct pt_regs *, long); #endif +void do_mce(struct pt_regs *, long);
static inline int get_si_code(unsigned long condition) { --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1407,6 +1407,11 @@ static void unexpected_machine_check(str void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
+void do_mce(struct pt_regs *regs, long error_code) +{ + machine_check_vector(regs, error_code); +} + /* * Called for each booted CPU to set up machine checks. * Must be called with preempt off: --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1399,7 +1399,7 @@ errorentry page_fault do_page_fault errorentry async_page_fault do_async_page_fault #endif #ifdef CONFIG_X86_MCE -paranoidzeroentry machine_check *machine_check_vector(%rip) +paranoidzeroentry machine_check do_mce #endif
/*
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hverkuil@xs4all.nl
commit 037e0865c2ecbaa4558feba239ece08d7e457ec0 upstream.
The v4l2_input32 struct wasn't updated when this field was added. It didn't cause a failure in the compat code, but it is better to keep it in sync with v4l2_input to avoid confusion.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com [bwh: Backported to 3.2: adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -572,7 +572,8 @@ struct v4l2_input32 { __u32 tuner; /* Associated tuner */ compat_u64 std; __u32 status; - __u32 reserved[4]; + __u32 capabilities; + __u32 reserved[3]; };
/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dennis Yang dennisyang@qnap.com
commit 490ae017f54e55bde382d45ea24bddfb6d1a0aaf upstream.
For btree removal, there is a corner case that a single thread could takes 6 locks which is more than THIN_MAX_CONCURRENT_LOCKS(5) and leads to deadlock.
A btree removal might eventually call rebalance_children()->rebalance3() to rebalance entries of three neighbor child nodes when shadow_spine has already acquired two write locks. In rebalance3(), it tries to shadow and acquire the write locks of all three child nodes. However, shadowing a child node requires acquiring a read lock of the original child node and a write lock of the new block. Although the read lock will be released after block shadowing, shadowing the third child node in rebalance3() could still take the sixth lock. (2 write locks for shadow_spine + 2 write locks for the first two child nodes's shadow + 1 write lock for the last child node's shadow + 1 read lock for the last child node)
Signed-off-by: Dennis Yang dennisyang@qnap.com Acked-by: Joe Thornber thornber@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/md/dm-thin-metadata.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -81,10 +81,14 @@ #define SECTOR_TO_BLOCK_SHIFT 3
/* + * For btree insert: * 3 for btree insert + * 2 for btree lookup used within space map + * For btree remove: + * 2 for shadow spine + + * 4 for rebalance 3 child node */ -#define THIN_MAX_CONCURRENT_LOCKS 5 +#define THIN_MAX_CONCURRENT_LOCKS 6
/* This should be plenty */ #define SPACE_MAP_ROOT_SIZE 128
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Poirier bpoirier@suse.com
commit 4110e02eb45ea447ec6f5459c9934de0a273fb91 upstream.
e1000e_check_for_copper_link() and e1000_check_for_copper_link_ich8lan() are the two functions that may be assigned to mac.ops.check_for_link when phy.media_type == e1000_media_type_copper. Commit 19110cfbb34d ("e1000e: Separate signaling for link check/link up") changed the meaning of the return value of check_for_link for copper media but only adjusted the first function. This patch adjusts the second function likewise.
Reported-by: Christian Hesse list@eworm.de Reported-by: Gabriel C nix.or.die@gmail.com Link: https://bugzilla.kernel.org/show_bug.cgi?id=198047 Fixes: 19110cfbb34d ("e1000e: Separate signaling for link check/link up") Signed-off-by: Benjamin Poirier bpoirier@suse.com Tested-by: Aaron Brown aaron.f.brown@intel.com Tested-by: Christian Hesse list@eworm.de Signed-off-by: Jeff Kirsher jeffrey.t.kirsher@intel.com [bwh: Backported to 3.2: e1000_check_for_copper_link() has a single return statement for success and error cases, so set ret_val in the link-up case instead of changing that statement.] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/net/ethernet/intel/e1000e/ich8lan.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -657,6 +657,9 @@ out: * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. + * + * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link + * up). **/ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) { @@ -672,7 +675,7 @@ static s32 e1000_check_for_copper_link_i * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) { - ret_val = 0; + ret_val = 1; goto out; }
@@ -761,9 +764,12 @@ static s32 e1000_check_for_copper_link_i * different link partner. */ ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) + if (ret_val) { e_dbg("Error configuring flow control\n"); + return ret_val; + }
+ ret_val = 1; out: return ret_val; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jan Engelhardt jengelh@inai.de
commit 203f45003a3d03eea8fa28d74cfc74c354416fdb upstream.
queue_cache_init is first called for the Control Word Queue (n2_crypto_probe). At that time, queue_cache[0] is NULL and a new kmem_cache will be allocated. If the subsequent n2_register_algs call fails, the kmem_cache will be released in queue_cache_destroy, but queue_cache_init[0] is not set back to NULL.
So when the Module Arithmetic Unit gets probed next (n2_mau_probe), queue_cache_init will not allocate a kmem_cache again, but leave it as its bogus value, causing a BUG() to trigger when queue_cache[0] is eventually passed to kmem_cache_zalloc:
n2_crypto: Found N2CP at /virtual-devices@100/n2cp@7 n2_crypto: Registered NCS HVAPI version 2.0 called queue_cache_init n2_crypto: md5 alg registration failed n2cp f028687c: /virtual-devices@100/n2cp@7: Unable to register algorithms. called queue_cache_destroy n2cp: probe of f028687c failed with error -22 n2_crypto: Found NCP at /virtual-devices@100/ncp@6 n2_crypto: Registered NCS HVAPI version 2.0 called queue_cache_init kernel BUG at mm/slab.c:2993! Call Trace: [0000000000604488] kmem_cache_alloc+0x1a8/0x1e0 (inlined) kmem_cache_zalloc (inlined) new_queue (inlined) spu_queue_setup (inlined) handle_exec_unit [0000000010c61eb4] spu_mdesc_scan+0x1f4/0x460 [n2_crypto] [0000000010c62b80] n2_mau_probe+0x100/0x220 [n2_crypto] [000000000084b174] platform_drv_probe+0x34/0xc0
Signed-off-by: Jan Engelhardt jengelh@inai.de Acked-by: David S. Miller davem@davemloft.net Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/crypto/n2_core.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -1642,6 +1642,7 @@ static int queue_cache_init(void) CWQ_ENTRY_SIZE, 0, NULL); if (!queue_cache[HV_NCS_QTYPE_CWQ - 1]) { kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_MAU - 1]); + queue_cache[HV_NCS_QTYPE_MAU - 1] = NULL; return -ENOMEM; } return 0; @@ -1651,6 +1652,8 @@ static void queue_cache_destroy(void) { kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_MAU - 1]); kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_CWQ - 1]); + queue_cache[HV_NCS_QTYPE_MAU - 1] = NULL; + queue_cache[HV_NCS_QTYPE_CWQ - 1] = NULL; }
static int spu_queue_register(struct spu_queue *p, unsigned long q_type)
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds torvalds@linux-foundation.org
commit 3ce120b16cc548472f80cf8644f90eda958cf1b6 upstream.
It appears that hardened gentoo enables "-fstack-check" by default for gcc.
That doesn't work _at_all_ for the kernel, because the kernel stack doesn't act like a user stack at all: it's much smaller, and it doesn't auto-expand on use. So the extra "probe one page below the stack" code generated by -fstack-check just breaks the kernel in horrible ways, causing infinite double faults etc.
[ I have to say, that the particular code gcc generates looks very stupid even for user space where it works, but that's a separate issue. ]
Reported-and-tested-by: Alexander Tsoy alexander@tsoy.me Reported-and-tested-by: Toralf Förster toralf.foerster@gmx.de Cc: Dave Hansen dave.hansen@intel.com Cc: Jiri Kosina jikos@kernel.org Cc: Andy Lutomirski luto@amacapital.net Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- Makefile | 3 +++ 1 file changed, 3 insertions(+)
--- a/Makefile +++ b/Makefile @@ -631,6 +631,9 @@ KBUILD_CFLAGS += $(call cc-disable-warni # disable invalid "can't wrap" optimizations for signed / pointers KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
+# Make sure -fstack-check isn't enabled (like gentoo apparently did) +KBUILD_CFLAGS += $(call cc-option,-fno-stack-check,) + # conserve stack if available KBUILD_CFLAGS += $(call cc-option,-fconserve-stack)
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: "Steven Rostedt (VMware)" rostedt@goodmis.org
commit 45d8b80c2ac5d21cd1e2954431fb676bc2b1e099 upstream.
Two info bits were added to the "commit" part of the ring buffer data page when returned to be consumed. This was to inform the user space readers that events have been missed, and that the count may be stored at the end of the page.
What wasn't handled, was the splice code that actually called a function to return the length of the data in order to zero out the rest of the page before sending it up to user space. These data bits were returned with the length making the value negative, and that negative value was not checked. It was compared to PAGE_SIZE, and only used if the size was less than PAGE_SIZE. Luckily PAGE_SIZE is unsigned long which made the compare an unsigned compare, meaning the negative size value did not end up causing a large portion of memory to be randomly zeroed out.
Fixes: 66a8cb95ed040 ("ring-buffer: Add place holder recording of dropped events") Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- kernel/trace/ring_buffer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -360,6 +360,8 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_data /* Missed count stored at end */ #define RB_MISSED_STORED (1 << 30)
+#define RB_MISSED_FLAGS (RB_MISSED_EVENTS|RB_MISSED_STORED) + struct buffer_data_page { u64 time_stamp; /* page time stamp */ local_t commit; /* write committed index */ @@ -411,7 +413,9 @@ static void rb_init_page(struct buffer_d */ size_t ring_buffer_page_len(void *page) { - return local_read(&((struct buffer_data_page *)page)->commit) + struct buffer_data_page *bpage = page; + + return (local_read(&bpage->commit) & ~RB_MISSED_FLAGS) + BUF_PAGE_HDR_SIZE; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Joe Thornber ejt@redhat.com
commit 8c971178a788c70e8d6db5c3a813de1a1f54e5b7 upstream.
Introduce THIN_MAX_CONCURRENT_LOCKS into dm-thin-metadata to give a name to an otherwise "magic" number.
Signed-off-by: Joe Thornber ejt@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Alasdair G Kergon agk@redhat.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/md/dm-thin-metadata.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
--- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -80,6 +80,12 @@ #define THIN_METADATA_CACHE_SIZE 64 #define SECTOR_TO_BLOCK_SHIFT 3
+/* + * 3 for btree insert + + * 2 for btree lookup used within space map + */ +#define THIN_MAX_CONCURRENT_LOCKS 5 + /* This should be plenty */ #define SPACE_MAP_ROOT_SIZE 128
@@ -669,13 +675,9 @@ struct dm_pool_metadata *dm_pool_metadat return ERR_PTR(-ENOMEM); }
- /* - * Max hex locks: - * 3 for btree insert + - * 2 for btree lookup used within space map - */ bm = dm_block_manager_create(bdev, THIN_METADATA_BLOCK_SIZE, - THIN_METADATA_CACHE_SIZE, 5); + THIN_METADATA_CACHE_SIZE, + THIN_MAX_CONCURRENT_LOCKS); if (!bm) { DMERR("could not create block manager"); kfree(pmd);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau nbd@nbd.name
commit ad23b750933ea7bf962678972a286c78a8fa36aa upstream.
Commit "net: igmp: Use correct source address on IGMPv3 reports" introduced a check to validate the source address of locally generated IGMPv3 packets. Instead of checking the local interface address directly, it uses inet_ifa_match(fl4->saddr, ifa), which checks if the address is on the local subnet (or equal to the point-to-point address if used).
This breaks for point-to-point interfaces, so check against ifa->ifa_local directly.
Cc: Kevin Cernekee cernekee@chromium.org Fixes: a46182b00290 ("net: igmp: Use correct source address on IGMPv3 reports") Reported-by: Sebastian Gottschall s.gottschall@dd-wrt.com Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/ipv4/igmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -310,7 +310,7 @@ static __be32 igmpv3_get_srcaddr(struct return htonl(INADDR_ANY);
for_ifa(in_dev) { - if (inet_ifa_match(fl4->saddr, ifa)) + if (fl4->saddr == ifa->ifa_local) return fl4->saddr; } endfor_ifa(in_dev);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Oscar Campos oscar.campos@member.fsf.org
commit 293b915fd9bebf33cdc906516fb28d54649a25ac upstream.
Trackpoint buttons detection fails on ThinkPad 570 and 470 series, this makes the middle button of the trackpoint to not being recogized. As I don't believe there is any trackpoint with less than 3 buttons this patch just assumes three buttons when the extended button information read fails.
Signed-off-by: Oscar Campos oscar.campos@member.fsf.org Acked-by: Peter Hutterer peter.hutterer@who-t.net Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/input/mouse/trackpoint.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -298,8 +298,8 @@ int trackpoint_detect(struct psmouse *ps return 0;
if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { - printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n"); - button_info = 0; + printk(KERN_WARNING "trackpoint.c: failed to get extended button data, assuming 3 buttons\n"); + button_info = 0x33; }
psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Mentz danielmentz@google.com
commit 025a26fa14f8fd55d50ab284a30c016a5be953d0 upstream.
Commit b2787845fb91 ("V4L/DVB (5289): Add support for video output overlays.") added the field global_alpha to struct v4l2_window but did not update the compat layer accordingly. This change adds global_alpha to struct v4l2_window32 and copies the value for global_alpha back and forth.
Signed-off-by: Daniel Mentz danielmentz@google.com Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -46,6 +46,7 @@ struct v4l2_window32 { compat_caddr_t clips; /* actually struct v4l2_clip32 * */ __u32 clipcount; compat_caddr_t bitmap; + __u8 global_alpha; };
static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) @@ -54,7 +55,8 @@ static int get_v4l2_window32(struct v4l2 copy_from_user(&kp->w, &up->w, sizeof(up->w)) || get_user(kp->field, &up->field) || get_user(kp->chromakey, &up->chromakey) || - get_user(kp->clipcount, &up->clipcount)) + get_user(kp->clipcount, &up->clipcount) || + get_user(kp->global_alpha, &up->global_alpha)) return -EFAULT; if (kp->clipcount > 2048) return -EINVAL; @@ -87,7 +89,8 @@ static int put_v4l2_window32(struct v4l2 if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || put_user(kp->field, &up->field) || put_user(kp->chromakey, &up->chromakey) || - put_user(kp->clipcount, &up->clipcount)) + put_user(kp->clipcount, &up->clipcount) || + put_user(kp->global_alpha, &up->global_alpha)) return -EFAULT; return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hverkuil@xs4all.nl
From: Hans Verkuil hans.verkuil@cisco.com
commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream.
If the ioctl returned -ENOTTY, then don't bother copying back the result as there is no point.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 639abeee3392..bae5dd776d82 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -2308,8 +2308,10 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
/* Handles IOCTL */ err = func(file, cmd, parg); - if (err == -ENOIOCTLCMD) - err = -EINVAL; + if (err == -ENOTTY || err == -ENOIOCTLCMD) { + err = -ENOTTY; + goto out; + }
if (has_array_args) { *kernel_ptr = user_ptr;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Steve Wise swise@opengridcomputing.com
commit f55688c45442bc863f40ad678c638785b26cdce6 upstream.
If the RECV CQE is in error, ignore the MSN check. This was causing recvs that were flushed into the sw cq to be completed with the wrong status (BAD_MSN instead of FLUSHED).
Signed-off-by: Steve Wise swise@opengridcomputing.com Signed-off-by: Jason Gunthorpe jgg@mellanox.com [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/infiniband/hw/cxgb4/cq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -484,10 +484,10 @@ static int poll_cq(struct t4_wq *wq, str ret = -EAGAIN; goto skip_cqe; } - if (unlikely((CQE_WRID_MSN(hw_cqe) != (wq->rq.msn)))) { + if (unlikely(!CQE_STATUS(hw_cqe) && + CQE_WRID_MSN(hw_cqe) != wq->rq.msn)) { t4_set_wq_in_error(wq); - hw_cqe->header |= htonl(V_CQE_STATUS(T4_ERR_MSN)); - goto proc_cqe; + hw_cqe->header |= cpu_to_be32(V_CQE_STATUS(T4_ERR_MSN)); } goto proc_cqe; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Ben Hutchings ben@decadent.org.uk
Commit 49e67dd17649 "of: fdt: add missing allocation-failure check" added a "return NULL" statement in __unflatten_device_tree(). When applied to the 3.2-stable branch, this introduced a compiler warning (not an error!) because the function returns void here.
Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -389,7 +389,7 @@ static void __unflatten_device_tree(stru mem = (unsigned long) dt_alloc(size + 4, __alignof__(struct device_node)); if (!mem) - return NULL; + return;
memset((void *)mem, 0, size);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Marc Kleine-Budde mkl@pengutronix.de
commit 8cb68751c115d176ec851ca56ecfbb411568c9e8 upstream.
If an invalid CAN frame is received, from a driver or from a tun interface, a Kernel warning is generated.
This patch replaces the WARN_ONCE by a simple pr_warn_once, so that a kernel, bootet with panic_on_warn, does not panic. A printk seems to be more appropriate here.
Reported-by: syzbot+4386709c0c1284dca827@syzkaller.appspotmail.com Suggested-by: Dmitry Vyukov dvyukov@google.com Acked-by: Oliver Hartkopp socketcan@hartkopp.net Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de [bwh: Backported to 3.2: - Keep using the 'drop' label, as it has another user - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -653,13 +653,13 @@ static int can_rcv(struct sk_buff *skb, if (!net_eq(dev_net(dev), &init_net)) goto drop;
- if (WARN_ONCE(dev->type != ARPHRD_CAN || - skb->len != sizeof(struct can_frame) || - cf->can_dlc > 8, - "PF_CAN: dropped non conform skbuf: " - "dev type %d, len %d, can_dlc %d\n", - dev->type, skb->len, cf->can_dlc)) + if (unlikely(dev->type != ARPHRD_CAN || + skb->len != sizeof(struct can_frame) || + cf->can_dlc > 8)) { + pr_warn_once("PF_CAN: dropped non conform CAN skbuf: dev type %d, len %d, can_dlc %d\n", + dev->type, skb->len, cf->can_dlc); goto drop; + }
/* update statistics */ can_stats.rx_frames++;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Diego Elio Pettenò flameeyes@flameeyes.eu
commit 4307413256ac1e09b8f53e8715af3df9e49beec3 upstream.
Add IDs for the OneTouch Verio IQ that comes with an embedded USB-to-serial converter.
Signed-off-by: Diego Elio Pettenò flameeyes@flameeyes.eu Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -126,6 +126,7 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x10C4, 0x8470) }, /* Juniper Networks BX Series System Console */ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0x84B6) }, /* Starizona Hyperion */ + { USB_DEVICE(0x10C4, 0x85A7) }, /* LifeScan OneTouch Verio IQ */ { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */ { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */ { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Andrzej Hajda a.hajda@samsung.com
commit 655e9780ab913a3a06d4a164d55e3b755524186d upstream.
Alignment/padding rules on AMD64 and ARM64 differs. To allow properly match compatible ioctls on ARM64 kernels without breaking AMD64 some fields should be aligned using compat_s64 type and in one case struct should be unpacked.
Signed-off-by: Andrzej Hajda a.hajda@samsung.com [hans.verkuil@cisco.com: use compat_u64 instead of compat_s64 in v4l2_input32] Signed-off-by: Hans Verkuil hans.verkuil@cisco.com
Signed-off-by: Mauro Carvalho Chehab mchehab@osg.samsung.com [bwh: Backported to 3.2: adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -274,7 +274,7 @@ static int put_v4l2_create32(struct v4l2
struct v4l2_standard32 { __u32 index; - __u32 id[2]; /* __u64 would get the alignment wrong */ + compat_u64 id; __u8 name[24]; struct v4l2_fract frameperiod; /* Frames, not fields */ __u32 framelines; @@ -294,7 +294,7 @@ static int put_v4l2_standard32(struct v4 { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || put_user(kp->index, &up->index) || - copy_to_user(up->id, &kp->id, sizeof(__u64)) || + put_user(kp->id, &up->id) || copy_to_user(up->name, kp->name, 24) || copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || put_user(kp->framelines, &up->framelines) || @@ -569,10 +569,10 @@ struct v4l2_input32 { __u32 type; /* Type of input */ __u32 audioset; /* Associated audios (bitfield) */ __u32 tuner; /* Associated tuner */ - v4l2_std_id std; + compat_u64 std; __u32 status; __u32 reserved[4]; -} __attribute__ ((packed)); +};
/* The 64-bit v4l2_input struct has extra padding at the end of the struct. Otherwise it is identical to the 32-bit version. */ @@ -720,6 +720,7 @@ static int put_v4l2_ext_controls32(struc struct v4l2_event32 { __u32 type; union { + compat_s64 value64; __u8 data[64]; } u; __u32 pending;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg johannes.berg@intel.com
commit 5762d7d3eda25c03cc2d9d45227be3f5ab6bec9e upstream.
Fix two places where the structure isn't initialized to zero, and thus can't be filled properly by the driver.
Fixes: 4a4b8169501b ("cfg80211: Accept multiple RSSI thresholds for CQM") Fixes: 9930380f0bd8 ("cfg80211: implement IWRATE") Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: - Drop change in cfg80211_cqm_rssi_update() - Adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1265,8 +1265,7 @@ static int cfg80211_wext_giwrate(struct { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - /* we are under RTNL - globally locked - so can use a static struct */ - static struct station_info sinfo; + struct station_info sinfo = {}; u8 addr[ETH_ALEN]; int err;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long lucien.xin@gmail.com
commit a0ff660058b88d12625a783ce9e5c1371c87951f upstream.
After commit cea0cc80a677 ("sctp: use the right sk after waking up from wait_buf sleep"), it may change to lock another sk if the asoc has been peeled off in sctp_wait_for_sndbuf.
However, the asoc's new sk could be already closed elsewhere, as it's in the sendmsg context of the old sk that can't avoid the new sk's closing. If the sk's last one refcnt is held by this asoc, later on after putting this asoc, the new sk will be freed, while under it's own lock.
This patch is to revert that commit, but fix the old issue by returning error under the old sk's lock.
Fixes: cea0cc80a677 ("sctp: use the right sk after waking up from wait_buf sleep") Reported-by: syzbot+ac6ea7baa4432811eb50@syzkaller.appspotmail.com Signed-off-by: Xin Long lucien.xin@gmail.com Acked-by: Neil Horman nhorman@tuxdriver.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/sctp/socket.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
--- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -94,7 +94,7 @@ static int sctp_writeable(struct sock *sk); static void sctp_wfree(struct sk_buff *skb); static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, - size_t msg_len, struct sock **orig_sk); + size_t msg_len); static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p); static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); @@ -1912,7 +1912,7 @@ SCTP_STATIC int sctp_sendmsg(struct kioc timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); if (!sctp_wspace(asoc)) { /* sk can be changed by peel off when waiting for buf. */ - err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len, &sk); + err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); if (err) goto out_free; } @@ -6465,12 +6465,12 @@ void sctp_sock_rfree(struct sk_buff *skb
/* Helper function to wait for space in the sndbuf. */ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, - size_t msg_len, struct sock **orig_sk) + size_t msg_len) { struct sock *sk = asoc->base.sk; - int err = 0; long current_timeo = *timeo_p; DEFINE_WAIT(wait); + int err = 0;
SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%zu\n", asoc, (long)(*timeo_p), msg_len); @@ -6498,17 +6498,13 @@ static int sctp_wait_for_sndbuf(struct s sctp_release_sock(sk); current_timeo = schedule_timeout(current_timeo); sctp_lock_sock(sk); - if (sk != asoc->base.sk) { - release_sock(sk); - sk = asoc->base.sk; - lock_sock(sk); - } + if (sk != asoc->base.sk) + goto do_error;
*timeo_p = current_timeo; }
out: - *orig_sk = sk; finish_wait(&asoc->wait, &wait);
/* Release the association's refcnt. */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Cong Wang xiyou.wangcong@gmail.com
commit 78bbb15f2239bc8e663aa20bbe1987c91a0b75f6 upstream.
A vlan device with vid 0 is allow to creat by not able to be fully cleaned up by unregister_vlan_dev() which checks for vlan_id!=0.
Also, VLAN 0 is probably not a valid number and it is kinda "reserved" for HW accelerating devices, but it is probably too late to reject it from creation even if makes sense. Instead, just remove the check in unregister_vlan_dev().
Reported-by: Dmitry Vyukov dvyukov@google.com Fixes: ad1afb003939 ("vlan_dev: VLAN 0 should be treated as "no vlan tag" (802.1p packet)") Cc: Vlad Yasevich vyasevich@gmail.com Cc: Ben Hutchings ben.hutchings@codethink.co.uk Signed-off-by: Cong Wang xiyou.wangcong@gmail.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: The vlan driver didn't leak memory itself, but might cause underlying drivers to leak resources for VID 0. Keep the check for hardware acceleration.] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/8021q/vlan.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
--- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -132,11 +132,7 @@ void unregister_vlan_dev(struct net_devi call_rcu(&grp->rcu, vlan_rcu_free); }
- /* Take it out of our own structures, but be sure to interlock with - * HW accelerating devices or SW vlan input packet processing if - * VLAN is not 0 (leave it there for 802.1p). - */ - if (vlan_id && (real_dev->features & NETIF_F_HW_VLAN_FILTER)) + if (real_dev->features & NETIF_F_HW_VLAN_FILTER) ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id);
/* Get rid of the vlan's reference to real_dev */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Guillaume Nault g.nault@alphalink.fr
commit 02612bb05e51df8489db5e94d0cf8d1c81f87b0c upstream.
In pppoe_sendmsg(), reserving dev->hard_header_len bytes of headroom was probably fine before the introduction of ->needed_headroom in commit f5184d267c1a ("net: Allow netdevices to specify needed head/tailroom").
But now, virtual devices typically advertise the size of their overhead in dev->needed_headroom, so we must also take it into account in skb_reserve(). Allocation size of skb is also updated to take dev->needed_tailroom into account and replace the arbitrary 32 bytes with the real size of a PPPoE header.
This issue was discovered by syzbot, who connected a pppoe socket to a gre device which had dev->header_ops->create == ipgre_header and dev->hard_header_len == 0. Therefore, PPPoE didn't reserve any headroom, and dev_hard_header() crashed when ipgre_header() tried to prepend its header to skb->data.
skbuff: skb_under_panic: text:000000001d390b3a len:31 put:24 head:00000000d8ed776f data:000000008150e823 tail:0x7 end:0xc0 dev:gre0 ------------[ cut here ]------------ kernel BUG at net/core/skbuff.c:104! invalid opcode: 0000 [#1] SMP KASAN Dumping ftrace buffer: (ftrace buffer empty) Modules linked in: CPU: 1 PID: 3670 Comm: syzkaller801466 Not tainted 4.15.0-rc7-next-20180115+ #97 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:skb_panic+0x162/0x1f0 net/core/skbuff.c:100 RSP: 0018:ffff8801d9bd7840 EFLAGS: 00010282 RAX: 0000000000000083 RBX: ffff8801d4f083c0 RCX: 0000000000000000 RDX: 0000000000000083 RSI: 1ffff1003b37ae92 RDI: ffffed003b37aefc RBP: ffff8801d9bd78a8 R08: 1ffff1003b37ae8a R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: ffffffff86200de0 R13: ffffffff84a981ad R14: 0000000000000018 R15: ffff8801d2d34180 FS: 00000000019c4880(0000) GS:ffff8801db300000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000208bc000 CR3: 00000001d9111001 CR4: 00000000001606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: skb_under_panic net/core/skbuff.c:114 [inline] skb_push+0xce/0xf0 net/core/skbuff.c:1714 ipgre_header+0x6d/0x4e0 net/ipv4/ip_gre.c:879 dev_hard_header include/linux/netdevice.h:2723 [inline] pppoe_sendmsg+0x58e/0x8b0 drivers/net/ppp/pppoe.c:890 sock_sendmsg_nosec net/socket.c:630 [inline] sock_sendmsg+0xca/0x110 net/socket.c:640 sock_write_iter+0x31a/0x5d0 net/socket.c:909 call_write_iter include/linux/fs.h:1775 [inline] do_iter_readv_writev+0x525/0x7f0 fs/read_write.c:653 do_iter_write+0x154/0x540 fs/read_write.c:932 vfs_writev+0x18a/0x340 fs/read_write.c:977 do_writev+0xfc/0x2a0 fs/read_write.c:1012 SYSC_writev fs/read_write.c:1085 [inline] SyS_writev+0x27/0x30 fs/read_write.c:1082 entry_SYSCALL_64_fastpath+0x29/0xa0
Admittedly PPPoE shouldn't be allowed to run on non Ethernet-like interfaces, but reserving space for ->needed_headroom is a more fundamental issue that needs to be addressed first.
Same problem exists for __pppoe_xmit(), which also needs to take dev->needed_headroom into account in skb_cow_head().
Fixes: f5184d267c1a ("net: Allow netdevices to specify needed head/tailroom") Reported-by: syzbot+ed0838d0fa4c4f2b528e20286e6dc63effc7c14d@syzkaller.appspotmail.com Signed-off-by: Guillaume Nault g.nault@alphalink.fr Reviewed-by: Xin Long lucien.xin@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/net/ppp/pppoe.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
--- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -838,6 +838,7 @@ static int pppoe_sendmsg(struct kiocb *i struct pppoe_hdr *ph; struct net_device *dev; char *start; + int hlen;
lock_sock(sk); if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) { @@ -856,16 +857,16 @@ static int pppoe_sendmsg(struct kiocb *i if (total_len > (dev->mtu + dev->hard_header_len)) goto end;
- - skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32, - 0, GFP_KERNEL); + hlen = LL_RESERVED_SPACE(dev); + skb = sock_wmalloc(sk, hlen + sizeof(*ph) + total_len + + dev->needed_tailroom, 0, GFP_KERNEL); if (!skb) { error = -ENOMEM; goto end; }
/* Reserve space for headers. */ - skb_reserve(skb, dev->hard_header_len); + skb_reserve(skb, hlen); skb_reset_network_header(skb);
skb->dev = dev; @@ -926,7 +927,7 @@ static int __pppoe_xmit(struct sock *sk, /* Copy the data if there is no space for the header or if it's * read-only. */ - if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len)) + if (skb_cow_head(skb, LL_RESERVED_SPACE(dev) + sizeof(*ph))) goto abort;
__skb_push(skb, sizeof(*ph));
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 898dfe4687f460ba337a01c11549f87269a13fa2 upstream.
The aloop driver tries to update the hw constraints of the connected target on the cable of the opened PCM substream. This is done by adding the extra hw constraints rules referring to the substream runtime->hw fields, while the other substream may update the runtime hw of another side on the fly.
This is, however, racy and may result in the inconsistent values when both PCM streams perform the prepare concurrently. One of the reason is that it overwrites the other's runtime->hw field; which is not only racy but also broken when it's called before the open of another side finishes. And, since the reference to runtime->hw isn't protected, the concurrent write may give the partial value update and become inconsistent.
This patch is an attempt to fix and clean up: - The prepare doesn't change the runtime->hw of other side any longer, but only update the cable->hw that is referred commonly. - The extra rules refer to the loopback_pcm object instead of the runtime->hw. The actual hw is deduced from cable->hw. - The extra rules take the cable_lock to protect against the race.
Fixes: b1c73fc8e697 ("ALSA: snd-aloop: Fix hw_params restrictions and checking") Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/drivers/aloop.c | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-)
--- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -308,19 +308,6 @@ static int loopback_trigger(struct snd_p return 0; }
-static void params_change_substream(struct loopback_pcm *dpcm, - struct snd_pcm_runtime *runtime) -{ - struct snd_pcm_runtime *dst_runtime; - - if (dpcm == NULL || dpcm->substream == NULL) - return; - dst_runtime = dpcm->substream->runtime; - if (dst_runtime == NULL) - return; - dst_runtime->hw = dpcm->cable->hw; -} - static void params_change(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -332,10 +319,6 @@ static void params_change(struct snd_pcm cable->hw.rate_max = runtime->rate; cable->hw.channels_min = runtime->channels; cable->hw.channels_max = runtime->channels; - params_change_substream(cable->streams[SNDRV_PCM_STREAM_PLAYBACK], - runtime); - params_change_substream(cable->streams[SNDRV_PCM_STREAM_CAPTURE], - runtime); }
static int loopback_prepare(struct snd_pcm_substream *substream) @@ -611,24 +594,29 @@ static unsigned int get_cable_index(stru static int rule_format(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { - - struct snd_pcm_hardware *hw = rule->private; + struct loopback_pcm *dpcm = rule->private; + struct loopback_cable *cable = dpcm->cable; struct snd_mask m;
snd_mask_none(&m); - m.bits[0] = (u_int32_t)hw->formats; - m.bits[1] = (u_int32_t)(hw->formats >> 32); + mutex_lock(&dpcm->loopback->cable_lock); + m.bits[0] = (u_int32_t)cable->hw.formats; + m.bits[1] = (u_int32_t)(cable->hw.formats >> 32); + mutex_unlock(&dpcm->loopback->cable_lock); return snd_mask_refine(hw_param_mask(params, rule->var), &m); }
static int rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { - struct snd_pcm_hardware *hw = rule->private; + struct loopback_pcm *dpcm = rule->private; + struct loopback_cable *cable = dpcm->cable; struct snd_interval t;
- t.min = hw->rate_min; - t.max = hw->rate_max; + mutex_lock(&dpcm->loopback->cable_lock); + t.min = cable->hw.rate_min; + t.max = cable->hw.rate_max; + mutex_unlock(&dpcm->loopback->cable_lock); t.openmin = t.openmax = 0; t.integer = 0; return snd_interval_refine(hw_param_interval(params, rule->var), &t); @@ -637,11 +625,14 @@ static int rule_rate(struct snd_pcm_hw_p static int rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { - struct snd_pcm_hardware *hw = rule->private; + struct loopback_pcm *dpcm = rule->private; + struct loopback_cable *cable = dpcm->cable; struct snd_interval t;
- t.min = hw->channels_min; - t.max = hw->channels_max; + mutex_lock(&dpcm->loopback->cable_lock); + t.min = cable->hw.channels_min; + t.max = cable->hw.channels_max; + mutex_unlock(&dpcm->loopback->cable_lock); t.openmin = t.openmax = 0; t.integer = 0; return snd_interval_refine(hw_param_interval(params, rule->var), &t); @@ -708,19 +699,19 @@ static int loopback_open(struct snd_pcm_ /* are cached -> they do not reflect the actual state */ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, - rule_format, &runtime->hw, + rule_format, dpcm, SNDRV_PCM_HW_PARAM_FORMAT, -1); if (err < 0) goto unlock; err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - rule_rate, &runtime->hw, + rule_rate, dpcm, SNDRV_PCM_HW_PARAM_RATE, -1); if (err < 0) goto unlock; err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - rule_channels, &runtime->hw, + rule_channels, dpcm, SNDRV_PCM_HW_PARAM_CHANNELS, -1); if (err < 0) goto unlock;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long lucien.xin@gmail.com
commit cea0cc80a6777beb6eb643d4ad53690e1ad1d4ff upstream.
Commit dfcb9f4f99f1 ("sctp: deny peeloff operation on asocs with threads sleeping on it") fixed the race between peeloff and wait sndbuf by checking waitqueue_active(&asoc->wait) in sctp_do_peeloff().
But it actually doesn't work, as even if waitqueue_active returns false the waiting sndbuf thread may still not yet hold sk lock. After asoc is peeled off, sk is not asoc->base.sk any more, then to hold the old sk lock couldn't make assoc safe to access.
This patch is to fix this by changing to hold the new sk lock if sk is not asoc->base.sk, meanwhile, also set the sk in sctp_sendmsg with the new sk.
With this fix, there is no more race between peeloff and waitbuf, the check 'waitqueue_active' in sctp_do_peeloff can be removed.
Thanks Marcelo and Neil for making this clear.
v1->v2: fix it by changing to lock the new sock instead of adding a flag in asoc.
Suggested-by: Neil Horman nhorman@tuxdriver.com Signed-off-by: Xin Long lucien.xin@gmail.com Acked-by: Neil Horman nhorman@tuxdriver.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/sctp/socket.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
--- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -93,8 +93,8 @@ /* Forward declarations for internal helper functions. */ static int sctp_writeable(struct sock *sk); static void sctp_wfree(struct sk_buff *skb); -static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p, - size_t msg_len); +static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, + size_t msg_len, struct sock **orig_sk); static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p); static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); @@ -1911,7 +1911,8 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); if (!sctp_wspace(asoc)) { - err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); + /* sk can be changed by peel off when waiting for buf. */ + err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len, &sk); if (err) goto out_free; } @@ -4247,12 +4248,6 @@ SCTP_STATIC int sctp_do_peeloff(struct s if (!net_eq(current->nsproxy->net_ns, sock_net(sk))) return -EINVAL;
- /* If there is a thread waiting on more sndbuf space for - * sending on this asoc, it cannot be peeled. - */ - if (waitqueue_active(&asoc->wait)) - return -EBUSY; - /* An association cannot be branched off from an already peeled-off * socket, nor is this supported for tcp style sockets. */ @@ -6470,7 +6465,7 @@ void sctp_sock_rfree(struct sk_buff *skb
/* Helper function to wait for space in the sndbuf. */ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, - size_t msg_len) + size_t msg_len, struct sock **orig_sk) { struct sock *sk = asoc->base.sk; int err = 0; @@ -6503,11 +6498,17 @@ static int sctp_wait_for_sndbuf(struct s sctp_release_sock(sk); current_timeo = schedule_timeout(current_timeo); sctp_lock_sock(sk); + if (sk != asoc->base.sk) { + release_sock(sk); + sk = asoc->base.sk; + lock_sock(sk); + }
*timeo_p = current_timeo; }
out: + *orig_sk = sk; finish_wait(&asoc->wait, &wait);
/* Release the association's refcnt. */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream.
The result of the VIDIOC_PREPARE_BUF ioctl was never copied back to userspace since it was missing in the switch.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -933,6 +933,7 @@ static long do_video_ioctl(struct file * err = put_v4l2_create32(&karg.v2crt, up); break;
+ case VIDIOC_PREPARE_BUF: case VIDIOC_QUERYBUF: case VIDIOC_QBUF: case VIDIOC_DQBUF:
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Sergei Shtylyov sergei.shtylyov@cogentembedded.com
commit f9a531d6731d74f1e24298d9641c2dc1fef2631b upstream.
After the Ether platform data is fixed, the driver probe() method would still fail since the 'struct sh_eth_cpu_data' corresponding to SH771x indicates the presence of TSU but the memory resource for it is absent. Add the missing TSU resource to both Ether devices and fix the harmless off-by-one error in the main memory resources, while at it...
Fixes: 4986b996882d ("net: sh_eth: remove the SH_TSU_ADDR") Signed-off-by: Sergei Shtylyov sergei.shtylyov@cogentembedded.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- arch/sh/boards/mach-se/770x/setup.c | 14 ++++++++++++-- arch/sh/include/mach-se/mach/se.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-)
--- a/arch/sh/boards/mach-se/770x/setup.c +++ b/arch/sh/boards/mach-se/770x/setup.c @@ -123,10 +123,15 @@ static struct sh_eth_plat_data sh_eth_pl static struct resource sh_eth0_resources[] = { [0] = { .start = SH_ETH0_BASE, - .end = SH_ETH0_BASE + 0x1B8, + .end = SH_ETH0_BASE + 0x1B8 - 1, .flags = IORESOURCE_MEM, }, [1] = { + .start = SH_TSU_BASE, + .end = SH_TSU_BASE + 0x200 - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { .start = SH_ETH0_IRQ, .end = SH_ETH0_IRQ, .flags = IORESOURCE_IRQ, @@ -146,10 +151,15 @@ static struct platform_device sh_eth0_de static struct resource sh_eth1_resources[] = { [0] = { .start = SH_ETH1_BASE, - .end = SH_ETH1_BASE + 0x1B8, + .end = SH_ETH1_BASE + 0x1B8 - 1, .flags = IORESOURCE_MEM, }, [1] = { + .start = SH_TSU_BASE, + .end = SH_TSU_BASE + 0x200 - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { .start = SH_ETH1_IRQ, .end = SH_ETH1_IRQ, .flags = IORESOURCE_IRQ, --- a/arch/sh/include/mach-se/mach/se.h +++ b/arch/sh/include/mach-se/mach/se.h @@ -98,6 +98,7 @@ /* Base address */ #define SH_ETH0_BASE 0xA7000000 #define SH_ETH1_BASE 0xA7000400 +#define SH_TSU_BASE 0xA7000800 /* PHY ID */ #if defined(CONFIG_CPU_SUBTYPE_SH7710) # define PHY_ID 0x00
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 29159a4ed7044c52e3e2cf1a9fb55cec4745c60b upstream.
The loops for read and write in PCM OSS emulation have no proper check of pending signals, and they keep processing even after user tries to break. This results in a very long delay, often seen as RCU stall when a huge unprocessed bytes remain queued. The bug could be easily triggered by syzkaller.
As a simple workaround, this patch adds the proper check of pending signals and aborts the loop appropriately.
Reported-by: syzbot+993cb4cfcbbff3947c21@syzkaller.appspotmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/oss/pcm_oss.c | 8 ++++++++ 1 file changed, 8 insertions(+)
--- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1422,6 +1422,10 @@ static ssize_t snd_pcm_oss_write1(struct tmp != runtime->oss.period_bytes) break; } + if (signal_pending(current)) { + tmp = -ERESTARTSYS; + goto err; + } } mutex_unlock(&runtime->oss.params_lock); return xfer; @@ -1507,6 +1511,10 @@ static ssize_t snd_pcm_oss_read1(struct bytes -= tmp; xfer += tmp; } + if (signal_pending(current)) { + tmp = -ERESTARTSYS; + goto err; + } } mutex_unlock(&runtime->oss.params_lock); return xfer;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu herbert@gondor.apana.org.au
commit d16b46e4fd8bc6063624605f25b8c0835bb1fbe3 upstream.
We do not need locking in xfrm_trans_queue because it is designed to use per-CPU buffers. However, the original code incorrectly used skb_queue_tail which takes the lock. This patch switches it to __skb_queue_tail instead.
Reported-and-tested-by: Artem Savkov asavkov@redhat.com Fixes: acf568ee859f ("xfrm: Reinject transport-mode packets...") Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/xfrm/xfrm_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -324,7 +324,7 @@ int xfrm_trans_queue(struct sk_buff *skb return -ENOBUFS;
XFRM_TRANS_SKB_CB(skb)->finish = finish; - skb_queue_tail(&trans->queue, skb); + __skb_queue_tail(&trans->queue, skb); tasklet_schedule(&trans->tasklet); return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream.
The struct v4l2_plane32 should set m.userptr as well. The same happens in v4l2_buffer32 and v4l2-compliance tests for this.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -296,16 +296,20 @@ static int get_v4l2_plane32(struct v4l2_ sizeof(up->data_offset))) return -EFAULT;
- if (memory == V4L2_MEMORY_USERPTR) { + switch (memory) { + case V4L2_MEMORY_MMAP: + case V4L2_MEMORY_OVERLAY: + if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, + sizeof(up32->m.mem_offset))) + return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: if (get_user(p, &up32->m.userptr)) return -EFAULT; up_pln = compat_ptr(p); if (put_user((unsigned long)up_pln, &up->m.userptr)) return -EFAULT; - } else { - if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, - sizeof(up32->m.mem_offset))) - return -EFAULT; + break; }
return 0; @@ -314,17 +318,27 @@ static int get_v4l2_plane32(struct v4l2_ static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, enum v4l2_memory memory) { + unsigned long p; + if (copy_in_user(up32, up, 2 * sizeof(__u32)) || copy_in_user(&up32->data_offset, &up->data_offset, sizeof(up->data_offset))) return -EFAULT;
- /* For MMAP, driver might've set up the offset, so copy it back. - * USERPTR stays the same (was userspace-provided), so no copying. */ - if (memory == V4L2_MEMORY_MMAP) + switch (memory) { + case V4L2_MEMORY_MMAP: + case V4L2_MEMORY_OVERLAY: if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, sizeof(up->m.mem_offset))) return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: + if (get_user(p, &up->m.userptr) || + put_user((compat_ulong_t)ptr_to_compat((__force void *)p), + &up32->m.userptr)) + return -EFAULT; + break; + }
return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Neukum oneukum@suse.com
commit b9096d9f15c142574ebebe8fbb137012bb9d99c2 upstream.
This modem needs this quirk to operate. It produces timeouts when resumed without reset.
Signed-off-by: Oliver Neukum oneukum@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/core/quirks.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -128,6 +128,9 @@ static const struct usb_device_id usb_qu /* appletouch */ { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* ELSA MicroLink 56K */ + { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Avision AV600U */ { USB_DEVICE(0x0638, 0x0a13), .driver_info = USB_QUIRK_STRING_FETCH_255 },
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@google.com
commit 4e765b4972af7b07adcb1feb16e7a525ce1f6b28 upstream.
If a message sent to a PF_KEY socket ended with an incomplete extension header (fewer than 4 bytes remaining), then parse_exthdrs() read past the end of the message, into uninitialized memory. Fix it by returning -EINVAL in this case.
Reproducer:
#include <linux/pfkeyv2.h> #include <sys/socket.h> #include <unistd.h>
int main() { int sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); char buf[17] = { 0 }; struct sadb_msg *msg = (void *)buf;
msg->sadb_msg_version = PF_KEY_V2; msg->sadb_msg_type = SADB_DELETE; msg->sadb_msg_len = 2;
write(sock, buf, 17); }
Signed-off-by: Eric Biggers ebiggers@google.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/key/af_key.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -513,6 +513,9 @@ static int parse_exthdrs(struct sk_buff uint16_t ext_type; int ext_len;
+ if (len < sizeof(*ehdr)) + return -EINVAL; + ext_len = ehdr->sadb_ext_len; ext_len *= sizeof(uint64_t); ext_type = ehdr->sadb_ext_type;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@google.com
commit 06b335cb51af018d5feeff5dd4fd53847ddb675a upstream.
If a message sent to a PF_KEY socket ended with one of the extensions that takes a 'struct sadb_address' but there were not enough bytes remaining in the message for the ->sa_family member of the 'struct sockaddr' which is supposed to follow, then verify_address_len() read past the end of the message, into uninitialized memory. Fix it by returning -EINVAL in this case.
This bug was found using syzkaller with KMSAN.
Reproducer:
#include <linux/pfkeyv2.h> #include <sys/socket.h> #include <unistd.h>
int main() { int sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); char buf[24] = { 0 }; struct sadb_msg *msg = (void *)buf; struct sadb_address *addr = (void *)(msg + 1);
msg->sadb_msg_version = PF_KEY_V2; msg->sadb_msg_type = SADB_DELETE; msg->sadb_msg_len = 3; addr->sadb_address_len = 1; addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
write(sock, buf, 24); }
Reported-by: Alexander Potapenko glider@google.com Signed-off-by: Eric Biggers ebiggers@google.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/key/af_key.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -398,6 +398,11 @@ static int verify_address_len(const void #endif int len;
+ if (sp->sadb_address_len < + DIV_ROUND_UP(sizeof(*sp) + offsetofend(typeof(*addr), sa_family), + sizeof(uint64_t))) + return -EINVAL; + switch (addr->sa_family) { case AF_INET: len = DIV_ROUND_UP(sizeof(*sp) + sizeof(*sin), sizeof(uint64_t));
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit fe08f34d066f4404934a509b6806db1a4f700c86 upstream.
syzkaller triggered kernel warnings through PCM OSS emulation at closing a stream: WARNING: CPU: 0 PID: 3502 at sound/core/pcm_lib.c:1635 snd_pcm_hw_param_first+0x289/0x690 sound/core/pcm_lib.c:1635 Call Trace: .... snd_pcm_hw_param_near.constprop.27+0x78d/0x9a0 sound/core/oss/pcm_oss.c:457 snd_pcm_oss_change_params+0x17d3/0x3720 sound/core/oss/pcm_oss.c:969 snd_pcm_oss_make_ready+0xaa/0x130 sound/core/oss/pcm_oss.c:1128 snd_pcm_oss_sync+0x257/0x830 sound/core/oss/pcm_oss.c:1638 snd_pcm_oss_release+0x20b/0x280 sound/core/oss/pcm_oss.c:2431 __fput+0x327/0x7e0 fs/file_table.c:210 ....
This happens while it tries to open and set up the aloop device concurrently. The warning above (invoked from snd_BUG_ON() macro) is to detect the unexpected logical error where snd_pcm_hw_refine() call shouldn't fail. The theory is true for the case where the hw_params config rules are static. But for an aloop device, the hw_params rule condition does vary dynamically depending on the connected target; when another device is opened and changes the parameters, the device connected in another side is also affected, and it caused the error from snd_pcm_hw_refine().
That is, the simplest "solution" for this is to remove the incorrect assumption of static rules, and treat such an error as a normal error path. As there are a couple of other places using snd_BUG_ON() incorrectly, this patch removes these spurious snd_BUG_ON() calls.
Reported-by: syzbot+6f11c7e2a1b91d466432@syzkaller.appspotmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/oss/pcm_oss.c | 1 - sound/core/pcm_lib.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-)
--- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -465,7 +465,6 @@ static int snd_pcm_hw_param_near(struct v = snd_pcm_hw_param_last(pcm, params, var, dir); else v = snd_pcm_hw_param_first(pcm, params, var, dir); - snd_BUG_ON(v < 0); return v; }
--- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1546,7 +1546,7 @@ int snd_pcm_hw_param_first(struct snd_pc return changed; if (params->rmask) { int err = snd_pcm_hw_refine(pcm, params); - if (snd_BUG_ON(err < 0)) + if (err < 0) return err; } return snd_pcm_hw_param_value(params, var, dir); @@ -1592,7 +1592,7 @@ int snd_pcm_hw_param_last(struct snd_pcm return changed; if (params->rmask) { int err = snd_pcm_hw_refine(pcm, params); - if (snd_BUG_ON(err < 0)) + if (err < 0) return err; } return snd_pcm_hw_param_value(params, var, dir);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
commit 43cdd1b716b26f6af16da4e145b6578f98798bf6 upstream.
There's no need to be printing a raw kernel pointer to the kernel log at every boot. So just remove it, and change the whole message to use the correct dev_info() call at the same time.
Reported-by: Wang Qize wang_qize@venustech.com.cn Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/acpi/sbshc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -288,8 +288,8 @@ static int acpi_smbus_hc_add(struct acpi device->driver_data = hc;
acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); - printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", - hc->ec, hc->offset, hc->query_bit); + dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n", + hc->offset, hc->query_bit);
return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 6708913750344a900f2e73bfe4a4d6dbbce4fe8d upstream.
In the OSS emulation plugin builder where the frame size is parsed in the plugin chain, some places miss the possible errors returned from the plugin src_ or dst_frames callback.
This patch papers over such places.
Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/oss/pcm_plugin.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
--- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -589,18 +589,26 @@ snd_pcm_sframes_t snd_pcm_plug_write_tra snd_pcm_sframes_t frames = size;
plugin = snd_pcm_plug_first(plug); - while (plugin && frames > 0) { + while (plugin) { + if (frames <= 0) + return frames; if ((next = plugin->next) != NULL) { snd_pcm_sframes_t frames1 = frames; - if (plugin->dst_frames) + if (plugin->dst_frames) { frames1 = plugin->dst_frames(plugin, frames); + if (frames1 <= 0) + return frames1; + } if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) { return err; } if (err != frames1) { frames = err; - if (plugin->src_frames) + if (plugin->src_frames) { frames = plugin->src_frames(plugin, frames1); + if (frames <= 0) + return frames; + } } } else dst_channels = NULL;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Guennadi Liakhovetski g.liakhovetski@gmx.de
commit 6ed9b28504326f8cf542e6b68245b2f7ce009216 upstream.
Similar to an earlier patch, fixing reading user-space data for the VIDIOC_CREATE_BUFS ioctl() in 32-bit compatibility mode, this patch fixes writing back of the possibly modified struct to the user. However, unlike the former bug, this one is much less harmful, because it only results in the kernel failing to write the .type field back to the user, but in fact this is likely unneeded, because the kernel will hardly want to change that field. Therefore this bug is more of a theoretical nature.
Signed-off-by: Guennadi Liakhovetski g.liakhovetski@gmx.de Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Mauro Carvalho Chehab mchehab@osg.samsung.com [bwh: Backported to 3.2: adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -226,6 +226,9 @@ static int get_v4l2_create32(struct v4l2
static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) { + if (put_user(kp->type, &up->type)) + return -EFAULT; + switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: @@ -256,8 +259,7 @@ static int __put_v4l2_format32(struct v4
static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) || - put_user(kp->type, &up->type)) + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32))) return -EFAULT; return __put_v4l2_format32(kp, up); } @@ -265,8 +267,8 @@ static int put_v4l2_format32(struct v4l2 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || - copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt))) - return -EFAULT; + copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format))) + return -EFAULT; return __put_v4l2_format32(&kp->format, &up->format); }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit d83a8243aaefe62ace433e4384a4f077bed86acb upstream.
Some ioctls need to copy back the result even if the ioctl returned an error. However, don't do this for the error code -ENOTTY. It makes no sense in that cases.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -885,6 +885,9 @@ static long do_video_ioctl(struct file * set_fs(old_fs); }
+ if (err == -ENOTTY) + return err; + /* Special case: even after an error we need to put the results back for these ioctls since the error_idx will contain information on which control failed. */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Li Jinyue lijinyue@huawei.com
commit fbe0e839d1e22d88810f3ee3e2f1479be4c0aa4a upstream.
UBSAN reports signed integer overflow in kernel/futex.c:
UBSAN: Undefined behaviour in kernel/futex.c:2041:18 signed integer overflow: 0 - -2147483648 cannot be represented in type 'int'
Add a sanity check to catch negative values of nr_wake and nr_requeue.
Signed-off-by: Li Jinyue lijinyue@huawei.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Cc: peterz@infradead.org Cc: dvhart@infradead.org Link: https://lkml.kernel.org/r/1513242294-31786-1-git-send-email-lijinyue@huawei.... [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- kernel/futex.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/kernel/futex.c +++ b/kernel/futex.c @@ -1376,6 +1376,9 @@ static int futex_requeue(u32 __user *uad struct plist_head *head1; struct futex_q *this, *next;
+ if (nr_wake < 0 || nr_requeue < 0) + return -EINVAL; + if (requeue_pi) { /* * Requeue PI only works on two distinct uaddrs. This
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream.
These helper functions do not really help. Move the code to the __get/put_v4l2_format32 functions.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com [bwh: Rebased on top of some earlier fixes] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -89,64 +89,6 @@ static int put_v4l2_window32(struct v4l2 return 0; }
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) - return -EFAULT; - return 0; -} - -static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, - struct v4l2_pix_format_mplane __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane))) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, - struct v4l2_pix_format_mplane __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane))) - return -EFAULT; - return 0; -} - -static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) - return -EFAULT; - return 0; -} - -static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format))) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format))) - return -EFAULT; - return 0; -} - struct v4l2_format32 { enum v4l2_buf_type type; union { @@ -184,20 +126,23 @@ static int __get_v4l2_format32(struct v4 switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); + return copy_from_user(&kp->fmt.pix, &up->fmt.pix, + sizeof(kp->fmt.pix)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp, - &up->fmt.pix_mp); + return copy_from_user(&kp->fmt.pix_mp, &up->fmt.pix_mp, + sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); + return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); case V4L2_BUF_TYPE_VBI_CAPTURE: case V4L2_BUF_TYPE_VBI_OUTPUT: - return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); + return copy_from_user(&kp->fmt.vbi, &up->fmt.vbi, + sizeof(kp->fmt.vbi)) ? -EFAULT : 0; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); + return copy_from_user(&kp->fmt.sliced, &up->fmt.sliced, + sizeof(kp->fmt.sliced)) ? -EFAULT : 0; case V4L2_BUF_TYPE_PRIVATE: if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data))) return -EFAULT; @@ -232,20 +177,23 @@ static int __put_v4l2_format32(struct v4 switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); + return copy_to_user(&up->fmt.pix, &kp->fmt.pix, + sizeof(kp->fmt.pix)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp, - &up->fmt.pix_mp); + return copy_to_user(&up->fmt.pix_mp, &kp->fmt.pix_mp, + sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); case V4L2_BUF_TYPE_VBI_CAPTURE: case V4L2_BUF_TYPE_VBI_OUTPUT: - return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); + return copy_to_user(&up->fmt.vbi, &kp->fmt.vbi, + sizeof(kp->fmt.vbi)) ? -EFAULT : 0; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); + return copy_to_user(&up->fmt.sliced, &kp->fmt.sliced, + sizeof(kp->fmt.sliced)) ? -EFAULT : 0; case V4L2_BUF_TYPE_PRIVATE: if (copy_to_user(up, kp, sizeof(up->fmt.raw_data))) return -EFAULT; @@ -544,10 +492,10 @@ static int get_v4l2_framebuffer32(struct if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || get_user(tmp, &up->base) || get_user(kp->capability, &up->capability) || - get_user(kp->flags, &up->flags)) + get_user(kp->flags, &up->flags) || + copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt))) return -EFAULT; kp->base = (__force void *)compat_ptr(tmp); - get_v4l2_pix_format(&kp->fmt, &up->fmt); return 0; }
@@ -558,9 +506,9 @@ static int put_v4l2_framebuffer32(struct if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || put_user(tmp, &up->base) || put_user(kp->capability, &up->capability) || - put_user(kp->flags, &up->flags)) + put_user(kp->flags, &up->flags) || + copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt))) return -EFAULT; - put_v4l2_pix_format(&kp->fmt, &up->fmt); return 0; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Aaron Ma aaron.ma@canonical.com
commit f5d07b9e98022d50720e38aa936fc11c67868ece upstream.
Lenovo introduced trackpoint compatible sticks with minimum PS/2 commands. They supposed to reply with 0x02, 0x03, or 0x04 in response to the "Read Extended ID" command, so we would know not to try certain extended commands. Unfortunately even some trackpoints reporting the original IBM version (0x01 firmware 0x0e) now respond with incorrect data to the "Get Extended Buttons" command:
thinkpad_acpi: ThinkPad BIOS R0DET87W (1.87 ), EC unknown thinkpad_acpi: Lenovo ThinkPad E470, model 20H1004SGE
psmouse serio2: trackpoint: IBM TrackPoint firmware: 0x0e, buttons: 0/0
Since there are no trackpoints without buttons, let's assume the trackpoint has 3 buttons when we get 0 response to the extended buttons query.
Signed-off-by: Aaron Ma aaron.ma@canonical.com Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=196253 Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com [bwh: Backported to 3.2: use printk() instead of psmouse_warn()] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/input/mouse/trackpoint.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -300,6 +300,9 @@ int trackpoint_detect(struct psmouse *ps if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { printk(KERN_WARNING "trackpoint.c: failed to get extended button data, assuming 3 buttons\n"); button_info = 0x33; + } else if (!button_info) { + printk(KERN_WARNING "trackpoint.c: got 0 in extended button data, assuming 3 buttons\n"); + button_info = 0x33; }
psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Howells dhowells@redhat.com
commit 98801506552593c9b8ac11021b0cdad12cab4f6b upstream.
Fix the default for fscache_maybe_release_page() for when the cookie isn't valid or the page isn't cached. It mustn't return false as that indicates the page cannot yet be freed.
The problem with the default is that if, say, there's no cache, but a network filesystem's pages are using up almost all the available memory, a system can OOM because the filesystem ->releasepage() op will not allow them to be released as fscache_maybe_release_page() incorrectly prevents it.
This can be tested by writing a sequence of 512MiB files to an AFS mount. It does not affect NFS or CIFS because both of those wrap the call in a check of PG_fscache and it shouldn't bother Ceph as that only has PG_private set whilst writeback is in progress. This might be an issue for 9P, however.
Note that the pages aren't entirely stuck. Removing a file or unmounting will clear things because that uses ->invalidatepage() instead.
Fixes: 201a15428bd5 ("FS-Cache: Handle pages pending storage that get evicted under OOM conditions") Reported-by: Marc Dionne marc.dionne@auristor.com Signed-off-by: David Howells dhowells@redhat.com Reviewed-by: Jeff Layton jlayton@redhat.com Acked-by: Al Viro viro@zeniv.linux.org.uk Tested-by: Marc Dionne marc.dionne@auristor.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- include/linux/fscache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -642,7 +642,7 @@ bool fscache_maybe_release_page(struct f { if (fscache_cookie_valid(cookie) && PageFsCache(page)) return __fscache_maybe_release_page(cookie, page, gfp); - return false; + return true; }
/**
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long lucien.xin@gmail.com
commit c5006b8aa74599ce19104b31d322d2ea9ff887cc upstream.
The check in sctp_sockaddr_af is not robust enough to forbid binding a v4mapped v6 addr on a v4 socket.
The worse thing is that v4 socket's bind_verify would not convert this v4mapped v6 addr to a v4 addr. syzbot even reported a crash as the v4 socket bound a v6 addr.
This patch is to fix it by doing the common sa.sa_family check first, then AF_INET check for v4mapped v6 addrs.
Fixes: 7dab83de50c7 ("sctp: Support ipv6only AF_INET6 sockets.") Reported-by: syzbot+7b7b518b1228d2743963@syzkaller.appspotmail.com Acked-by: Neil Horman nhorman@tuxdriver.com Signed-off-by: Xin Long lucien.xin@gmail.com Acked-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/sctp/socket.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
--- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -314,16 +314,14 @@ static struct sctp_af *sctp_sockaddr_af( if (len < sizeof (struct sockaddr)) return NULL;
+ if (!opt->pf->af_supported(addr->sa.sa_family, opt)) + return NULL; + /* V4 mapped address are really of AF_INET family */ if (addr->sa.sa_family == AF_INET6 && - ipv6_addr_v4mapped(&addr->v6.sin6_addr)) { - if (!opt->pf->af_supported(AF_INET, opt)) - return NULL; - } else { - /* Does this PF support this AF? */ - if (!opt->pf->af_supported(addr->sa.sa_family, opt)) - return NULL; - } + ipv6_addr_v4mapped(&addr->v6.sin6_addr) && + !opt->pf->af_supported(AF_INET, opt)) + return NULL;
/* If we get this far, af is valid. */ af = sctp_get_af_specific(addr->sa.sa_family);
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy christophe.leroy@c-s.fr
commit f8b39039cbf2a15f2b8c9f081e1cbd5dee00aaf5 upstream.
In case of TX timeout, fs_timeout() calls phy_stop(), which triggers the following BUG_ON() as we are in interrupt.
[92708.199889] kernel BUG at drivers/net/phy/mdio_bus.c:482! [92708.204985] Oops: Exception in kernel mode, sig: 5 [#1] [92708.210119] PREEMPT [92708.212107] CMPC885 [92708.214216] CPU: 0 PID: 3 Comm: ksoftirqd/0 Tainted: G W 4.9.61 #39 [92708.223227] task: c60f0a40 task.stack: c6104000 [92708.227697] NIP: c02a84bc LR: c02a947c CTR: c02a93d8 [92708.232614] REGS: c6105c70 TRAP: 0700 Tainted: G W (4.9.61) [92708.241193] MSR: 00021032 <ME,IR,DR,RI>[92708.244818] CR: 24000822 XER: 20000000 [92708.248767] GPR00: c02a947c c6105d20 c60f0a40 c62b4c00 00000005 0000001f c069aad8 0001a688 GPR08: 00000007 00000100 c02a93d8 00000000 000005fc 00000000 c6213240 c06338e4 GPR16: 00000001 c06330d4 c0633094 00000000 c0680000 c6104000 c6104000 00000000 GPR24: 00000200 00000000 ffffffff 00000004 00000078 00009032 00000000 c62b4c00 NIP [c02a84bc] mdiobus_read+0x20/0x74 [92708.281517] LR [c02a947c] kszphy_config_intr+0xa4/0xc4 [92708.286547] Call Trace: [92708.288980] [c6105d20] [c6104000] 0xc6104000 (unreliable) [92708.294339] [c6105d40] [c02a947c] kszphy_config_intr+0xa4/0xc4 [92708.300098] [c6105d50] [c02a5330] phy_stop+0x60/0x9c [92708.305007] [c6105d60] [c02c84d0] fs_timeout+0xdc/0x110 [92708.310197] [c6105d80] [c035cd48] dev_watchdog+0x268/0x2a0 [92708.315593] [c6105db0] [c0060288] call_timer_fn+0x34/0x17c [92708.321014] [c6105dd0] [c00605f0] run_timer_softirq+0x21c/0x2e4 [92708.326887] [c6105e50] [c001e19c] __do_softirq+0xf4/0x2f4 [92708.332207] [c6105eb0] [c001e3c8] run_ksoftirqd+0x2c/0x40 [92708.337560] [c6105ec0] [c003b420] smpboot_thread_fn+0x1f0/0x258 [92708.343405] [c6105ef0] [c003745c] kthread+0xbc/0xd0 [92708.348217] [c6105f40] [c000c400] ret_from_kernel_thread+0x5c/0x64 [92708.354275] Instruction dump: [92708.357207] 7c0803a6 bbc10018 38210020 4e800020 7c0802a6 9421ffe0 54290024 bfc10018 [92708.364865] 90010024 7c7f1b78 81290008 552902ee <0f090000> 3bc3002c 7fc3f378 90810008 [92708.372711] ---[ end trace 42b05441616fafd7 ]---
This patch moves fs_timeout() actions into an async worker.
Fixes: commit 48257c4f168e5 ("Add fs_enet ethernet network driver, for several embedded platforms") Signed-off-by: Christophe Leroy christophe.leroy@c-s.fr Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 16 +++++++++++++--- drivers/net/ethernet/freescale/fs_enet/fs_enet.h | 1 + 2 files changed, 14 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -706,9 +706,11 @@ static int fs_enet_start_xmit(struct sk_ return NETDEV_TX_OK; }
-static void fs_timeout(struct net_device *dev) +static void fs_timeout_work(struct work_struct *work) { - struct fs_enet_private *fep = netdev_priv(dev); + struct fs_enet_private *fep = container_of(work, struct fs_enet_private, + timeout_work); + struct net_device *dev = fep->ndev; unsigned long flags; int wake = 0;
@@ -720,7 +722,6 @@ static void fs_timeout(struct net_device phy_stop(fep->phydev); (*fep->ops->stop)(dev); (*fep->ops->restart)(dev); - phy_start(fep->phydev); }
phy_start(fep->phydev); @@ -731,6 +732,13 @@ static void fs_timeout(struct net_device netif_wake_queue(dev); }
+static void fs_timeout(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + schedule_work(&fep->timeout_work); +} + /*----------------------------------------------------------------------------- * generic link-change handler - should be sufficient for most cases *-----------------------------------------------------------------------------*/ @@ -857,6 +865,7 @@ static int fs_enet_close(struct net_devi netif_carrier_off(dev); if (fep->fpi->use_napi) napi_disable(&fep->napi); + cancel_work_sync(&fep->timeout_work); phy_stop(fep->phydev);
spin_lock_irqsave(&fep->lock, flags); @@ -1080,6 +1089,7 @@ static int __devinit fs_enet_probe(struc
ndev->netdev_ops = &fs_enet_netdev_ops; ndev->watchdog_timeo = 2 * HZ; + INIT_WORK(&fep->timeout_work, fs_timeout_work); if (fpi->use_napi) netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight); --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h @@ -124,6 +124,7 @@ struct fs_enet_private { spinlock_t lock; /* during all ops except TX pckt processing */ spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */ struct fs_platform_info *fpi; + struct work_struct timeout_work; const struct fs_ops *ops; int rx_ring, tx_ring; dma_addr_t ring_mem_addr;
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Håkon Bugge Haakon.Bugge@oracle.com
commit f3069c6d33f6ae63a1668737bc78aaaa51bff7ca upstream.
This is a fix for syzkaller719569, where memory registration was attempted without any underlying transport being loaded.
Analysis of the case reveals that it is the setsockopt() RDS_GET_MR (2) and RDS_GET_MR_FOR_DEST (7) that are vulnerable.
Here is an example stack trace when the bug is hit:
BUG: unable to handle kernel NULL pointer dereference at 00000000000000c0 IP: __rds_rdma_map+0x36/0x440 [rds] PGD 2f93d03067 P4D 2f93d03067 PUD 2f93d02067 PMD 0 Oops: 0000 [#1] SMP Modules linked in: bridge stp llc tun rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache rds binfmt_misc sb_edac intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul c rc32_pclmul ghash_clmulni_intel pcbc aesni_intel crypto_simd glue_helper cryptd iTCO_wdt mei_me sg iTCO_vendor_support ipmi_si mei ipmi_devintf nfsd shpchp pcspkr i2c_i801 ioatd ma ipmi_msghandler wmi lpc_ich mfd_core auth_rpcgss nfs_acl lockd grace sunrpc ip_tables ext4 mbcache jbd2 mgag200 i2c_algo_bit drm_kms_helper ixgbe syscopyarea ahci sysfillrect sysimgblt libahci mdio fb_sys_fops ttm ptp libata sd_mod mlx4_core drm crc32c_intel pps_core megaraid_sas i2c_core dca dm_mirror dm_region_hash dm_log dm_mod CPU: 48 PID: 45787 Comm: repro_set2 Not tainted 4.14.2-3.el7uek.x86_64 #2 Hardware name: Oracle Corporation ORACLE SERVER X5-2L/ASM,MOBO TRAY,2U, BIOS 31110000 03/03/2017 task: ffff882f9190db00 task.stack: ffffc9002b994000 RIP: 0010:__rds_rdma_map+0x36/0x440 [rds] RSP: 0018:ffffc9002b997df0 EFLAGS: 00010202 RAX: 0000000000000000 RBX: ffff882fa2182580 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffc9002b997e40 RDI: ffff882fa2182580 RBP: ffffc9002b997e30 R08: 0000000000000000 R09: 0000000000000002 R10: ffff885fb29e3838 R11: 0000000000000000 R12: ffff882fa2182580 R13: ffff882fa2182580 R14: 0000000000000002 R15: 0000000020000ffc FS: 00007fbffa20b700(0000) GS:ffff882fbfb80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000000c0 CR3: 0000002f98a66006 CR4: 00000000001606e0 Call Trace: rds_get_mr+0x56/0x80 [rds] rds_setsockopt+0x172/0x340 [rds] ? __fget_light+0x25/0x60 ? __fdget+0x13/0x20 SyS_setsockopt+0x80/0xe0 do_syscall_64+0x67/0x1b0 entry_SYSCALL64_slow_path+0x25/0x25 RIP: 0033:0x7fbff9b117f9 RSP: 002b:00007fbffa20aed8 EFLAGS: 00000293 ORIG_RAX: 0000000000000036 RAX: ffffffffffffffda RBX: 00000000000c84a4 RCX: 00007fbff9b117f9 RDX: 0000000000000002 RSI: 0000400000000114 RDI: 000000000000109b RBP: 00007fbffa20af10 R08: 0000000000000020 R09: 00007fbff9dd7860 R10: 0000000020000ffc R11: 0000000000000293 R12: 0000000000000000 R13: 00007fbffa20b9c0 R14: 00007fbffa20b700 R15: 0000000000000021
Code: 41 56 41 55 49 89 fd 41 54 53 48 83 ec 18 8b 87 f0 02 00 00 48 89 55 d0 48 89 4d c8 85 c0 0f 84 2d 03 00 00 48 8b 87 00 03 00 00 <48> 83 b8 c0 00 00 00 00 0f 84 25 03 00 0 0 48 8b 06 48 8b 56 08
The fix is to check the existence of an underlying transport in __rds_rdma_map().
Signed-off-by: Håkon Bugge haakon.bugge@oracle.com Reported-by: syzbot syzkaller@googlegroups.com Acked-by: Santosh Shilimkar santosh.shilimkar@oracle.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/rds/rdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -184,7 +184,7 @@ static int __rds_rdma_map(struct rds_soc long i; int ret;
- if (rs->rs_bound_addr == 0) { + if (rs->rs_bound_addr == 0 || !rs->rs_transport) { ret = -ENOTCONN; /* XXX not a great errno */ goto out; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Kodanev alexey.kodanev@oracle.com
commit dd5684ecae3bd8e44b644f50e2c12c7e57fdfef5 upstream.
ccid2_hc_tx_rto_expire() timer callback always restarts the timer again and can run indefinitely (unless it is stopped outside), and after commit 120e9dabaf55 ("dccp: defer ccid_hc_tx_delete() at dismantle time"), which moved ccid_hc_tx_delete() (also includes sk_stop_timer()) from dccp_destroy_sock() to sk_destruct(), this started to happen quite often. The timer prevents releasing the socket, as a result, sk_destruct() won't be called.
Found with LTP/dccp_ipsec tests running on the bonding device, which later couldn't be unloaded after the tests were completed:
unregister_netdevice: waiting for bond0 to become free. Usage count = 148
Fixes: 2a91aa396739 ("[DCCP] CCID2: Initial CCID2 (TCP-Like) implementation") Signed-off-by: Alexey Kodanev alexey.kodanev@oracle.com Reviewed-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/dccp/ccids/ccid2.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -140,6 +140,9 @@ static void ccid2_hc_tx_rto_expire(unsig
ccid2_pr_debug("RTO_EXPIRE\n");
+ if (sk->sk_state == DCCP_CLOSED) + goto out; + /* back-off timer */ hc->tx_rto <<= 1; if (hc->tx_rto > DCCP_RTO_MAX)
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jeremy Compostella jeremy.compostella@intel.com
commit 89c6efa61f5709327ecfa24bff18e57a4e80c7fa upstream.
On a I2C_SMBUS_I2C_BLOCK_DATA read request, if data->block[0] is greater than I2C_SMBUS_BLOCK_MAX + 1, the underlying I2C driver writes data out of the msgbuf1 array boundary.
It is possible from a user application to run into that issue by calling the I2C_SMBUS ioctl with data.block[0] greater than I2C_SMBUS_BLOCK_MAX + 1.
This patch makes the code compliant with Documentation/i2c/dev-interface by raising an error when the requested size is larger than 32 bytes.
Call Trace: [<ffffffff8139f695>] dump_stack+0x67/0x92 [<ffffffff811802a4>] panic+0xc5/0x1eb [<ffffffff810ecb5f>] ? vprintk_default+0x1f/0x30 [<ffffffff817456d3>] ? i2cdev_ioctl_smbus+0x303/0x320 [<ffffffff8109a68b>] __stack_chk_fail+0x1b/0x20 [<ffffffff817456d3>] i2cdev_ioctl_smbus+0x303/0x320 [<ffffffff81745aed>] i2cdev_ioctl+0x4d/0x1e0 [<ffffffff811f761a>] do_vfs_ioctl+0x2ba/0x490 [<ffffffff81336e43>] ? security_file_ioctl+0x43/0x60 [<ffffffff811f7869>] SyS_ioctl+0x79/0x90 [<ffffffff81a22e97>] entry_SYSCALL_64_fastpath+0x12/0x6a
Signed-off-by: Jeremy Compostella jeremy.compostella@intel.com Signed-off-by: Wolfram Sang wsa@the-dreams.de [bwh: Backported to 3.2: adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/i2c/i2c-core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
--- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -2009,16 +2009,17 @@ static s32 i2c_smbus_xfer_emulated(struc the underlying bus driver */ break; case I2C_SMBUS_I2C_BLOCK_DATA: + if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { + dev_err(&adapter->dev, "Invalid block %s size %d\n", + read_write == I2C_SMBUS_READ ? "read" : "write", + data->block[0]); + return -EINVAL; + } + if (read_write == I2C_SMBUS_READ) { msg[1].len = data->block[0]; } else { msg[0].len = data->block[0] + 1; - if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { - dev_err(&adapter->dev, - "Invalid block write size %d\n", - data->block[0]); - return -EINVAL; - } for (i = 1; i <= data->block[0]; i++) msgbuf0[i] = data->block[i]; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Poirier bpoirier@suse.com
commit 19110cfbb34d4af0cdfe14cd243f3b09dc95b013 upstream.
Lennart reported the following race condition:
\ e1000_watchdog_task \ e1000e_has_link \ hw->mac.ops.check_for_link() === e1000e_check_for_copper_link /* link is up */ mac->get_link_status = false;
/* interrupt */ \ e1000_msix_other hw->mac.get_link_status = true;
link_active = !hw->mac.get_link_status /* link_active is false, wrongly */
This problem arises because the single flag get_link_status is used to signal two different states: link status needs checking and link status is down.
Avoid the problem by using the return value of .check_for_link to signal the link status to e1000e_has_link().
Reported-by: Lennart Sorensen lsorense@csclub.uwaterloo.ca Signed-off-by: Benjamin Poirier bpoirier@suse.com Tested-by: Aaron Brown aaron.f.brown@intel.com Signed-off-by: Jeff Kirsher jeffrey.t.kirsher@intel.com [bwh: Backported to 3.2: adjust filename] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/net/ethernet/intel/e1000e/lib.c | 11 ++++++++--- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/intel/e1000e/lib.c +++ b/drivers/net/ethernet/intel/e1000e/lib.c @@ -435,6 +435,9 @@ void e1000e_clear_hw_cntrs_base(struct e * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. + * + * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link + * up). **/ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) { @@ -449,7 +452,7 @@ s32 e1000e_check_for_copper_link(struct * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) - return 0; + return 1;
/* * First we want to see if the MII Status Register reports @@ -494,10 +497,12 @@ s32 e1000e_check_for_copper_link(struct * different link partner. */ ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) + if (ret_val) { e_dbg("Error configuring flow control\n"); + return ret_val; + }
- return ret_val; + return 1; }
/** --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -4222,7 +4222,7 @@ static bool e1000e_has_link(struct e1000 case e1000_media_type_copper: if (hw->mac.get_link_status) { ret_val = hw->mac.ops.check_for_link(hw); - link_active = !hw->mac.get_link_status; + link_active = ret_val > 0; } else { link_active = 1; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit b088b53e20c7d09b5ab84c5688e609f478e5c417 upstream.
The extra hw constraint rule for the formats the aloop driver introduced has a slight flaw, where it doesn't return a positive value when the mask got changed. It came from the fact that it's basically a copy&paste from snd_hw_constraint_mask64(). The original code is supposed to be a single-shot and it modifies the mask bits only once and never after, while what we need for aloop is the dynamic hw rule that limits the mask bits.
This difference results in the inconsistent state, as the hw_refine doesn't apply the dependencies fully. The worse and surprisingly result is that it causes a crash in OSS emulation when multiple full-duplex reads/writes are performed concurrently (I leave why it triggers Oops to readers as a homework).
For fixing this, replace a few open-codes with the standard snd_mask_*() macros.
Reported-by: syzbot+3902b5220e8ca27889ca@syzkaller.appspotmail.com Fixes: b1c73fc8e697 ("ALSA: snd-aloop: Fix hw_params restrictions and checking") Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/drivers/aloop.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
--- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -39,6 +39,7 @@ #include <sound/core.h> #include <sound/control.h> #include <sound/pcm.h> +#include <sound/pcm_params.h> #include <sound/info.h> #include <sound/initval.h>
@@ -612,14 +613,12 @@ static int rule_format(struct snd_pcm_hw {
struct snd_pcm_hardware *hw = rule->private; - struct snd_mask *maskp = hw_param_mask(params, rule->var); + struct snd_mask m;
- maskp->bits[0] &= (u_int32_t)hw->formats; - maskp->bits[1] &= (u_int32_t)(hw->formats >> 32); - memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */ - if (! maskp->bits[0] && ! maskp->bits[1]) - return -EINVAL; - return 0; + snd_mask_none(&m); + m.bits[0] = (u_int32_t)hw->formats; + m.bits[1] = (u_int32_t)(hw->formats >> 32); + return snd_mask_refine(hw_param_mask(params, rule->var), &m); }
static int rule_rate(struct snd_pcm_hw_params *params,
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann arnd@arndb.de
commit 2bd7b4aacdb6efa5ccd4749c365c171b884791d2 upstream.
The global array clashes with a newly added symbol of the same name:
drivers/staging/ccree/cc_debugfs.o:(.data+0x0): multiple definition of `debug_regs' drivers/mmc/host/s3cmci.o:(.data+0x70): first defined here
We should fix both, this one addresses the s3cmci driver by removing the symbol from the global namespace. While at it, this separates the declaration from the type definition and makes the variable const.
Fixes: 9bdd203b4dc8 ("s3cmci: add debugfs support for examining driver and hardware state") Fixes: b3ec9a6736f2 ("staging: ccree: staging: ccree: replace sysfs by debugfs interface") Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/mmc/host/s3cmci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index f7f157a62a4a..555c7f133eb8 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1424,7 +1424,9 @@ static const struct file_operations s3cmci_fops_state = { struct s3cmci_reg { unsigned short addr; unsigned char *name; -} debug_regs[] = { +}; + +static const struct s3cmci_reg debug_regs[] = { DBG_REG(CON), DBG_REG(PRE), DBG_REG(CMDARG), @@ -1446,7 +1448,7 @@ struct s3cmci_reg { static int s3cmci_regs_show(struct seq_file *seq, void *v) { struct s3cmci_host *host = seq->private; - struct s3cmci_reg *rptr = debug_regs; + const struct s3cmci_reg *rptr = debug_regs;
for (; rptr->name; rptr++) seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 900498a34a3ac9c611e9b425094c8106bdd7dc1c upstream.
PCM OSS read/write loops keep taking the mutex lock for the whole read/write, and this might take very long when the exceptionally high amount of data is given. Also, since it invokes with mutex_lock(), the concurrent read/write becomes unbreakable.
This patch tries to address these issues by replacing mutex_lock() with mutex_lock_interruptible(), and also splits / re-takes the lock at each read/write period chunk, so that it can switch the context more finely if requested.
Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/oss/pcm_oss.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-)
--- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1375,8 +1375,11 @@ static ssize_t snd_pcm_oss_write1(struct
if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) return tmp; - mutex_lock(&runtime->oss.params_lock); while (bytes > 0) { + if (mutex_lock_interruptible(&runtime->oss.params_lock)) { + tmp = -ERESTARTSYS; + break; + } if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { tmp = bytes; if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes) @@ -1420,18 +1423,18 @@ static ssize_t snd_pcm_oss_write1(struct xfer += tmp; if ((substream->f_flags & O_NONBLOCK) != 0 && tmp != runtime->oss.period_bytes) - break; + tmp = -EAGAIN; } + err: + mutex_unlock(&runtime->oss.params_lock); + if (tmp < 0) + break; if (signal_pending(current)) { tmp = -ERESTARTSYS; - goto err; + break; } + tmp = 0; } - mutex_unlock(&runtime->oss.params_lock); - return xfer; - - err: - mutex_unlock(&runtime->oss.params_lock); return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; }
@@ -1479,8 +1482,11 @@ static ssize_t snd_pcm_oss_read1(struct
if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) return tmp; - mutex_lock(&runtime->oss.params_lock); while (bytes > 0) { + if (mutex_lock_interruptible(&runtime->oss.params_lock)) { + tmp = -ERESTARTSYS; + break; + } if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { if (runtime->oss.buffer_used == 0) { tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); @@ -1511,16 +1517,16 @@ static ssize_t snd_pcm_oss_read1(struct bytes -= tmp; xfer += tmp; } + err: + mutex_unlock(&runtime->oss.params_lock); + if (tmp < 0) + break; if (signal_pending(current)) { tmp = -ERESTARTSYS; - goto err; + break; } + tmp = 0; } - mutex_unlock(&runtime->oss.params_lock); - return xfer; - - err: - mutex_unlock(&runtime->oss.params_lock); return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; }
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Fleytman Dmitry Fleytman dmitry.fleytman@gmail.com
commit 7f038d256c723dd390d2fca942919573995f4cfd upstream.
Commit e0429362ab15 ("usb: Add device quirk for Logitech HD Pro Webcams C920 and C930e") introduced quirk to workaround an issue with some Logitech webcams.
There is one more model that has the same issue - C925e, so applying the same quirk as well.
See aforementioned commit message for detailed explanation of the problem.
Signed-off-by: Dmitry Fleytman dmitry.fleytman@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/usb/core/quirks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -53,10 +53,11 @@ static const struct usb_device_id usb_qu /* Microsoft LifeCam-VX700 v2.0 */ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
- /* Logitech HD Pro Webcams C920, C920-C and C930e */ + /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */ { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT }, + { USB_DEVICE(0x046d, 0x085b), .driver_info = USB_QUIRK_DELAY_INIT },
/* Logitech ConferenceCam CC3000e */ { USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT },
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Stange nstange@suse.de
commit 20b50d79974ea3192e8c3ab7faf4e536e5f14d8f upstream.
Commit 8f659a03a0ba ("net: ipv4: fix for a race condition in raw_sendmsg") fixed the issue of possibly inconsistent ->hdrincl handling due to concurrent updates by reading this bit-field member into a local variable and using the thus stabilized value in subsequent tests.
However, aforementioned commit also adds the (correct) comment that
/* hdrincl should be READ_ONCE(inet->hdrincl) * but READ_ONCE() doesn't work with bit fields */
because as it stands, the compiler is free to shortcut or even eliminate the local variable at its will.
Note that I have not seen anything like this happening in reality and thus, the concern is a theoretical one.
However, in order to be on the safe side, emulate a READ_ONCE() on the bit-field by doing it on the local 'hdrincl' variable itself:
int hdrincl = inet->hdrincl; hdrincl = READ_ONCE(hdrincl);
This breaks the chain in the sense that the compiler is not allowed to replace subsequent reads from hdrincl with reloads from inet->hdrincl.
Fixes: 8f659a03a0ba ("net: ipv4: fix for a race condition in raw_sendmsg") Signed-off-by: Nicolai Stange nstange@suse.de Reviewed-by: Stefano Brivio sbrivio@redhat.com Signed-off-by: David S. Miller davem@davemloft.net [bwh: Backported to 3.2: use ACCESS_ONCE()] Signed-off-by: Ben Hutchings ben@decadent.org.uk --- net/ipv4/raw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -491,9 +491,11 @@ static int raw_sendmsg(struct kiocb *ioc goto out;
/* hdrincl should be READ_ONCE(inet->hdrincl) - * but READ_ONCE() doesn't work with bit fields + * but READ_ONCE() doesn't work with bit fields. + * Doing this indirectly yields the same result. */ hdrincl = inet->hdrincl; + hdrincl = ACCESS_ONCE(hdrincl); /* * Check the flags. */
3.2.100-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hans.verkuil@cisco.com
commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream.
put_v4l2_window32() didn't copy back the clip list to userspace. Drivers can update the clip rectangles, so this should be done.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Acked-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@s-opensource.com Signed-off-by: Ben Hutchings ben@decadent.org.uk --- drivers/media/video/v4l2-compat-ioctl32.c | 59 +++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 19 deletions(-)
--- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -51,6 +51,11 @@ struct v4l2_window32 {
static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { + struct v4l2_clip32 __user *uclips; + struct v4l2_clip __user *kclips; + compat_caddr_t p; + u32 n; + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || copy_from_user(&kp->w, &up->w, sizeof(up->w)) || get_user(kp->field, &up->field) || @@ -60,38 +65,54 @@ static int get_v4l2_window32(struct v4l2 return -EFAULT; if (kp->clipcount > 2048) return -EINVAL; - if (kp->clipcount) { - struct v4l2_clip32 __user *uclips; - struct v4l2_clip __user *kclips; - int n = kp->clipcount; - compat_caddr_t p; + if (!kp->clipcount) { + kp->clips = NULL; + return 0; + }
- if (get_user(p, &up->clips)) + n = kp->clipcount; + if (get_user(p, &up->clips)) + return -EFAULT; + uclips = compat_ptr(p); + kclips = compat_alloc_user_space(n * sizeof(*kclips)); + kp->clips = kclips; + while (n--) { + if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) return -EFAULT; - uclips = compat_ptr(p); - kclips = compat_alloc_user_space(n * sizeof(*kclips)); - kp->clips = kclips; - while (--n >= 0) { - if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) - return -EFAULT; - if (put_user(n ? kclips + 1 : NULL, &kclips->next)) - return -EFAULT; - uclips += 1; - kclips += 1; - } - } else - kp->clips = NULL; + if (put_user(n ? kclips + 1 : NULL, &kclips->next)) + return -EFAULT; + uclips++; + kclips++; + } return 0; }
static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { + struct v4l2_clip __user *kclips = kp->clips; + struct v4l2_clip32 __user *uclips; + u32 n = kp->clipcount; + compat_caddr_t p; + if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || put_user(kp->field, &up->field) || put_user(kp->chromakey, &up->chromakey) || put_user(kp->clipcount, &up->clipcount) || put_user(kp->global_alpha, &up->global_alpha)) return -EFAULT; + + if (!kp->clipcount) + return 0; + + if (get_user(p, &up->clips)) + return -EFAULT; + uclips = compat_ptr(p); + while (n--) { + if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c))) + return -EFAULT; + uclips++; + kclips++; + } return 0; }
On Wed, Feb 28, 2018 at 03:20:21PM +0000, Ben Hutchings wrote:
This is the start of the stable review cycle for the 3.2.100 release. There are 140 patches in this series, which will be posted as responses to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri Mar 02 18:00:00 UTC 2018. Anything received after that time might be too late.
Build results: total: 86 pass: 86 fail: 0 Qemu test results: total: 69 pass: 69 fail: 0
Details are available at http://kerneltests.org/builders.
Guenter
linux-stable-mirror@lists.linaro.org