From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:37308 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751550AbeABNhO (ORCPT ); Tue, 2 Jan 2018 08:37:14 -0500 Date: Tue, 2 Jan 2018 13:36:57 +0000 From: Ben Hutchings To: linux-kernel@vger.kernel.org, Andrew Morton , torvalds@linux-foundation.org, Jiri Slaby , stable@vger.kernel.org Cc: lwn@lwn.net Message-ID: <20180102133657.GV2971@decadent.org.uk> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="fkwCrey//1f/3EP1" Content-Disposition: inline Subject: Linux 3.16.52 Sender: stable-owner@vger.kernel.org List-ID: --fkwCrey//1f/3EP1 Content-Type: multipart/mixed; boundary="+b2GFy/wpzNn/yIF" Content-Disposition: inline --+b2GFy/wpzNn/yIF Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable I'm announcing the release of the 3.16.52 kernel. All users of the 3.16 kernel series should upgrade. The updated 3.16.y git tree can be found at: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable= =2Egit linux-3.16.y and can be browsed at the normal kernel.org git web browser: https://git.kernel.org/?p=3Dlinux/kernel/git/stable/linux-stable.git The diff from 3.16.51 is attached to this message. Ben. ------------ Makefile | 2 +- arch/alpha/kernel/ptrace.c | 2 +- arch/arm/boot/dts/da850-evm.dts | 7 ++ arch/arm/include/asm/Kbuild | 1 - arch/arm/include/asm/unaligned.h | 27 +++++ arch/arm/kernel/traps.c | 28 ++++-- arch/arm/kvm/emulate.c | 5 +- arch/arm/kvm/mmio.c | 4 +- arch/arm64/kernel/head.S | 1 + arch/arm64/kernel/traps.c | 28 +++--- arch/arm64/kvm/inject_fault.c | 16 ++- arch/arm64/mm/fault.c | 2 +- arch/blackfin/kernel/ptrace.c | 4 +- arch/cris/arch-v32/kernel/ptrace.c | 2 +- arch/ia64/kernel/ptrace.c | 2 +- arch/mips/ar7/platform.c | 1 + arch/mips/include/asm/mips-cm.h | 4 +- arch/mips/kernel/ptrace32.c | 4 +- arch/mips/mm/uasm-micromips.c | 2 +- arch/parisc/kernel/syscall.S | 6 +- arch/powerpc/kernel/ptrace32.c | 4 +- arch/powerpc/perf/core-book3s.c | 5 + arch/powerpc/platforms/pseries/mobility.c | 4 +- arch/s390/mm/gup.c | 7 +- arch/sh/include/cpu-sh2a/cpu/sh7264.h | 4 +- arch/sh/include/cpu-sh2a/cpu/sh7269.h | 4 +- arch/sh/include/cpu-sh4/cpu/sh7722.h | 2 +- arch/sh/include/cpu-sh4/cpu/sh7757.h | 8 +- arch/tile/kernel/setup.c | 2 +- arch/x86/crypto/salsa20_glue.c | 7 -- arch/x86/include/asm/uaccess.h | 14 ++- arch/x86/kernel/amd_nb.c | 48 +++++++++ arch/x86/kernel/cpu/microcode/intel.c | 18 ++++ arch/x86/kvm/vmx.c | 7 +- arch/x86/kvm/x86.c | 8 +- arch/x86/oprofile/op_model_ppro.c | 4 +- block/bio.c | 14 ++- crypto/hmac.c | 6 +- crypto/salsa20_generic.c | 7 -- crypto/shash.c | 13 ++- drivers/block/rbd.c | 4 +- drivers/bus/mvebu-mbus.c | 2 +- drivers/crypto/talitos.c | 7 +- drivers/gpio/gpiolib-acpi.c | 2 +- drivers/gpu/drm/i915/intel_bios.c | 7 ++ drivers/hid/i2c-hid/i2c-hid.c | 3 +- drivers/iio/adc/ad7793.c | 4 +- drivers/iio/adc/ad_sigma_delta.c | 28 ++++++ drivers/iio/adc/mcp320x.c | 1 + drivers/iio/industrialio-core.c | 4 +- drivers/infiniband/hw/mlx5/mem.c | 49 ++++----- drivers/infiniband/hw/ocrdma/ocrdma_hw.c | 3 + drivers/infiniband/ulp/ipoib/ipoib_ib.c | 13 --- drivers/input/ff-core.c | 13 ++- drivers/input/misc/ims-pcu.c | 16 ++- drivers/input/misc/uinput.c | 57 +++++++---- drivers/input/touchscreen/ti_am335x_tsc.c | 2 +- drivers/iommu/amd_iommu.c | 1 + drivers/iommu/exynos-iommu.c | 2 +- drivers/net/can/c_can/c_can_pci.c | 1 - drivers/net/can/c_can/c_can_platform.c | 1 - drivers/net/can/usb/esd_usb2.c | 2 +- drivers/net/can/usb/gs_usb.c | 10 +- drivers/net/can/usb/kvaser_usb.c | 3 +- drivers/net/macvtap.c | 6 +- drivers/net/tun.c | 7 ++ drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 58 +++-------- drivers/net/wireless/brcm80211/brcmfmac/fweh.h | 68 ++++++++++--- drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 10 ++ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 5 + drivers/net/wireless/iwlwifi/mvm/mac80211.c | 10 +- drivers/pci/pci-sysfs.c | 11 ++- drivers/s390/scsi/zfcp_aux.c | 5 + drivers/s390/scsi/zfcp_erp.c | 18 ++-- drivers/s390/scsi/zfcp_scsi.c | 5 + drivers/scsi/libiscsi.c | 2 +- drivers/scsi/lpfc/lpfc_init.c | 1 + drivers/scsi/scsi_scan.c | 3 + drivers/scsi/sd.c | 16 ++- drivers/staging/iio/adc/ad7192.c | 4 +- drivers/staging/iio/meter/ade7759.c | 2 +- drivers/usb/class/cdc-acm.c | 3 + drivers/usb/core/config.c | 6 +- drivers/usb/core/hub.c | 13 ++- drivers/usb/core/quirks.c | 4 + drivers/usb/gadget/composite.c | 5 + drivers/usb/gadget/dummy_hcd.c | 81 +++++++++++---- drivers/usb/gadget/f_mass_storage.c | 31 ++---- drivers/usb/gadget/f_mass_storage.h | 14 --- drivers/usb/gadget/inode.c | 55 +++++++++-- drivers/usb/gadget/mass_storage.c | 20 +--- drivers/usb/gadget/net2280.c | 5 +- drivers/usb/host/pci-quirks.c | 8 +- drivers/usb/host/xhci-hub.c | 22 ++++- drivers/usb/host/xhci.h | 2 +- drivers/usb/renesas_usbhs/fifo.c | 23 ++++- drivers/usb/serial/cp210x.c | 1 + drivers/usb/serial/ftdi_sio.c | 2 + drivers/usb/serial/ftdi_sio_ids.h | 7 ++ drivers/usb/serial/metro-usb.c | 1 + drivers/usb/serial/option.c | 2 + drivers/usb/serial/qcserial.c | 4 + drivers/usb/storage/transport.c | 14 ++- drivers/usb/storage/unusual_devs.h | 7 ++ drivers/uwb/hwa-rc.c | 2 + drivers/uwb/uwbd.c | 12 ++- fs/block_dev.c | 6 +- fs/btrfs/ioctl.c | 10 +- fs/cifs/cifsfs.c | 2 +- fs/cifs/connect.c | 8 ++ fs/cifs/file.c | 7 ++ fs/cifs/smb2pdu.c | 34 +++++-- fs/direct-io.c | 3 +- fs/ecryptfs/ecryptfs_kernel.h | 25 +++-- fs/ecryptfs/keystore.c | 9 +- fs/exec.c | 22 ++++- fs/fscache/object-list.c | 7 ++ fs/fuse/dir.c | 3 +- fs/mpage.c | 14 ++- fs/ocfs2/alloc.c | 24 +++-- fs/read_write.c | 4 +- fs/xattr.c | 2 +- include/crypto/internal/hash.h | 8 ++ include/linux/buffer_head.h | 1 + include/linux/capability.h | 2 + include/linux/iio/adc/ad_sigma_delta.h | 3 + include/linux/input.h | 1 + include/linux/key.h | 2 + include/linux/mbus.h | 4 +- include/linux/mm.h | 2 + include/linux/mm_types.h | 1 + include/linux/mmzone.h | 10 +- include/linux/netdevice.h | 3 + include/linux/of.h | 10 ++ include/linux/pci_ids.h | 2 + include/linux/preempt_mask.h | 21 ++-- include/linux/ptrace.h | 11 ++- include/linux/sched.h | 1 + include/linux/skbuff.h | 7 ++ include/net/protocol.h | 2 +- include/net/route.h | 4 +- include/net/tcp.h | 8 +- include/net/udp.h | 2 +- include/scsi/scsi_device.h | 1 + include/scsi/scsi_devinfo.h | 1 + include/sound/seq_kernel.h | 3 +- include/sound/seq_virmidi.h | 1 + include/sound/timer.h | 2 + include/trace/events/kvm.h | 7 +- include/uapi/linux/spi/spidev.h | 1 + kernel/capability.c | 36 ++++++- kernel/fork.c | 9 +- kernel/params.c | 2 +- kernel/ptrace.c | 91 +++++++++++------ kernel/sched/core.c | 21 ++-- kernel/sched/features.h | 1 - kernel/sysctl.c | 3 +- kernel/trace/trace.c | 12 ++- kernel/workqueue.c | 37 +++---- kernel/workqueue_internal.h | 3 +- lib/asn1_decoder.c | 7 +- lib/digsig.c | 6 ++ mm/huge_memory.c | 14 +-- mm/init-mm.c | 2 + mm/memory.c | 2 +- mm/memory_hotplug.c | 6 +- mm/nommu.c | 2 +- net/8021q/vlan.c | 6 +- net/bluetooth/bnep/core.c | 3 + net/bluetooth/cmtp/core.c | 3 + net/core/dev.c | 6 +- net/core/rtnetlink.c | 5 +- net/core/skbuff.c | 1 + net/dccp/proto.c | 5 + net/ipv4/ip_input.c | 22 +++-- net/ipv4/ip_vti.c | 3 +- net/ipv4/route.c | 44 +++++---- net/ipv4/tcp_ipv4.c | 9 +- net/ipv4/tcp_output.c | 12 ++- net/ipv4/udp.c | 30 ++++-- net/ipv6/ip6_gre.c | 41 ++++---- net/ipv6/ip6_vti.c | 3 +- net/l2tp/l2tp_core.c | 10 +- net/l2tp/l2tp_core.h | 5 +- net/l2tp/l2tp_eth.c | 51 +--------- net/l2tp/l2tp_ip.c | 20 ++-- net/l2tp/l2tp_ip6.c | 21 ++-- net/l2tp/l2tp_ppp.c | 10 +- net/netfilter/ipset/ip_set_core.c | 23 +++-- net/netfilter/nfnetlink_cthelper.c | 10 ++ net/netfilter/x_tables.c | 4 +- net/netfilter/xt_osf.c | 7 ++ net/netlink/af_netlink.c | 3 + net/packet/af_packet.c | 4 +- net/sched/sch_generic.c | 1 + net/sctp/input.c | 2 +- net/sctp/sm_sideeffect.c | 4 +- net/unix/diag.c | 2 + net/wireless/nl80211.c | 12 ++- net/xfrm/xfrm_state.c | 1 + net/xfrm/xfrm_user.c | 3 +- security/keys/big_key.c | 2 +- security/keys/encrypted-keys/encrypted.c | 7 ++ security/keys/internal.h | 2 +- security/keys/key.c | 2 + security/keys/keyctl.c | 8 +- security/keys/keyring.c | 72 +++++++------- security/keys/process_keys.c | 8 +- security/keys/request_key.c | 46 +++++++-- security/keys/request_key_auth.c | 69 ++++++------- security/keys/trusted.c | 69 ++++++------- security/smack/smack_lsm.c | 65 ++++++------ security/yama/yama_lsm.c | 4 +- sound/core/hrtimer.c | 1 + sound/core/seq/oss/seq_oss_midi.c | 4 +- sound/core/seq/oss/seq_oss_readq.c | 29 ++++++ sound/core/seq/oss/seq_oss_readq.h | 2 + sound/core/seq/seq_clientmgr.c | 2 +- sound/core/seq/seq_virmidi.c | 27 +++-- sound/core/timer.c | 109 ++++++++++++++---= ---- sound/core/timer_compat.c | 17 +++- sound/pci/hda/hda_codec.c | 2 +- sound/soc/codecs/adau17x1.c | 24 ++++- sound/soc/codecs/adau17x1.h | 2 + sound/usb/caiaq/device.c | 12 ++- sound/usb/usx2y/usb_stream.c | 6 +- 226 files changed, 1732 insertions(+), 944 deletions(-) Adrian Salido (1): HID: i2c-hid: allocate hid buffers for real worst case Al Viro (3): more bio_map_user_iov() leak fixes Bluetooth: cmtp: cmtp_add_connection() should verify that it's dealin= g with l2cap socket Bluetooth: bnep: bnep_add_connection() should verify that it's dealin= g with l2cap socket Alan Stern (11): usb-storage: fix bogus hardware error messages for ATA pass-thru devi= ces usb-storage: unusual_devs entry to fix write-access regression for Se= agate external drives USB: gadgetfs: fix copy_to_user while holding spinlock USB: gadgetfs: Fix crash caused by inadequate synchronization USB: g_mass_storage: Fix deadlock when driver is unbound USB: dummy-hcd: fix connection failures (wrong speed) USB: dummy-hcd: fix infinite-loop resubmission bug USB: gadgetfs, dummy-hcd, net2280: fix locking for callbacks USB: dummy-hcd: Fix erroneous synchronization change USB: dummy-hcd: Fix deadlock caused by disconnect detection USB: core: prevent malicious bNumInterfaces overflow Alex Estrin (1): Revert "IB/ipoib: Update broadcast object if PKey value was changed i= n index 0" Alexey Kodanev (1): vti: fix use after free in vti_tunnel_xmit/vti6_tnl_xmit Andreas Engel (1): USB: serial: cp210x: add support for ELV TFD500 Andreas Gruenbacher (2): vfs: Return -ENXIO for negative SEEK_HOLE / SEEK_DATA offsets direct-io: Prevent NULL pointer access in submit_page_section Andrei Vagin (1): net/unix: don't show information about sockets from other namespaces Andrew Gabbasov (1): usb: gadget: composite: Fix use-after-free in usb_composite_overwrite= _options Andrew Honig (1): KVM: VMX: remove I/O port 0x80 bypass on Intel hosts Andrey Konovalov (2): uwb: ensure that endpoint is interrupt uwb: properly check kthread_run return value Aravind Gopalakrishnan (2): pci_ids: Add PCI device IDs for F15h M60h x86, amd_nb: Add device IDs to NB tables for F15h M60h Arnd Bergmann (4): gpio: acpi: work around false-positive -Wstring-overflow warning usb: gadget: dummy: fix nonsensical comparisons include/linux/of.h: provide of_n_{addr,size}_cells wrappers for !CONF= IG_OF ARM: 8715/1: add a private asm/unaligned.h Ashish Samant (1): ocfs2: fstrim: Fix start offset of first cluster group during fstrim Baruch Siach (1): spi: uapi: spidev: add missing ioctl header Ben Hutchings (2): ipsec: Fix aborted xfrm policy dump crash Linux 3.16.52 Bo Yan (1): tracing: Erase irqsoff trace with empty write Borislav Petkov (3): x86/microcode/intel: Disable late loading on model 79 x86/cpu/AMD: Apply the Erratum 688 fix when the BIOS doesn't x86/oprofile/ppro: Do not use __this_cpu*() in preemptible context Casey Schaufler (1): lsm: fix smack_inode_removexattr and xattr_getsecurity memleak Christophe Jaillet (1): IB/mlx5: Fix the size parameter to find_first_bit Colin Ian King (2): IB/ocrdma: fix incorrect fall-through on switch statement staging: iio: ade7759: fix signed extension bug on shift of a u8 Cong Wang (2): tun: call dev_get_valid_name() before register_netdevice() vlan: fix a use-after-free in vlan_device_event() Craig Gallek (1): tun/tap: sanitize TUNSETSNDBUF input Dan Carpenter (1): tile: array underflow in setup_maxnodemem() David Disseldorp (2): SMB: fix leak of validate negotiate info response buffer SMB: fix validate negotiate info uninitialised memory use Dmitry Fleytman (1): usb: Increase quirk delay for USB devices Dmitry Torokhov (3): Input: uinput - avoid FF flush when destroying device Input: uinput - avoid crash when sending FF request to device going a= way Input: ims-psu - check if CDC union descriptor is sane Dongjiu Geng (1): arm/arm64: KVM: set right LR register value for 32 bit guest when inj= ect abort Dragos Bogdan (2): iio: ad_sigma_delta: Implement a dedicated reset function iio: ad7793: Fix the serial interface reset Eric Biggers (18): KEYS: fix cred refcount leak in request_key_auth_new() KEYS: don't revoke uninstantiated key in request_key_auth_new() KEYS: fix key refcount leak in keyctl_assume_authority() KEYS: fix key refcount leak in keyctl_read_key() KEYS: fix writing past end of user-supplied buffer in keyring_read() KEYS: prevent creating a different user's keyrings KEYS: encrypted: fix dereference of NULL user_key_payload FS-Cache: fix dereference of NULL user_key_payload lib/digsig: fix dereference of NULL user_key_payload ecryptfs: fix dereference of NULL user_key_payload KEYS: return full count in keyring_read() if buffer is too small KEYS: trusted: sanitize all key material KEYS: trusted: fix writing past end of buffer in trusted_read() KEYS: fix out-of-bounds read during ASN.1 parsing KEYS: fix NULL pointer dereference during ASN.1 parsing [ver #2] crypto: salsa20 - fix blkcipher_walk API usage crypto: hmac - require that the underlying hash algorithm is unkeyed KEYS: add missing permission check for request_key() destination Eric Dumazet (3): tcp: fastopen: fix on syn-data transmit failure netfilter: x_tables: avoid stack-out-of-bounds read in xt_copy_counte= rs_from_user tcp: fix tcp_mtu_probe() vs highest_sack Eric W. Biederman (5): mm: Add a user_ns owner to mm_struct and fix ptrace permission checks ptrace: Capture the ptracer's creds not PT_PTRACE_CAP exec: Ensure mm->user_ns contains the execed files ptrace: Don't allow accessing an undumpable mm ptrace: Properly initialize ptracer_cred on fork Ethan Zhao (1): sched/sysctl: Check user input value of sysctl_sched_time_avg Felipe Balbi (1): usb: quirks: add quirk for WORLDE MINI MIDI keyboard Florian Westphal (1): netfilter: ipset: pernet ops must be unregistered last Geert Uytterhoeven (4): sh: sh7722: remove nonexistent GPIO_PTQ7 to fix pinctrl registration sh: sh7757: remove nonexistent GPIO_PT[JLNQ]7_RESV to fix pinctrl reg= istration sh: sh7264: remove nonexistent GPIO_PH[0-7] to fix pinctrl registrati= on sh: sh7269: remove nonexistent GPIO_PH[0-7] to fix pinctrl registrati= on Gerald Schaefer (1): s390/mm: fix write access check in gup_huge_pmd() Guillaume Nault (6): l2tp: fix l2tp_eth module loading l2tp: check ps->sock before running pppol2tp_session_ioctl() l2tp: hold tunnel in pppol2tp_connect() l2tp: hold socket before dropping lock in l2tp_ip{, 6}_recv() l2tp: hold tunnel socket when handling control frames in l2tp_ip and = l2tp_ip6 l2tp: don't use l2tp_tunnel_find() in l2tp_ip and l2tp_ip6 Gustavo A. R. Silva (1): MIPS: microMIPS: Fix incorrect mask in insn_table_MM Hante Meuleman (1): brcmfmac: Add length checks on firmware events Haozhong Zhang (1): KVM: nVMX: fix guest CR4 loading when emulating L2 to L1 exit Henryk Heisig (1): USB: serial: option: add support for TP-Link LTE module Herbert Xu (1): crypto: shash - Fix zero-length shash ahash digest crash Ilya Dryomov (1): rbd: use GFP_NOIO for parent stat and data requests Ilya Lesokhin (1): IB/mlx5: Simplify mlx5_ib_cont_pages Jan Luebbe (1): bus: mbus: fix window size calculation for 4GB windows Jani Nikula (1): drm/i915/bios: ignore HDMI on port A Jann Horn (1): security: let security modules use PTRACE_MODE_* with bitmasks Jason A. Donenfeld (1): security/keys: properly zero out sensitive key material in big_key Jean Delvare (1): kernel/params.c: align add_sysfs_param documentation with code Jeff Lance (1): Input: ti_am335x_tsc - fix incorrect step config for 5 wire touchscre= en Jeffrey Chu (1): USB: serial: ftdi_sio: add id for Cypress WICED dev board Jim Dickerson (1): usb: pci-quirks.c: Corrected timeout values used in handshake Jimmy Assarsson (1): can: kvaser_usb: Correct return value in printout Joerg Roedel (1): iommu/amd: Finish TLB flush in amd_iommu_unmap() Johan Hovold (1): USB: serial: metro-usb: add MS7820 device id Johannes Thumshirn (1): scsi: libiscsi: fix shifting of DID_REQUEUE host byte John David Anglin (1): parisc: Fix double-word compare and exchange in LWS code on 32-bit ke= rnels Jonathan Basseri (1): xfrm: Clear sk_dst_cache when applying per-socket policy. Kazuya Mizuguchi (1): usb: renesas_usbhs: Fix DMAC sequence for receiving zero-length packet Kevin Cernekee (4): brcmfmac: Add check for short event packets netfilter: nfnetlink_cthelper: Add missing permission checks netlink: Add netns check on taps netfilter: xt_osf: Add missing permission checks Kirill A. Shutemov (1): mm, thp: Do not make page table dirty unconditionally in touch_p[mu]d= () Konstantin Khlebnikov (2): net_sched: always reset qdisc backlog in qdisc_reset() Smack: remove unneeded NULL-termination from securtity label LEROY Christophe (2): crypto: talitos - fix sha224 crypto: talitos - Don't provide setkey for non hmac hashing algs. Lauro Ramos Venancio (1): sched/topology: Optimize build_group_mask() Li Bin (1): workqueue: Fix NULL pointer dereference Luca Coelho (1): iwlwifi: mvm: use IWL_HCMD_NOCOPY for MCAST_FILTER_CMD Lukas Wunner (1): iio: adc: mcp320x: Fix oops on module unload Maksim Salau (1): usb: cdc_acm: Add quirk for Elatec TWN3 Marc Zyngier (1): arm64: Make sure SPsel is always set Marek Szyprowski (1): iommu/exynos: Remove initconst attribute to avoid potential kernel oo= ps Mark Rutland (3): arm64: fix dump_instr when PAN and UAO are in use arm64: ensure __dump_instr() checks addr_limit ARM: 8720/1: ensure dump_instr() checks addr_limit Martin K. Petersen (1): scsi: sd: Implement blacklist option for WRITE SAME w/ UNMAP Mathias Nyman (2): xhci: fix finding correct bus_state structure for USB 3.1 hosts usb: hub: Allow reset retry for USB2 devices on connect bounce Matt Bennett (1): ip6_gre: Reduce log level in ip6gre_err() to debug Matt Fornero (1): iio: core: Return error for failed read_reg Matthew Wilcox (1): fs/mpage.c: fix mpage_writepage() for pages with buffers Mayank Rana (1): usb: xhci: Handle error condition in xhci_stop_device() Michael S. Tsirkin (1): macvtap: fix TUNSETSNDBUF values > 64k Miklos Szeredi (1): fuse: fix READDIRPLUS skipping an entry Mohamed Ghannam (1): dccp: CVE-2017-8824: use-after-free in DCCP code Nicolai Stange (1): PCI: Fix race condition with driver_override Nicolas Dichtel (1): net: enable interface alias removal via rtnl Oleg Nesterov (1): ptrace: change __ptrace_unlink() to clear ->ptrace under ->siglock Omar Sandoval (1): Btrfs: fix incorrect {node,sector}size endianness from BTRFS_IOC_FS_I= NFO Oswald Buddenhagen (1): MIPS: AR7: Ensure that serial ports are properly set up Paolo Abeni (4): ipv4: fix broadcast packets reception IPv4: early demux can return an error code udp: perform source validation for mcast early demux udp: fix bcast packet reception Paul Burton (1): MIPS: Fix CM region target definitions Peng Xu (1): nl80211: Define policy for packet pattern attributes Peter Zijlstra (3): x86/uaccess, sched/preempt: Verify access_ok() context sched/topology: Remove FORCE_SD_OVERLAP sched/topology: Simplify build_overlap_sched_groups() Ravi Bangoria (1): powerpc/sysrq: Fix oops whem ppmu is not registered Ricard Wanderlof (1): ASoC: adau17x1: Workaround for noise bug in ADC Richard Sch=FCtz (1): can: c_can: don't indicate triple sampling support for D_CAN Ronnie Sahlberg (1): cifs: check rsp for NULL before dereferencing in SMB2_open Sabrina Dubroca (1): l2tp: fix race condition in l2tp_tunnel_delete Sekhar Nori (1): ARM: dts: da850-evm: add serial and ethernet aliases Shrirang Bagul (1): USB: serial: qcserial: add Dell DW5818, DW5819 Shu Wang (2): cifs: release cifs root_cred after exit_cifs cifs: release auth_key.response for reconnect. Stefan M=E4tje (1): can: esd_usb2: Fix can_dlc value for received RTR, frames Stefan Popa (1): staging: iio: ad7192: Fix - use the dedicated reset function avoiding= dma from stack. Stefano Brivio (1): scsi: lpfc: Don't return internal MBXERR_ERROR code from probe functi= on Steffen Maier (1): scsi: zfcp: fix erp_action use-before-initialize in REC action trace Steve French (3): SMB: Validate negotiate (to protect against downgrade) even if signin= g off SMB3: Don't ignore O_SYNC/O_DSYNC and O_DIRECT flags SMB3: Validate negotiate request must always be signed Tahsin Erdogan (1): tracing: Fix trace_pipe behavior for instance traces Takashi Iwai (10): ALSA: usx2y: Suppress kernel warning at page allocation failures ALSA: seq: Fix copy_from_user() call inside lock ALSA: caiaq: Fix stray URB at probe error path ALSA: hda: Remove superfluous '-' added by printk conversion ALSA: timer: Add missing mutex lock for compat ioctls ALSA: seq: Fix nested rwsem annotation for lockdep splat ALSA: timer: Protect the whole snd_timer_close() with open race ALSA: timer: Limit max instances per timer ALSA: seq: Avoid invalid lockdep class warning ALSA: seq: Fix OSS sysex delivery in OSS emulation Tejun Heo (1): workqueue: replace pool->manager_arb mutex with a flag Tyrel Datwyler (1): powerpc/pseries: Fix parent_dn reference leak in add_dt_node() Wanpeng Li (1): KVM: Fix stack-out-of-bounds read in write_mmio Will Deacon (1): arm64: fault: Route pte translation faults via do_translation_fault Willem de Bruijn (1): packet: only test po->has_vnet_hdr once in packet_snd Wolfgang Grandegger (1): can: gs_usb: fix busy loop if no more TX context is available Xin Long (4): ip6_gre: skb_push ipv6hdr before packing the header in ip6gre_header sctp: add the missing sock_owned_by_user check in sctp_icmp_redirect ip6_gre: only increase err_count for some certain type icmpv6 in ip6g= re_err sctp: fix a type cast warnings that causes a_rwnd gets the wrong value YASUAKI ISHIMATSU (2): mm/memory_hotplug: change pfn_to_section_nr/section_nr_to_pfn macro t= o inline function mm/memory_hotplug: define find_{smallest|biggest}_section_pfn as unsi= gned long Yazen Ghannam (1): x86/amd_nb: Add Fam17h Data Fabric as "Northbridge" Ye Yin (1): netfilter/ipvs: clear ipvs_property flag when SKB net namespace chang= ed Yoshihiro Shimoda (2): usb: renesas_usbhs: fix the BCLR setting condition for non-DCP pipe usb: renesas_usbhs: fix usbhsf_fifo_clear() for RX direction satoru takeuchi (1): btrfs: prevent to set invalid default subvolid --+b2GFy/wpzNn/yIF Content-Type: text/x-diff; charset=UTF-8; name="linux-3.16.52.patch" Content-Disposition: attachment; filename="linux-3.16.52.patch" Content-Transfer-Encoding: quoted-printable diff --git a/Makefile b/Makefile index fc9df28cecf1..5cf074eb43ed 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION =3D 3 PATCHLEVEL =3D 16 -SUBLEVEL =3D 51 +SUBLEVEL =3D 52 EXTRAVERSION =3D NAME =3D Museum of Fishiegoodies =20 diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index 86d835157b54..292e6cae1d10 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -281,7 +281,7 @@ long arch_ptrace(struct task_struct *child, long reques= t, /* When I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: - copied =3D access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + copied =3D ptrace_access_vm(child, addr, &tmp, sizeof(tmp), 0); ret =3D -EIO; if (copied !=3D sizeof(tmp)) break; diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.= dts index 21342ab78ff5..c2f242d122f0 100644 --- a/arch/arm/boot/dts/da850-evm.dts +++ b/arch/arm/boot/dts/da850-evm.dts @@ -14,6 +14,13 @@ compatible =3D "ti,da850-evm", "ti,da850"; model =3D "DA850/AM1808/OMAP-L138 EVM"; =20 + aliases { + serial0 =3D &serial0; + serial1 =3D &serial1; + serial2 =3D &serial2; + ethernet0 =3D ð0; + }; + soc { pmx_core: pinmux@1c14120 { status =3D "okay"; diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index f5a357601983..4d9849d22357 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -36,4 +36,3 @@ generic-y +=3D termbits.h generic-y +=3D termios.h generic-y +=3D timex.h generic-y +=3D trace_clock.h -generic-y +=3D unaligned.h diff --git a/arch/arm/include/asm/unaligned.h b/arch/arm/include/asm/unalig= ned.h new file mode 100644 index 000000000000..ab905ffcf193 --- /dev/null +++ b/arch/arm/include/asm/unaligned.h @@ -0,0 +1,27 @@ +#ifndef __ASM_ARM_UNALIGNED_H +#define __ASM_ARM_UNALIGNED_H + +/* + * We generally want to set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS on ARMv= 6+, + * but we don't want to use linux/unaligned/access_ok.h since that can lead + * to traps on unaligned stm/ldm or strd/ldrd. + */ +#include + +#if defined(__LITTLE_ENDIAN) +# include +# include +# include +# define get_unaligned __get_unaligned_le +# define put_unaligned __put_unaligned_le +#elif defined(__BIG_ENDIAN) +# include +# include +# include +# define get_unaligned __get_unaligned_be +# define put_unaligned __put_unaligned_be +#else +# error need to define endianess +#endif + +#endif /* __ASM_ARM_UNALIGNED_H */ diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 8dffc57a9f71..cba3cb0b1a47 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -129,30 +129,26 @@ static void dump_mem(const char *lvl, const char *str= , unsigned long bottom, set_fs(fs); } =20 -static void dump_instr(const char *lvl, struct pt_regs *regs) +static void __dump_instr(const char *lvl, struct pt_regs *regs) { unsigned long addr =3D instruction_pointer(regs); const int thumb =3D thumb_mode(regs); const int width =3D thumb ? 4 : 8; - mm_segment_t fs; char str[sizeof("00000000 ") * 5 + 2 + 1], *p =3D str; int i; =20 /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. + * Note that we now dump the code first, just in case the backtrace + * kills us. */ - fs =3D get_fs(); - set_fs(KERNEL_DS); =20 for (i =3D -4; i < 1 + !!thumb; i++) { unsigned int val, bad; =20 if (thumb) - bad =3D __get_user(val, &((u16 *)addr)[i]); + bad =3D get_user(val, &((u16 *)addr)[i]); else - bad =3D __get_user(val, &((u32 *)addr)[i]); + bad =3D get_user(val, &((u32 *)addr)[i]); =20 if (!bad) p +=3D sprintf(p, i =3D=3D 0 ? "(%0*x) " : "%0*x ", @@ -163,8 +159,20 @@ static void dump_instr(const char *lvl, struct pt_regs= *regs) } } printk("%sCode: %s\n", lvl, str); +} =20 - set_fs(fs); +static void dump_instr(const char *lvl, struct pt_regs *regs) +{ + mm_segment_t fs; + + if (!user_mode(regs)) { + fs =3D get_fs(); + set_fs(KERNEL_DS); + __dump_instr(lvl, regs); + set_fs(fs); + } else { + __dump_instr(lvl, regs); + } } =20 #ifdef CONFIG_ARM_UNWIND diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index d6c005283678..ef0a11f8a9d1 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c @@ -295,7 +295,7 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) u32 return_offset =3D (is_thumb) ? 2 : 4; =20 new_spsr_value =3D cpsr; - new_lr_value =3D *vcpu_pc(vcpu) - return_offset; + new_lr_value =3D *vcpu_pc(vcpu) + return_offset; =20 *vcpu_cpsr(vcpu) =3D (cpsr & ~MODE_MASK) | UND_MODE; *vcpu_cpsr(vcpu) |=3D PSR_I_BIT; @@ -324,9 +324,8 @@ static void inject_abt(struct kvm_vcpu *vcpu, bool is_p= abt, unsigned long addr) unsigned long new_spsr_value; unsigned long cpsr =3D *vcpu_cpsr(vcpu); u32 sctlr =3D vcpu->arch.cp15[c1_SCTLR]; - bool is_thumb =3D (cpsr & PSR_T_BIT); u32 vect_offset; - u32 return_offset =3D (is_thumb) ? 4 : 0; + u32 return_offset =3D (is_pabt) ? 4 : 8; bool is_lpae; =20 new_spsr_value =3D cpsr; diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c index 4cb5a93182e9..c47f108c2b8a 100644 --- a/arch/arm/kvm/mmio.c +++ b/arch/arm/kvm/mmio.c @@ -113,7 +113,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struc= t kvm_run *run) } =20 trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, - data); + &data); data =3D vcpu_data_host_to_guest(vcpu, data, len); *vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt) =3D data; } @@ -192,7 +192,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run = *run, trace_kvm_mmio((mmio.is_write) ? KVM_TRACE_MMIO_WRITE : KVM_TRACE_MMIO_READ_UNSATISFIED, mmio.len, fault_ipa, - (mmio.is_write) ? data : 0); + (mmio.is_write) ? &data : NULL); =20 if (mmio.is_write) mmio_write_buf(mmio.data, mmio.len, data); diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index cb83c1aabae8..d15ed089bb83 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -269,6 +269,7 @@ ENDPROC(stext) * booted in EL1 or EL2 respectively. */ ENTRY(el2_setup) + msr SPsel, #1 // We want to use SP_EL{1,2} mrs x0, CurrentEL cmp x0, #CurrentEL_EL2 b.ne 1f diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index c1c2ad6a1c94..ec1e323060e0 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -59,8 +59,7 @@ static void dump_mem(const char *lvl, const char *str, un= signed long bottom, =20 /* * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. + * to safely read from kernel space. */ fs =3D get_fs(); set_fs(KERNEL_DS); @@ -97,25 +96,16 @@ static void dump_backtrace_entry(unsigned long where, u= nsigned long stack) stack + sizeof(struct pt_regs)); } =20 -static void dump_instr(const char *lvl, struct pt_regs *regs) +static void __dump_instr(const char *lvl, struct pt_regs *regs) { unsigned long addr =3D instruction_pointer(regs); - mm_segment_t fs; char str[sizeof("00000000 ") * 5 + 2 + 1], *p =3D str; int i; =20 - /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. - */ - fs =3D get_fs(); - set_fs(KERNEL_DS); - for (i =3D -4; i < 1; i++) { unsigned int val, bad; =20 - bad =3D __get_user(val, &((u32 *)addr)[i]); + bad =3D get_user(val, &((u32 *)addr)[i]); =20 if (!bad) p +=3D sprintf(p, i =3D=3D 0 ? "(%08x) " : "%08x ", val); @@ -125,8 +115,18 @@ static void dump_instr(const char *lvl, struct pt_regs= *regs) } } printk("%sCode: %s\n", lvl, str); +} =20 - set_fs(fs); +static void dump_instr(const char *lvl, struct pt_regs *regs) +{ + if (!user_mode(regs)) { + mm_segment_t fs =3D get_fs(); + set_fs(KERNEL_DS); + __dump_instr(lvl, regs); + set_fs(fs); + } else { + __dump_instr(lvl, regs); + } } =20 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index f527a37ac979..595d311affe8 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -29,12 +29,26 @@ PSR_I_BIT | PSR_D_BIT) #define EL1_EXCEPT_SYNC_OFFSET 0x200 =20 +/* + * Table taken from ARMv8 ARM DDI0487B-B, table G1-10. + */ +static const u8 return_offsets[8][2] =3D { + [0] =3D { 0, 0 }, /* Reset, unused */ + [1] =3D { 4, 2 }, /* Undefined */ + [2] =3D { 0, 0 }, /* SVC, unused */ + [3] =3D { 4, 4 }, /* Prefetch abort */ + [4] =3D { 8, 8 }, /* Data abort */ + [5] =3D { 0, 0 }, /* HVC, unused */ + [6] =3D { 4, 4 }, /* IRQ, unused */ + [7] =3D { 4, 4 }, /* FIQ, unused */ +}; + static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offs= et) { unsigned long cpsr; unsigned long new_spsr_value =3D *vcpu_cpsr(vcpu); bool is_thumb =3D (new_spsr_value & COMPAT_PSR_T_BIT); - u32 return_offset =3D (is_thumb) ? 4 : 0; + u32 return_offset =3D return_offsets[vect_offset >> 2][is_thumb]; u32 sctlr =3D vcpu_cp15(vcpu, c1_SCTLR); =20 cpsr =3D mode | COMPAT_PSR_I_BIT; diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 8fd2315bdf4d..ca1b882bc9e1 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -386,7 +386,7 @@ static struct fault_info { { do_translation_fault, SIGSEGV, SEGV_MAPERR, "input address range fault"= }, { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault"= }, { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault"= }, - { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, + { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault"= }, { do_bad, SIGBUS, 0, "reserved access flag fault" }, { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 8b8fe671b1a6..7d8ece6a93fb 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -270,7 +270,7 @@ long arch_ptrace(struct task_struct *child, long reques= t, switch (bfin_mem_access_type(addr, to_copy)) { case BFIN_MEM_ACCESS_CORE: case BFIN_MEM_ACCESS_CORE_ONLY: - copied =3D access_process_vm(child, addr, &tmp, + copied =3D ptrace_access_vm(child, addr, &tmp, to_copy, 0); if (copied) break; @@ -323,7 +323,7 @@ long arch_ptrace(struct task_struct *child, long reques= t, switch (bfin_mem_access_type(addr, to_copy)) { case BFIN_MEM_ACCESS_CORE: case BFIN_MEM_ACCESS_CORE_ONLY: - copied =3D access_process_vm(child, addr, &data, + copied =3D ptrace_access_vm(child, addr, &data, to_copy, 1); break; case BFIN_MEM_ACCESS_DMA: diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel= /ptrace.c index f085229cf870..04251c6cb5f9 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *child, long reques= t, /* The trampoline page is globally mapped, no page table to traverse.*/ tmp =3D *(unsigned long*)addr; } else { - copied =3D access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + copied =3D ptrace_access_vm(child, addr, &tmp, sizeof(tmp), 0); =20 if (copied !=3D sizeof(tmp)) break; diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index b7a5fffe0924..c218249c4792 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -1156,7 +1156,7 @@ arch_ptrace (struct task_struct *child, long request, case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: /* read word at location addr */ - if (access_process_vm(child, addr, &data, sizeof(data), 0) + if (ptrace_access_vm(child, addr, &data, sizeof(data), 0) !=3D sizeof(data)) return -EIO; /* ensure return value is not mistaken for error code */ diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index 7e2356fd5fd6..e4f47d3e55bb 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -581,6 +581,7 @@ static int __init ar7_register_uarts(void) uart_port.type =3D PORT_AR7; uart_port.uartclk =3D clk_get_rate(bus_clk) / 2; uart_port.iotype =3D UPIO_MEM32; + uart_port.flags =3D UPF_FIXED_TYPE; uart_port.regshift =3D 2; =20 uart_port.line =3D 0; diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-c= m.h index 6a9d2dd005ca..79c882be9d17 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -173,8 +173,8 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_GCR_BASE_GCRBASE_MSK (_ULCAST_(0x1ffff) << 15) #define CM_GCR_BASE_CMDEFTGT_SHF 0 #define CM_GCR_BASE_CMDEFTGT_MSK (_ULCAST_(0x3) << 0) -#define CM_GCR_BASE_CMDEFTGT_DISABLED 0 -#define CM_GCR_BASE_CMDEFTGT_MEM 1 +#define CM_GCR_BASE_CMDEFTGT_MEM 0 +#define CM_GCR_BASE_CMDEFTGT_RESERVED 1 #define CM_GCR_BASE_CMDEFTGT_IOCU0 2 #define CM_GCR_BASE_CMDEFTGT_IOCU1 3 =20 diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index a83fb730b387..fdd26c104c6c 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -69,7 +69,7 @@ long compat_arch_ptrace(struct task_struct *child, compat= _long_t request, if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != =3D 0) break; =20 - copied =3D access_process_vm(child, (u64)addrOthers, &tmp, + copied =3D ptrace_access_vm(child, (u64)addrOthers, &tmp, sizeof(tmp), 0); if (copied !=3D sizeof(tmp)) break; @@ -178,7 +178,7 @@ long compat_arch_ptrace(struct task_struct *child, comp= at_long_t request, if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != =3D 0) break; ret =3D 0; - if (access_process_vm(child, (u64)addrOthers, &data, + if (ptrace_access_vm(child, (u64)addrOthers, &data, sizeof(data), 1) =3D=3D sizeof(data)) break; ret =3D -EIO; diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 8399ddf03a02..cab124e0572d 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -83,7 +83,7 @@ static struct insn insn_table_MM[] =3D { { insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS }, { insn_lb, M(mm_lb32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, { insn_ld, 0, 0 }, - { insn_lh, M(mm_lh32_op, 0, 0, 0, 0, 0), RS | RS | SIMM }, + { insn_lh, M(mm_lh32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, { insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIM= M }, { insn_lld, 0, 0 }, { insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM }, diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index f716e9e65a49..df6ff75c03ce 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -742,7 +742,7 @@ ENTRY(linux_gateway_page) 10: ldd 0(%sr3,%r25), %r25 11: ldd 0(%sr3,%r24), %r24 #else - /* Load new value into r22/r23 - high/low */ + /* Load old value into r22/r23 - high/low */ 10: ldw 0(%sr3,%r25), %r22 11: ldw 4(%sr3,%r25), %r23 /* Load new value into fr4 for atomic store later */ @@ -834,11 +834,11 @@ ENTRY(linux_gateway_page) copy %r0, %r28 #else /* Compare first word */ -19: ldw,ma 0(%sr3,%r26), %r29 +19: ldw 0(%sr3,%r26), %r29 sub,=3D %r29, %r22, %r0 b,n cas2_end /* Compare second word */ -20: ldw,ma 4(%sr3,%r26), %r29 +20: ldw 4(%sr3,%r26), %r29 sub,=3D %r29, %r23, %r0 b,n cas2_end /* Perform the store */ diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index f52b7db327c8..2e4f01dc9d64 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c @@ -73,7 +73,7 @@ long compat_arch_ptrace(struct task_struct *child, compat= _long_t request, if (get_user(addrOthers, (u32 __user * __user *)addr) !=3D 0) break; =20 - copied =3D access_process_vm(child, (u64)addrOthers, &tmp, + copied =3D ptrace_access_vm(child, (u64)addrOthers, &tmp, sizeof(tmp), 0); if (copied !=3D sizeof(tmp)) break; @@ -178,7 +178,7 @@ long compat_arch_ptrace(struct task_struct *child, comp= at_long_t request, if (get_user(addrOthers, (u32 __user * __user *)addr) !=3D 0) break; ret =3D 0; - if (access_process_vm(child, (u64)addrOthers, &tmp, + if (ptrace_access_vm(child, (u64)addrOthers, &tmp, sizeof(tmp), 1) =3D=3D sizeof(tmp)) break; ret =3D -EIO; diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3= s.c index 97579de6853b..6b989c2d6e31 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -755,6 +755,11 @@ void perf_event_print_debug(void) u32 pmcs[MAX_HWEVENTS]; int i; =20 + if (!ppmu) { + pr_info("Performance monitor hardware not registered.\n"); + return; + } + if (!ppmu->n_counter) return; =20 diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platf= orms/pseries/mobility.c index c70762e0daf1..eb4b07f3a505 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -224,8 +224,10 @@ static int add_dt_node(__be32 parent_phandle, __be32 d= rc_index) return -ENOENT; =20 dn =3D dlpar_configure_connector(drc_index, parent_dn); - if (!dn) + if (!dn) { + of_node_put(parent_dn); return -ENOENT; + } =20 rc =3D dlpar_attach_node(dn); if (rc) diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 639fce464008..21e925e9845a 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -51,13 +51,12 @@ static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd,= unsigned long addr, static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr, unsigned long end, int write, struct page **pages, int *nr) { - unsigned long mask, result; struct page *head, *page, *tail; + unsigned long mask; int refs; =20 - result =3D write ? 0 : _SEGMENT_ENTRY_PROTECT; - mask =3D result | _SEGMENT_ENTRY_INVALID; - if ((pmd_val(pmd) & mask) !=3D result) + mask =3D (write ? _SEGMENT_ENTRY_PROTECT : 0) | _SEGMENT_ENTRY_INVALID; + if ((pmd_val(pmd) & mask) !=3D 0) return 0; VM_BUG_ON(!pfn_valid(pmd_val(pmd) >> PAGE_SHIFT)); =20 diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7264.h b/arch/sh/include/cpu-sh= 2a/cpu/sh7264.h index 4d1ef6d74bd6..2ae0e938b657 100644 --- a/arch/sh/include/cpu-sh2a/cpu/sh7264.h +++ b/arch/sh/include/cpu-sh2a/cpu/sh7264.h @@ -43,9 +43,7 @@ enum { GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4, GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0, =20 - /* Port H */ - GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4, - GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0, + /* Port H - Port H does not have a Data Register */ =20 /* Port I - not on device */ =20 diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7269.h b/arch/sh/include/cpu-sh= 2a/cpu/sh7269.h index 2a0ca8780f0d..13c495a9fc00 100644 --- a/arch/sh/include/cpu-sh2a/cpu/sh7269.h +++ b/arch/sh/include/cpu-sh2a/cpu/sh7269.h @@ -45,9 +45,7 @@ enum { GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4, GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0, =20 - /* Port H */ - GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4, - GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0, + /* Port H - Port H does not have a Data Register */ =20 /* Port I - not on device */ =20 diff --git a/arch/sh/include/cpu-sh4/cpu/sh7722.h b/arch/sh/include/cpu-sh4= /cpu/sh7722.h index 3bb74e534d0f..78961ab78a5a 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7722.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7722.h @@ -67,7 +67,7 @@ enum { GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0, =20 /* PTQ */ - GPIO_PTQ7, GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4, + GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4, GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0, =20 /* PTR */ diff --git a/arch/sh/include/cpu-sh4/cpu/sh7757.h b/arch/sh/include/cpu-sh4= /cpu/sh7757.h index 5340f3bc1863..b40fb541e72a 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7757.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7757.h @@ -40,7 +40,7 @@ enum { =20 /* PTJ */ GPIO_PTJ0, GPIO_PTJ1, GPIO_PTJ2, GPIO_PTJ3, - GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6, GPIO_PTJ7_RESV, + GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6, =20 /* PTK */ GPIO_PTK0, GPIO_PTK1, GPIO_PTK2, GPIO_PTK3, @@ -48,7 +48,7 @@ enum { =20 /* PTL */ GPIO_PTL0, GPIO_PTL1, GPIO_PTL2, GPIO_PTL3, - GPIO_PTL4, GPIO_PTL5, GPIO_PTL6, GPIO_PTL7_RESV, + GPIO_PTL4, GPIO_PTL5, GPIO_PTL6, =20 /* PTM */ GPIO_PTM0, GPIO_PTM1, GPIO_PTM2, GPIO_PTM3, @@ -56,7 +56,7 @@ enum { =20 /* PTN */ GPIO_PTN0, GPIO_PTN1, GPIO_PTN2, GPIO_PTN3, - GPIO_PTN4, GPIO_PTN5, GPIO_PTN6, GPIO_PTN7_RESV, + GPIO_PTN4, GPIO_PTN5, GPIO_PTN6, =20 /* PTO */ GPIO_PTO0, GPIO_PTO1, GPIO_PTO2, GPIO_PTO3, @@ -68,7 +68,7 @@ enum { =20 /* PTQ */ GPIO_PTQ0, GPIO_PTQ1, GPIO_PTQ2, GPIO_PTQ3, - GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6, GPIO_PTQ7_RESV, + GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6, =20 /* PTR */ GPIO_PTR0, GPIO_PTR1, GPIO_PTR2, GPIO_PTR3, diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index d8a9df999da3..0ac4de510b42 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -139,7 +139,7 @@ static int __init setup_maxnodemem(char *str) { char *endp; unsigned long long maxnodemem; - long node; + unsigned long node; =20 node =3D str ? simple_strtoul(str, &endp, 0) : INT_MAX; if (node >=3D MAX_NUMNODES || *endp !=3D ':') diff --git a/arch/x86/crypto/salsa20_glue.c b/arch/x86/crypto/salsa20_glue.c index 399a29d067d6..cb91a64a99e7 100644 --- a/arch/x86/crypto/salsa20_glue.c +++ b/arch/x86/crypto/salsa20_glue.c @@ -59,13 +59,6 @@ static int encrypt(struct blkcipher_desc *desc, =20 salsa20_ivsetup(ctx, walk.iv); =20 - if (likely(walk.nbytes =3D=3D nbytes)) - { - salsa20_encrypt_bytes(ctx, walk.src.virt.addr, - walk.dst.virt.addr, nbytes); - return blkcipher_walk_done(desc, &walk, 0); - } - while (walk.nbytes >=3D 64) { salsa20_encrypt_bytes(ctx, walk.src.virt.addr, walk.dst.virt.addr, diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 465504609869..887c0ea365a7 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,12 @@ static inline bool __chk_range_not_ok(unsigned long addr= , unsigned long size, un __chk_range_not_ok((unsigned long __force)(addr), size, limit); \ }) =20 +#ifdef CONFIG_DEBUG_ATOMIC_SLEEP +# define WARN_ON_IN_IRQ() WARN_ON_ONCE(!in_task()) +#else +# define WARN_ON_IN_IRQ() +#endif + /** * access_ok: - Checks if a user space pointer is valid * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that @@ -85,8 +92,11 @@ static inline bool __chk_range_not_ok(unsigned long addr= , unsigned long size, un * checks that the pointer is in the user space range - after calling * this function, memory access functions may still return -EFAULT. */ -#define access_ok(type, addr, size) \ - likely(!__range_not_ok(addr, size, user_addr_max())) +#define access_ok(type, addr, size) \ +({ \ + WARN_ON_IN_IRQ(); \ + likely(!__range_not_ok(addr, size, user_addr_max())); \ +}) =20 /* * The exception table consists of pairs of addresses relative to the diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 29f0c55d6efc..3c9d268939af 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -13,16 +13,24 @@ #include #include =20 +#define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463 +#define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464 + static u32 *flush_words; =20 +#define PCI_DEVICE_ID_AMD_CNB17H_F4 0x1704 + const struct pci_device_id amd_nb_misc_ids[] =3D { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, {} }; EXPORT_SYMBOL(amd_nb_misc_ids); @@ -30,8 +38,11 @@ EXPORT_SYMBOL(amd_nb_misc_ids); static const struct pci_device_id amd_nb_link_ids[] =3D { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) }, {} }; =20 @@ -278,6 +289,41 @@ void amd_flush_garts(void) } EXPORT_SYMBOL_GPL(amd_flush_garts); =20 +static void __fix_erratum_688(void *info) +{ +#define MSR_AMD64_IC_CFG 0xC0011021 + + msr_set_bit(MSR_AMD64_IC_CFG, 3); + msr_set_bit(MSR_AMD64_IC_CFG, 14); +} + +/* Apply erratum 688 fix so machines without a BIOS fix work. */ +static __init void fix_erratum_688(void) +{ + struct pci_dev *F4; + u32 val; + + if (boot_cpu_data.x86 !=3D 0x14) + return; + + if (!amd_northbridges.num) + return; + + F4 =3D node_to_amd_nb(0)->link; + if (!F4) + return; + + if (pci_read_config_dword(F4, 0x164, &val)) + return; + + if (val & BIT(2)) + return; + + on_each_cpu(__fix_erratum_688, NULL, 0); + + pr_info("x86/cpu/AMD: CPU erratum 688 worked around\n"); +} + static __init int init_amd_nbs(void) { int err =3D 0; @@ -290,6 +336,8 @@ static __init int init_amd_nbs(void) if (amd_cache_gart() < 0) pr_notice("Cannot initialize GART flush words, GART support disabled\n"); =20 + fix_erratum_688(); + return err; } =20 diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index a276fa75d9b5..8eaa571cb5f6 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -267,6 +267,18 @@ static int get_ucode_fw(void *to, const void *from, si= ze_t n) return 0; } =20 +static bool is_blacklisted(unsigned int cpu) +{ + struct cpuinfo_x86 *c =3D &cpu_data(cpu); + + if (c->x86 =3D=3D 6 && c->x86_model =3D=3D 0x4F) { + pr_err_once("late loading on model 79 is disabled.\n"); + return true; + } + + return false; +} + static enum ucode_state request_microcode_fw(int cpu, struct device *devic= e, bool refresh_fw) { @@ -275,6 +287,9 @@ static enum ucode_state request_microcode_fw(int cpu, s= truct device *device, const struct firmware *firmware; enum ucode_state ret; =20 + if (is_blacklisted(cpu)) + return UCODE_NFOUND; + sprintf(name, "intel-ucode/%02x-%02x-%02x", c->x86, c->x86_model, c->x86_mask); =20 @@ -299,6 +314,9 @@ static int get_ucode_user(void *to, const void *from, s= ize_t n) static enum ucode_state request_microcode_user(int cpu, const void __user *buf, size_t size) { + if (is_blacklisted(cpu)) + return UCODE_NFOUND; + return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user); } =20 diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 50a1d48b1419..f9a6d8d68720 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8670,7 +8670,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *v= cpu, * (KVM doesn't change it)- no reason to call set_cr4_guest_host_mask(); */ vcpu->arch.cr4_guest_owned_bits =3D ~vmcs_readl(CR4_GUEST_HOST_MASK); - kvm_set_cr4(vcpu, vmcs12->host_cr4); + vmx_set_cr4(vcpu, vmcs12->host_cr4); =20 nested_ept_uninit_mmu_context(vcpu); =20 @@ -9029,12 +9029,7 @@ static int __init vmx_init(void) memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE); memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE); =20 - /* - * Allow direct access to the PC debug port (it is often used for I/O - * delays, but the vmexits simply slow things down). - */ memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE); - clear_bit(0x80, vmx_io_bitmap_a); =20 memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE); =20 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 77edfa6d0b54..2d7ccb5a2bdd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4052,7 +4052,7 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_= t addr, int len, void *v) !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v)) && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v)) break; - trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v); + trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, v); handled +=3D n; addr +=3D n; len -=3D n; @@ -4276,7 +4276,7 @@ static int read_prepare(struct kvm_vcpu *vcpu, void *= val, int bytes) { if (vcpu->mmio_read_completed) { trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, - vcpu->mmio_fragments[0].gpa, *(u64 *)val); + vcpu->mmio_fragments[0].gpa, val); vcpu->mmio_read_completed =3D 0; return 1; } @@ -4298,14 +4298,14 @@ static int write_emulate(struct kvm_vcpu *vcpu, gpa= _t gpa, =20 static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *v= al) { - trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val); + trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, val); return vcpu_mmio_write(vcpu, gpa, bytes, val); } =20 static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, void *val, int bytes) { - trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0); + trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, NULL); return X86EMUL_IO_NEEDED; } =20 diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model= _ppro.c index d90528ea5412..12c051d19e4b 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c @@ -212,8 +212,8 @@ static void arch_perfmon_setup_counters(void) eax.full =3D cpuid_eax(0xa); =20 /* Workaround for BIOS bugs in 6/15. Taken from perfmon2 */ - if (eax.split.version_id =3D=3D 0 && __this_cpu_read(cpu_info.x86) =3D=3D= 6 && - __this_cpu_read(cpu_info.x86_model) =3D=3D 15) { + if (eax.split.version_id =3D=3D 0 && boot_cpu_data.x86 =3D=3D 6 && + boot_cpu_data.x86_model =3D=3D 15) { eax.split.version_id =3D 2; eax.split.num_counters =3D 2; eax.split.bit_width =3D 40; diff --git a/block/bio.c b/block/bio.c index dcc6365bcc11..4218dab2bb47 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1286,6 +1286,7 @@ static struct bio *__bio_map_user_iov(struct request_= queue *q, struct bio *bio; int cur_page =3D 0; int ret, offset; + struct bio_vec *bvec; =20 for (i =3D 0; i < iov_count; i++) { unsigned long uaddr =3D (unsigned long)iov[i].iov_base; @@ -1329,7 +1330,12 @@ static struct bio *__bio_map_user_iov(struct request= _queue *q, =20 ret =3D get_user_pages_fast(uaddr, local_nr_pages, write_to_vm, &pages[cur_page]); - if (ret < local_nr_pages) { + if (unlikely(ret < local_nr_pages)) { + for (j =3D cur_page; j < page_limit; j++) { + if (!pages[j]) + break; + put_page(pages[j]); + } ret =3D -EFAULT; goto out_unmap; } @@ -1384,10 +1390,8 @@ static struct bio *__bio_map_user_iov(struct request= _queue *q, return bio; =20 out_unmap: - for (i =3D 0; i < nr_pages; i++) { - if(!pages[i]) - break; - page_cache_release(pages[i]); + bio_for_each_segment_all(bvec, bio, j) { + put_page(bvec->bv_page); } out: kfree(pages); diff --git a/crypto/hmac.c b/crypto/hmac.c index ade790b454e9..758688b4bc6b 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -197,11 +197,15 @@ static int hmac_create(struct crypto_template *tmpl, = struct rtattr **tb) salg =3D shash_attr_alg(tb[1], 0, 0); if (IS_ERR(salg)) return PTR_ERR(salg); + alg =3D &salg->base; =20 + /* The underlying hash algorithm must be unkeyed */ err =3D -EINVAL; + if (crypto_shash_alg_has_setkey(salg)) + goto out_put_alg; + ds =3D salg->digestsize; ss =3D salg->statesize; - alg =3D &salg->base; if (ds > alg->cra_blocksize || ss < alg->cra_blocksize) goto out_put_alg; diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c index f550b5d94630..d7da0eea5622 100644 --- a/crypto/salsa20_generic.c +++ b/crypto/salsa20_generic.c @@ -188,13 +188,6 @@ static int encrypt(struct blkcipher_desc *desc, =20 salsa20_ivsetup(ctx, walk.iv); =20 - if (likely(walk.nbytes =3D=3D nbytes)) - { - salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, - walk.src.virt.addr, nbytes); - return blkcipher_walk_done(desc, &walk, 0); - } - while (walk.nbytes >=3D 64) { salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, walk.src.virt.addr, diff --git a/crypto/shash.c b/crypto/shash.c index 03fbcd4a82c4..73c065321867 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -24,11 +24,12 @@ =20 static const struct crypto_type crypto_shash_type; =20 -static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, - unsigned int keylen) +int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, + unsigned int keylen) { return -ENOSYS; } +EXPORT_SYMBOL_GPL(shash_no_setkey); =20 static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, unsigned int keylen) @@ -274,12 +275,14 @@ static int shash_async_finup(struct ahash_request *re= q) =20 int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc) { - struct scatterlist *sg =3D req->src; - unsigned int offset =3D sg->offset; unsigned int nbytes =3D req->nbytes; + struct scatterlist *sg; + unsigned int offset; int err; =20 - if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { + if (nbytes && + (sg =3D req->src, offset =3D sg->offset, + nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) { void *data; =20 data =3D kmap_atomic(sg_page(sg)); diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 6eea35b05f6a..d1c04f0f79b6 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -2584,7 +2584,7 @@ static int rbd_img_obj_parent_read_full(struct rbd_ob= j_request *obj_request) * from the parent. */ page_count =3D (u32)calc_pages_for(0, length); - pages =3D ceph_alloc_page_vector(page_count, GFP_KERNEL); + pages =3D ceph_alloc_page_vector(page_count, GFP_NOIO); if (IS_ERR(pages)) { result =3D PTR_ERR(pages); pages =3D NULL; @@ -2711,7 +2711,7 @@ static int rbd_img_obj_exists_submit(struct rbd_obj_r= equest *obj_request) */ size =3D sizeof (__le64) + sizeof (__le32) + sizeof (__le32); page_count =3D (u32)calc_pages_for(0, size); - pages =3D ceph_alloc_page_vector(page_count, GFP_KERNEL); + pages =3D ceph_alloc_page_vector(page_count, GFP_NOIO); if (IS_ERR(pages)) return PTR_ERR(pages); =20 diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index d29f5ffdb0f4..d729c1cc7542 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -523,7 +523,7 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_s= tate *mbus) if (mbus->hw_io_coherency) w->mbus_attr |=3D ATTR_HW_COHERENCY; w->base =3D base & DDR_BASE_CS_LOW_MASK; - w->size =3D (size | ~DDR_SIZE_MASK) + 1; + w->size =3D (u64)(size | ~DDR_SIZE_MASK) + 1; } } mvebu_mbus_dram_info.num_cs =3D cs; diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index c6bd28c59d65..0d3f3af79bde 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1581,9 +1581,9 @@ static int common_nonsnoop_hash(struct talitos_edesc = *edesc, req_ctx->swinit =3D 0; } else { desc->ptr[1] =3D zero_entry; - /* Indicate next op is not the first. */ - req_ctx->first =3D 0; } + /* Indicate next op is not the first. */ + req_ctx->first =3D 0; =20 /* HMAC key */ if (ctx->keylen) @@ -2550,7 +2550,8 @@ static struct talitos_crypto_alg *talitos_alg_alloc(s= truct device *dev, t_alg->algt.alg.hash.final =3D ahash_final; t_alg->algt.alg.hash.finup =3D ahash_finup; t_alg->algt.alg.hash.digest =3D ahash_digest; - t_alg->algt.alg.hash.setkey =3D ahash_setkey; + if (!strncmp(alg->cra_name, "hmac", 4)) + t_alg->algt.alg.hash.setkey =3D ahash_setkey; =20 if (!(priv->features & TALITOS_FTR_HMAC_OK) && !strncmp(alg->cra_name, "hmac", 4)) { diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 86608585ec00..5b38f5aede59 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -130,7 +130,7 @@ static acpi_status acpi_gpiochip_request_interrupt(stru= ct acpi_resource *ares, =20 if (pin <=3D 255) { char ev_name[5]; - sprintf(ev_name, "_%c%02X", + sprintf(ev_name, "_%c%02hhX", agpio->triggering =3D=3D ACPI_EDGE_SENSITIVE ? 'E' : 'L', pin); if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle))) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel= _bios.c index 07d72573fc60..e03526a10340 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -939,6 +939,13 @@ static void parse_ddi_port(struct drm_i915_private *de= v_priv, enum port port, is_hdmi =3D is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_O= UTPUT) =3D=3D 0; is_edp =3D is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CON= NECTOR); =20 + if (port =3D=3D PORT_A && is_dvi) { + DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n", + is_hdmi ? "/HDMI" : ""); + is_dvi =3D false; + is_hdmi =3D false; + } + info->supports_dvi =3D is_dvi; info->supports_hdmi =3D is_hdmi; info->supports_dp =3D is_dp; diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 23eebb7f31aa..149d1da033c0 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -526,7 +526,8 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, = size_t report_size) { /* the worst case is computed from the set_report command with a * reportID > 15 and the maximum report length */ - int args_len =3D sizeof(__u8) + /* optional ReportID byte */ + int args_len =3D sizeof(__u8) + /* ReportID */ + sizeof(__u8) + /* optional ReportID byte */ sizeof(__u16) + /* data register */ sizeof(__u16) + /* size of the report */ report_size; /* report */ diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 5da07546e182..05ab5ad07df1 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -257,7 +257,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, unsigned int vref_mv) { struct ad7793_state *st =3D iio_priv(indio_dev); - int i, ret =3D -1; + int i, ret; unsigned long long scale_uv; u32 id; =20 @@ -266,7 +266,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, return ret; =20 /* reset the serial interface */ - ret =3D spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret)); + ret =3D ad_sd_reset(&st->sd, 32); if (ret < 0) goto out; usleep_range(500, 2000); /* Wait for at least 500us */ diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_de= lta.c index eb799a43aef0..dbcea7941059 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -177,6 +177,34 @@ int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, } EXPORT_SYMBOL_GPL(ad_sd_read_reg); =20 +/** + * ad_sd_reset() - Reset the serial interface + * + * @sigma_delta: The sigma delta device + * @reset_length: Number of SCLKs with DIN =3D 1 + * + * Returns 0 on success, an error code otherwise. + **/ +int ad_sd_reset(struct ad_sigma_delta *sigma_delta, + unsigned int reset_length) +{ + uint8_t *buf; + unsigned int size; + int ret; + + size =3D DIV_ROUND_UP(reset_length, 8); + buf =3D kcalloc(size, sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memset(buf, 0xff, size); + ret =3D spi_write(sigma_delta->spi, buf, size); + kfree(buf); + + return ret; +} +EXPORT_SYMBOL_GPL(ad_sd_reset); + static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, unsigned int mode, unsigned int channel) { diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 28a086e48776..662c930fb1c3 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -180,6 +180,7 @@ static int mcp320x_probe(struct spi_device *spi) indio_dev->name =3D spi_get_device_id(spi)->name; indio_dev->modes =3D INDIO_DIRECT_MODE; indio_dev->info =3D &mcp320x_info; + spi_set_drvdata(spi, indio_dev); =20 chip_info =3D &mcp3208_chip_infos[spi_get_device_id(spi)->driver_data]; indio_dev->channels =3D chip_info->channels; diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-cor= e.c index c6b0f1503366..4d1b400ed260 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -184,8 +184,10 @@ static ssize_t iio_debugfs_read_reg(struct file *file,= char __user *userbuf, ret =3D indio_dev->info->debugfs_reg_access(indio_dev, indio_dev->cached_reg_addr, 0, &val); - if (ret) + if (ret) { dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); + return ret; + } =20 len =3D snprintf(buf, sizeof(buf), "0x%X\n", val); =20 diff --git a/drivers/infiniband/hw/mlx5/mem.c b/drivers/infiniband/hw/mlx5/= mem.c index deff377934ff..474bcafe0684 100644 --- a/drivers/infiniband/hw/mlx5/mem.c +++ b/drivers/infiniband/hw/mlx5/mem.c @@ -46,46 +46,33 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,= int *count, int *shift, { unsigned long tmp; unsigned long m; - int i, k; - u64 base =3D 0; - int p =3D 0; - int skip; - int mask; - u64 len; - u64 pfn; + u64 base =3D ~0, p =3D 0; + u64 len, pfn; + int i =3D 0; struct scatterlist *sg; int entry; =20 addr =3D addr >> PAGE_SHIFT; tmp =3D (unsigned long)addr; - m =3D find_first_bit(&tmp, sizeof(tmp)); - skip =3D 1 << m; - mask =3D skip - 1; - i =3D 0; + m =3D find_first_bit(&tmp, BITS_PER_LONG); + for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) { len =3D sg_dma_len(sg) >> PAGE_SHIFT; pfn =3D sg_dma_address(sg) >> PAGE_SHIFT; - for (k =3D 0; k < len; k++) { - if (!(i & mask)) { - tmp =3D (unsigned long)pfn; - m =3D min_t(unsigned long, m, find_first_bit(&tmp, sizeof(tmp))); - skip =3D 1 << m; - mask =3D skip - 1; - base =3D pfn; - p =3D 0; - } else { - if (base + p !=3D pfn) { - tmp =3D (unsigned long)p; - m =3D find_first_bit(&tmp, sizeof(tmp)); - skip =3D 1 << m; - mask =3D skip - 1; - base =3D pfn; - p =3D 0; - } - } - p++; - i++; + if (base + p !=3D pfn) { + /* If either the offset or the new + * base are unaligned update m + */ + tmp =3D (unsigned long)(pfn | p); + if (!IS_ALIGNED(tmp, 1 << m)) + m =3D find_first_bit(&tmp, BITS_PER_LONG); + + base =3D pfn; + p =3D 0; } + + p +=3D len; + i +=3D len; } =20 if (i) { diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/= hw/ocrdma/ocrdma_hw.c index 3bbf2010a821..e682c79c41c1 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -235,7 +235,10 @@ static int ocrdma_get_mbx_errno(u32 status) case OCRDMA_MBX_ADDI_STATUS_INSUFFICIENT_RESOURCES: err_num =3D -EAGAIN; break; + default: + err_num =3D -EFAULT; } + break; default: err_num =3D -EFAULT; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/u= lp/ipoib/ipoib_ib.c index 27fe62e2fd95..fcbfdda0e585 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -961,19 +961,6 @@ static inline int update_parent_pkey(struct ipoib_dev_= priv *priv) */ priv->dev->broadcast[8] =3D priv->pkey >> 8; priv->dev->broadcast[9] =3D priv->pkey & 0xff; - - /* - * Update the broadcast address in the priv->broadcast object, - * in case it already exists, otherwise no one will do that. - */ - if (priv->broadcast) { - spin_lock_irq(&priv->lock); - memcpy(priv->broadcast->mcmember.mgid.raw, - priv->dev->broadcast + 4, - sizeof(union ib_gid)); - spin_unlock_irq(&priv->lock); - } - return 0; } =20 diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index f50f6dd92274..b0e2de131b76 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -239,9 +239,15 @@ int input_ff_erase(struct input_dev *dev, int effect_i= d, struct file *file) EXPORT_SYMBOL_GPL(input_ff_erase); =20 /* - * flush_effects - erase all effects owned by a file handle + * input_ff_flush - erase all effects owned by a file handle + * @dev: input device to erase effect from + * @file: purported owner of the effects + * + * This function erases all force-feedback effects associated with + * the given owner from specified device. Note that @file may be %NULL, + * in which case all effects will be erased. */ -static int flush_effects(struct input_dev *dev, struct file *file) +int input_ff_flush(struct input_dev *dev, struct file *file) { struct ff_device *ff =3D dev->ff; int i; @@ -257,6 +263,7 @@ static int flush_effects(struct input_dev *dev, struct = file *file) =20 return 0; } +EXPORT_SYMBOL_GPL(input_ff_flush); =20 /** * input_ff_event() - generic handler for force-feedback events @@ -340,7 +347,7 @@ int input_ff_create(struct input_dev *dev, unsigned int= max_effects) mutex_init(&ff->mutex); =20 dev->ff =3D ff; - dev->flush =3D flush_effects; + dev->flush =3D input_ff_flush; dev->event =3D input_ff_event; __set_bit(EV_FF, dev->evbit); =20 diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index f19375acfeec..ea8c48a9e09d 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -1635,13 +1635,25 @@ ims_pcu_get_cdc_union_desc(struct usb_interface *in= tf) return NULL; } =20 - while (buflen > 0) { + while (buflen >=3D sizeof(*union_desc)) { union_desc =3D (struct usb_cdc_union_desc *)buf; =20 + if (union_desc->bLength > buflen) { + dev_err(&intf->dev, "Too large descriptor\n"); + return NULL; + } + if (union_desc->bDescriptorType =3D=3D USB_DT_CS_INTERFACE && union_desc->bDescriptorSubType =3D=3D USB_CDC_UNION_TYPE) { dev_dbg(&intf->dev, "Found union header\n"); - return union_desc; + + if (union_desc->bLength >=3D sizeof(*union_desc)) + return union_desc; + + dev_err(&intf->dev, + "Union descriptor to short (%d vs %zd\n)", + union_desc->bLength, sizeof(*union_desc)); + return NULL; } =20 buflen -=3D union_desc->bLength; diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 5a63c274ae1c..08cf73e92cb3 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -98,14 +98,15 @@ static int uinput_request_reserve_slot(struct uinput_de= vice *udev, uinput_request_alloc_id(udev, request)); } =20 -static void uinput_request_done(struct uinput_device *udev, - struct uinput_request *request) +static void uinput_request_release_slot(struct uinput_device *udev, + unsigned int id) { /* Mark slot as available */ - udev->requests[request->id] =3D NULL; - wake_up(&udev->requests_waitq); + spin_lock(&udev->requests_lock); + udev->requests[id] =3D NULL; + spin_unlock(&udev->requests_lock); =20 - complete(&request->done); + wake_up(&udev->requests_waitq); } =20 static int uinput_request_send(struct uinput_device *udev, @@ -138,20 +139,22 @@ static int uinput_request_send(struct uinput_device *= udev, static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request) { - int error; + int retval; =20 - error =3D uinput_request_reserve_slot(udev, request); - if (error) - return error; + retval =3D uinput_request_reserve_slot(udev, request); + if (retval) + return retval; =20 - error =3D uinput_request_send(udev, request); - if (error) { - uinput_request_done(udev, request); - return error; - } + retval =3D uinput_request_send(udev, request); + if (retval) + goto out; =20 wait_for_completion(&request->done); - return request->retval; + retval =3D request->retval; + + out: + uinput_request_release_slot(udev, request->id); + return retval; } =20 /* @@ -169,7 +172,7 @@ static void uinput_flush_requests(struct uinput_device = *udev) request =3D udev->requests[i]; if (request) { request->retval =3D -ENODEV; - uinput_request_done(udev, request); + complete(&request->done); } } =20 @@ -230,6 +233,18 @@ static int uinput_dev_erase_effect(struct input_dev *d= ev, int effect_id) return uinput_request_submit(udev, &request); } =20 +static int uinput_dev_flush(struct input_dev *dev, struct file *file) +{ + /* + * If we are called with file =3D=3D NULL that means we are tearing + * down the device, and therefore we can not handle FF erase + * requests: either we are handling UI_DEV_DESTROY (and holding + * the udev->mutex), or the file descriptor is closed and there is + * nobody on the other side anymore. + */ + return file ? input_ff_flush(dev, file) : 0; +} + static void uinput_destroy_device(struct uinput_device *udev) { const char *name, *phys; @@ -273,6 +288,12 @@ static int uinput_create_device(struct uinput_device *= udev) dev->ff->playback =3D uinput_dev_playback; dev->ff->set_gain =3D uinput_dev_set_gain; dev->ff->set_autocenter =3D uinput_dev_set_autocenter; + /* + * The standard input_ff_flush() implementation does + * not quite work for uinput as we can't reasonably + * handle FF requests during device teardown. + */ + dev->flush =3D uinput_dev_flush; } =20 error =3D input_register_device(udev->dev); @@ -840,7 +861,7 @@ static long uinput_ioctl_handler(struct file *file, uns= igned int cmd, } =20 req->retval =3D ff_up.retval; - uinput_request_done(udev, req); + complete(&req->done); goto out; =20 case UI_END_FF_ERASE: @@ -856,7 +877,7 @@ static long uinput_ioctl_handler(struct file *file, uns= igned int cmd, } =20 req->retval =3D ff_erase.retval; - uinput_request_done(udev, req); + complete(&req->done); goto out; } =20 diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touc= hscreen/ti_am335x_tsc.c index 2ce649520fe0..092fa8b31c67 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -157,7 +157,7 @@ static void titsc_step_config(struct titsc *ts_dev) break; case 5: config |=3D ts_dev->bit_xp | STEPCONFIG_INP_AN4 | - ts_dev->bit_xn | ts_dev->bit_yp; + STEPCONFIG_XNP | STEPCONFIG_YPN; break; case 8: config |=3D ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 07af55cc2dcc..353417c95502 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3440,6 +3440,7 @@ static size_t amd_iommu_unmap(struct iommu_domain *do= m, unsigned long iova, mutex_unlock(&domain->api_lock); =20 domain_flush_tlb_pde(domain); + domain_flush_complete(domain); =20 return unmap_size; } diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 99054d2c040d..e7434b1b1d62 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -676,7 +676,7 @@ static int __init exynos_sysmmu_probe(struct platform_d= evice *pdev) return 0; } =20 -static const struct of_device_id sysmmu_of_match[] __initconst =3D { +static const struct of_device_id sysmmu_of_match[] =3D { { .compatible =3D "samsung,exynos-sysmmu", }, { }, }; diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_ca= n_pci.c index b997508ea7c6..913a1c5ad1b4 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -178,7 +178,6 @@ static int c_can_pci_probe(struct pci_dev *pdev, break; case BOSCH_D_CAN: priv->regs =3D reg_map_d_can; - priv->can.ctrlmode_supported |=3D CAN_CTRLMODE_3_SAMPLES; break; default: ret =3D -EINVAL; diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can= /c_can_platform.c index 12430be6448a..660404f5ebac 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -266,7 +266,6 @@ static int c_can_plat_probe(struct platform_device *pde= v) break; case BOSCH_D_CAN: priv->regs =3D reg_map_d_can; - priv->can.ctrlmode_supported |=3D CAN_CTRLMODE_3_SAMPLES; priv->read_reg =3D c_can_plat_read_reg_aligned_to_16bit; priv->write_reg =3D c_can_plat_write_reg_aligned_to_16bit; priv->read_reg32 =3D d_can_plat_read_reg32; diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index 7a90075529c3..0cbf2d7eeb7c 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -334,7 +334,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_pri= v *priv, } =20 cf->can_id =3D id & ESD_IDMASK; - cf->can_dlc =3D get_can_dlc(msg->msg.rx.dlc); + cf->can_dlc =3D get_can_dlc(msg->msg.rx.dlc & ~ESD_RTR); =20 if (id & ESD_EXTID) cf->can_id |=3D CAN_EFF_FLAG; diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index b16c5a2d92fb..a864951dfc43 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -356,6 +356,8 @@ static void gs_usb_recieve_bulk_callback(struct urb *ur= b) =20 gs_free_tx_context(txc); =20 + atomic_dec(&dev->active_tx_urbs); + netif_wake_queue(netdev); } =20 @@ -444,14 +446,6 @@ static void gs_usb_xmit_callback(struct urb *urb) urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); - - atomic_dec(&dev->active_tx_urbs); - - if (!netif_device_present(netdev)) - return; - - if (netif_queue_stopped(netdev)) - netif_wake_queue(netdev); } =20 static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, struct net_devic= e *netdev) diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_= usb.c index 4d47f224d705..0c2c23c7dfe0 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -1263,7 +1263,8 @@ static int kvaser_usb_close(struct net_device *netdev) if (err) netdev_warn(netdev, "Cannot flush queue, error %d\n", err); =20 - if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel)) + err =3D kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel); + if (err) netdev_warn(netdev, "Cannot reset card, error %d\n", err); =20 err =3D kvaser_usb_stop_chip(priv); diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index b787d1ceeba6..47eba38ae526 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -1051,10 +1051,12 @@ static long macvtap_ioctl(struct file *file, unsign= ed int cmd, return 0; =20 case TUNSETSNDBUF: - if (get_user(u, up)) + if (get_user(s, sp)) return -EFAULT; + if (s <=3D 0) + return -EINVAL; =20 - q->sk.sk_sndbuf =3D u; + q->sk.sk_sndbuf =3D s; return 0; =20 case TUNGETVNETHDRSZ: diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 1c843a4ac7a4..a87b76341502 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1647,6 +1647,9 @@ static int tun_set_iff(struct net *net, struct file *= file, struct ifreq *ifr) =20 if (!dev) return -ENOMEM; + err =3D dev_get_valid_name(net, dev, name); + if (err) + goto err_free_dev; =20 dev_net_set(dev, net); dev->rtnl_link_ops =3D &tun_link_ops; @@ -2051,6 +2054,10 @@ static long __tun_chr_ioctl(struct file *file, unsig= ned int cmd, ret =3D -EFAULT; break; } + if (sndbuf <=3D 0) { + ret =3D -EINVAL; + break; + } =20 tun->sndbuf =3D sndbuf; tun_set_sndbuf(tun); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/w= ireless/brcm80211/brcmfmac/fweh.c index 3f9cb894d001..b53ba992767b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -25,50 +25,6 @@ #include "fweh.h" #include "fwil.h" =20 -/** - * struct brcm_ethhdr - broadcom specific ether header. - * - * @subtype: subtype for this packet. - * @length: TODO: length of appended data. - * @version: version indication. - * @oui: OUI of this packet. - * @usr_subtype: subtype for this OUI. - */ -struct brcm_ethhdr { - __be16 subtype; - __be16 length; - u8 version; - u8 oui[3]; - __be16 usr_subtype; -} __packed; - -struct brcmf_event_msg_be { - __be16 version; - __be16 flags; - __be32 event_type; - __be32 status; - __be32 reason; - __be32 auth_type; - __be32 datalen; - u8 addr[ETH_ALEN]; - char ifname[IFNAMSIZ]; - u8 ifidx; - u8 bsscfgidx; -} __packed; - -/** - * struct brcmf_event - contents of broadcom event packet. - * - * @eth: standard ether header. - * @hdr: broadcom specific ether header. - * @msg: common part of the actual event message. - */ -struct brcmf_event { - struct ethhdr eth; - struct brcm_ethhdr hdr; - struct brcmf_event_msg_be msg; -} __packed; - /** * struct brcmf_fweh_queue_item - event item on event queue. * @@ -85,6 +41,7 @@ struct brcmf_fweh_queue_item { u8 ifidx; u8 ifaddr[ETH_ALEN]; struct brcmf_event_msg_be emsg; + u32 datalen; u8 data[0]; }; =20 @@ -292,6 +249,11 @@ static void brcmf_fweh_event_worker(struct work_struct= *work) brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data, min_t(u32, emsg.datalen, 64), "event payload, len=3D%d\n", emsg.datalen); + if (emsg.datalen > event->datalen) { + brcmf_err("event invalid length header=3D%d, msg=3D%d\n", + event->datalen, emsg.datalen); + goto event_free; + } =20 /* special handling of interface event */ if (event->code =3D=3D BRCMF_E_IF) { @@ -423,7 +385,8 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp) * dispatch the event to a registered handler (using worker). */ void brcmf_fweh_process_event(struct brcmf_pub *drvr, - struct brcmf_event *event_packet) + struct brcmf_event *event_packet, + u32 packet_len) { enum brcmf_fweh_event_code code; struct brcmf_fweh_info *fweh =3D &drvr->fweh; @@ -443,6 +406,10 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, if (code !=3D BRCMF_E_IF && !fweh->evt_handler[code]) return; =20 + if (datalen > BRCMF_DCMD_MAXLEN || + datalen + sizeof(*event_packet) > packet_len) + return; + if (in_interrupt()) alloc_flag =3D GFP_ATOMIC; =20 @@ -456,6 +423,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, /* use memcpy to get aligned event message */ memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); memcpy(event->data, data, datalen); + event->datalen =3D datalen; memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN); =20 brcmf_fweh_queue_event(fweh, event); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/w= ireless/brcm80211/brcmfmac/fweh.h index d26b47698f68..9b5416193bf6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h @@ -27,7 +27,6 @@ struct brcmf_pub; struct brcmf_if; struct brcmf_cfg80211_info; -struct brcmf_event; =20 /* list of firmware events */ #define BRCMF_FWEH_EVENT_ENUM_DEFLIST \ @@ -173,12 +172,54 @@ enum brcmf_fweh_event_code { /** * definitions for event packet validation. */ -#define BRCMF_EVENT_OUI_OFFSET 19 -#define BRCM_OUI "\x00\x10\x18" -#define DOT11_OUI_LEN 3 -#define BCMILCP_BCM_SUBTYPE_EVENT 1 +#define BRCM_OUI "\x00\x10\x18" +#define BCMILCP_BCM_SUBTYPE_EVENT 1 =20 =20 +/** + * struct brcm_ethhdr - broadcom specific ether header. + * + * @subtype: subtype for this packet. + * @length: TODO: length of appended data. + * @version: version indication. + * @oui: OUI of this packet. + * @usr_subtype: subtype for this OUI. + */ +struct brcm_ethhdr { + __be16 subtype; + __be16 length; + u8 version; + u8 oui[3]; + __be16 usr_subtype; +} __packed; + +struct brcmf_event_msg_be { + __be16 version; + __be16 flags; + __be32 event_type; + __be32 status; + __be32 reason; + __be32 auth_type; + __be32 datalen; + u8 addr[ETH_ALEN]; + char ifname[IFNAMSIZ]; + u8 ifidx; + u8 bsscfgidx; +} __packed; + +/** + * struct brcmf_event - contents of broadcom event packet. + * + * @eth: standard ether header. + * @hdr: broadcom specific ether header. + * @msg: common part of the actual event message. + */ +struct brcmf_event { + struct ethhdr eth; + struct brcm_ethhdr hdr; + struct brcmf_event_msg_be msg; +} __packed; + /** * struct brcmf_event_msg - firmware event message. * @@ -247,33 +288,34 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code); int brcmf_fweh_activate_events(struct brcmf_if *ifp); void brcmf_fweh_process_event(struct brcmf_pub *drvr, - struct brcmf_event *event_packet); + struct brcmf_event *event_packet, + u32 packet_len); =20 static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, struct sk_buff *skb) { struct brcmf_event *event_packet; - u8 *data; u16 usr_stype; =20 /* only process events when protocol matches */ if (skb->protocol !=3D cpu_to_be16(ETH_P_LINK_CTL)) return; =20 + if ((skb->len + ETH_HLEN) < sizeof(*event_packet)) + return; + /* check for BRCM oui match */ event_packet =3D (struct brcmf_event *)skb_mac_header(skb); - data =3D (u8 *)event_packet; - data +=3D BRCMF_EVENT_OUI_OFFSET; - if (memcmp(BRCM_OUI, data, DOT11_OUI_LEN)) + if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0], + sizeof(event_packet->hdr.oui))) return; =20 /* final match on usr_subtype */ - data +=3D DOT11_OUI_LEN; - usr_stype =3D get_unaligned_be16(data); + usr_stype =3D get_unaligned_be16(&event_packet->hdr.usr_subtype); if (usr_stype !=3D BCMILCP_BCM_SUBTYPE_EVENT) return; =20 - brcmf_fweh_process_event(drvr, event_packet); + brcmf_fweh_process_event(drvr, event_packet, skb->len + ETH_HLEN); } =20 #endif /* FWEH_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wi= reless/brcm80211/brcmfmac/p2p.c index f3445ac627e4..b489476532df 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -1363,6 +1363,11 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if= *ifp, u16 mgmt_type; u8 action; =20 + if (e->datalen < sizeof(*rxframe)) { + brcmf_dbg(SCAN, "Event data to small. Ignore\n"); + return 0; + } + ch.chspec =3D be16_to_cpu(rxframe->chanspec); cfg->d11inf.decchspec(&ch); /* Check if wpa_supplicant has registered for this frame */ @@ -1861,6 +1866,11 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brc= mf_if *ifp, brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code, e->reason); =20 + if (e->datalen < sizeof(*rxframe)) { + brcmf_dbg(SCAN, "Event data to small. Ignore\n"); + return 0; + } + ch.chspec =3D be16_to_cpu(rxframe->chanspec); cfg->d11inf.decchspec(&ch); =20 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/driver= s/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 26c5f3bdf2c5..c3e0a9aecd42 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3036,6 +3036,11 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, =20 brcmf_dbg(SCAN, "Enter\n"); =20 + if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) { + brcmf_dbg(SCAN, "Event data to small. Ignore\n"); + return 0; + } + if (e->event_code =3D=3D BRCMF_E_PFN_NET_LOST) { brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n"); return 0; diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wire= less/iwlwifi/mvm/mac80211.c index e83644dfaa6c..15175dd0cf86 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1004,6 +1004,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u= 8 *mac, struct iwl_mvm_mc_iter_data *data =3D _data; struct iwl_mvm *mvm =3D data->mvm; struct iwl_mcast_filter_cmd *cmd =3D mvm->mcast_filter_cmd; + struct iwl_host_cmd hcmd =3D { + .id =3D MCAST_FILTER_CMD, + .flags =3D CMD_ASYNC, + .dataflags[0] =3D IWL_HCMD_DFL_NOCOPY, + }; int ret, len; =20 /* if we don't have free ports, mcast frames will be dropped */ @@ -1018,7 +1023,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u= 8 *mac, memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); len =3D roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); =20 - ret =3D iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd); + hcmd.len[0] =3D len; + hcmd.data[0] =3D cmd; + + ret =3D iwl_mvm_send_cmd(mvm, &hcmd); if (ret) IWL_ERR(mvm, "mcast filter cmd error. ret=3D%d\n", ret); } diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 0ca2961a56a2..a8c9a4a361fb 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -514,7 +514,7 @@ static ssize_t driver_override_store(struct device *dev, const char *buf, size_t count) { struct pci_dev *pdev =3D to_pci_dev(dev); - char *driver_override, *old =3D pdev->driver_override, *cp; + char *driver_override, *old, *cp; =20 /* We need to keep extra room for a newline */ if (count >=3D (PAGE_SIZE - 1)) @@ -528,12 +528,15 @@ static ssize_t driver_override_store(struct device *d= ev, if (cp) *cp =3D '\0'; =20 + device_lock(dev); + old =3D pdev->driver_override; if (strlen(driver_override)) { pdev->driver_override =3D driver_override; } else { kfree(driver_override); pdev->driver_override =3D NULL; } + device_unlock(dev); =20 kfree(old); =20 @@ -544,8 +547,12 @@ static ssize_t driver_override_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pdev =3D to_pci_dev(dev); + ssize_t len; =20 - return snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); + device_lock(dev); + len =3D snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); + device_unlock(dev); + return len; } static DEVICE_ATTR_RW(driver_override); =20 diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 8004b071a9f2..a7a0b3e4f5ea 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -356,6 +356,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_de= vice *ccw_device) INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports); INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update); =20 + adapter->erp_action.adapter =3D adapter; + if (zfcp_qdio_setup(adapter)) goto failed; =20 @@ -512,6 +514,9 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter= *adapter, u64 wwpn, port->dev.groups =3D zfcp_port_attr_groups; port->dev.release =3D zfcp_port_release; =20 + port->erp_action.adapter =3D adapter; + port->erp_action.port =3D port; + if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { kfree(port); goto err_out; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index acb0b8c3989d..d9b2949de543 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -193,9 +193,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int n= eed, u32 act_status, atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &zfcp_sdev->status); erp_action =3D &zfcp_sdev->erp_action; - memset(erp_action, 0, sizeof(struct zfcp_erp_action)); - erp_action->port =3D port; - erp_action->sdev =3D sdev; + WARN_ON_ONCE(erp_action->port !=3D port); + WARN_ON_ONCE(erp_action->sdev !=3D sdev); if (!(atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_RUNNING)) act_status |=3D ZFCP_STATUS_ERP_CLOSE_ONLY; @@ -208,8 +207,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int n= eed, u32 act_status, zfcp_erp_action_dismiss_port(port); atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); erp_action =3D &port->erp_action; - memset(erp_action, 0, sizeof(struct zfcp_erp_action)); - erp_action->port =3D port; + WARN_ON_ONCE(erp_action->port !=3D port); + WARN_ON_ONCE(erp_action->sdev !=3D NULL); if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) act_status |=3D ZFCP_STATUS_ERP_CLOSE_ONLY; break; @@ -219,7 +218,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int n= eed, u32 act_status, zfcp_erp_action_dismiss_adapter(adapter); atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); erp_action =3D &adapter->erp_action; - memset(erp_action, 0, sizeof(struct zfcp_erp_action)); + WARN_ON_ONCE(erp_action->port !=3D NULL); + WARN_ON_ONCE(erp_action->sdev !=3D NULL); if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_RUNNING)) act_status |=3D ZFCP_STATUS_ERP_CLOSE_ONLY; @@ -229,7 +229,11 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int = need, u32 act_status, return NULL; } =20 - erp_action->adapter =3D adapter; + WARN_ON_ONCE(erp_action->adapter !=3D adapter); + memset(&erp_action->list, 0, sizeof(erp_action->list)); + memset(&erp_action->timer, 0, sizeof(erp_action->timer)); + erp_action->step =3D ZFCP_ERP_STEP_UNINITIALIZED; + erp_action->fsf_req_id =3D 0; erp_action->action =3D need; erp_action->status =3D act_status; =20 diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index b495c085a0b5..0c03ae19b689 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -136,10 +136,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *= sdev) struct zfcp_unit *unit; int npiv =3D adapter->connection_features & FSF_FEATURE_NPIV_MODE; =20 + zfcp_sdev->erp_action.adapter =3D adapter; + zfcp_sdev->erp_action.sdev =3D sdev; + port =3D zfcp_get_port_by_wwpn(adapter, rport->port_name); if (!port) return -ENXIO; =20 + zfcp_sdev->erp_action.port =3D port; + unit =3D zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev)); if (unit) put_device(&unit->dev); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 877fd93766ce..fc6801fe134e 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1727,7 +1727,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct= scsi_cmnd *sc) =20 if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { reason =3D FAILURE_SESSION_IN_RECOVERY; - sc->result =3D DID_REQUEUE; + sc->result =3D DID_REQUEUE << 16; goto fault; } =20 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 0813a2dcd3d1..83ff6cba873e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5242,6 +5242,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "2999 Unsupported SLI4 Parameters " "Extents and RPI headers enabled.\n"); + rc =3D -EIO; goto out_free_bsmbx; } } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index c31e1cb009af..cf13b561af83 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -962,6 +962,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsig= ned char *inq_result, if (*bflags & BLIST_NO_DIF) sdev->no_dif =3D 1; =20 + if (*bflags & BLIST_UNMAP_LIMIT_WS) + sdev->unmap_limit_for_ws =3D 1; + sdev->eh_timeout =3D SCSI_DEFAULT_EH_TIMEOUT; =20 if (*bflags & BLIST_TRY_VPD_PAGES) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3dcb3c080c1e..c50cfd16a976 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -651,13 +651,21 @@ static void sd_config_discard(struct scsi_disk *sdkp,= unsigned int mode) break; =20 case SD_LBP_WS16: - max_blocks =3D min_not_zero(sdkp->max_ws_blocks, - (u32)SD_MAX_WS16_BLOCKS); + if (sdkp->device->unmap_limit_for_ws) + max_blocks =3D sdkp->max_unmap_blocks; + else + max_blocks =3D sdkp->max_ws_blocks; + + max_blocks =3D min_not_zero(max_blocks, (u32)SD_MAX_WS16_BLOCKS); break; =20 case SD_LBP_WS10: - max_blocks =3D min_not_zero(sdkp->max_ws_blocks, - (u32)SD_MAX_WS10_BLOCKS); + if (sdkp->device->unmap_limit_for_ws) + max_blocks =3D sdkp->max_unmap_blocks; + else + max_blocks =3D sdkp->max_ws_blocks; + + max_blocks =3D min_not_zero(max_blocks, (u32)SD_MAX_WS10_BLOCKS); break; =20 case SD_LBP_ZERO: diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7= 192.c index 26b2cdca29ad..c7aaf2bb1018 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -206,11 +206,9 @@ static int ad7192_setup(struct ad7192_state *st, struct iio_dev *indio_dev =3D spi_get_drvdata(st->sd.spi); unsigned long long scale_uv; int i, ret, id; - u8 ones[6]; =20 /* reset the serial interface */ - memset(&ones, 0xFF, 6); - ret =3D spi_write(st->sd.spi, &ones, 6); + ret =3D ad_sd_reset(&st->sd, 48); if (ret < 0) goto out; msleep(1); /* Wait for at least 500us */ diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/mete= r/ade7759.c index ea0c9debf8bf..14e3eca3ff35 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -124,7 +124,7 @@ static int ade7759_spi_read_reg_40(struct device *dev, reg_address); goto error_ret; } - *val =3D ((u64)st->rx[1] << 32) | (st->rx[2] << 24) | + *val =3D ((u64)st->rx[1] << 32) | ((u64)st->rx[2] << 24) | (st->rx[3] << 16) | (st->rx[4] << 8) | st->rx[5]; =20 error_ret: diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ef71827f92a3..58034df6351b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1775,6 +1775,9 @@ static const struct usb_device_id acm_ids[] =3D { { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */ .driver_info =3D NO_UNION_NORMAL, /* reports zero length descriptor */ }, + { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */ + .driver_info =3D NO_UNION_NORMAL, /* has misplaced union descriptor */ + }, =20 { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */ .driver_info =3D CLEAR_HALT_CONDITIONS, diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 063d9767d6fe..13d31422d6b7 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -519,6 +519,9 @@ static int usb_parse_configuration(struct usb_device *d= ev, int cfgidx, unsigned iad_num =3D 0; =20 memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); + nintf =3D nintf_orig =3D config->desc.bNumInterfaces; + config->desc.bNumInterfaces =3D 0; // Adjusted later + if (config->desc.bDescriptorType !=3D USB_DT_CONFIG || config->desc.bLength < USB_DT_CONFIG_SIZE || config->desc.bLength > size) { @@ -532,7 +535,6 @@ static int usb_parse_configuration(struct usb_device *d= ev, int cfgidx, buffer +=3D config->desc.bLength; size -=3D config->desc.bLength; =20 - nintf =3D nintf_orig =3D config->desc.bNumInterfaces; if (nintf > USB_MAXINTERFACES) { dev_warn(ddev, "config %d has too many interfaces: %d, " "using maximum allowed: %d\n", @@ -824,7 +826,7 @@ int usb_get_configuration(struct usb_device *dev) } =20 if (dev->quirks & USB_QUIRK_DELAY_INIT) - msleep(100); + msleep(200); =20 result =3D usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 598e9adf8858..b4dd4821d1fd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2625,13 +2625,16 @@ static int hub_port_wait_reset(struct usb_hub *hub,= int port1, if (!(portstatus & USB_PORT_STAT_CONNECTION)) return -ENOTCONN; =20 - /* bomb out completely if the connection bounced. A USB 3.0 - * connection may bounce if multiple warm resets were issued, + /* Retry if connect change is set but status is still connected. + * A USB 3.0 connection may bounce if multiple warm resets were issued, * but the device may have successfully re-connected. Ignore it. */ if (!hub_is_superspeed(hub->hdev) && - (portchange & USB_PORT_STAT_C_CONNECTION)) - return -ENOTCONN; + (portchange & USB_PORT_STAT_C_CONNECTION)) { + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + return -EAGAIN; + } =20 if (!(portstatus & USB_PORT_STAT_ENABLE)) return -EBUSY; @@ -4699,7 +4702,7 @@ static void hub_port_connect(struct usb_hub *hub, int= port1, u16 portstatus, goto loop; =20 if (udev->quirks & USB_QUIRK_DELAY_INIT) - msleep(1000); + msleep(2000); =20 /* consecutive bus-powered hubs aren't reliable; they can * violate the voltage drop budget. if the new child has diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index c9b564e362c8..25d0eed708a3 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -218,6 +218,10 @@ static const struct usb_device_id usb_quirk_list[] =3D= { /* Corsair Strafe RGB */ { USB_DEVICE(0x1b1c, 0x1b20), .driver_info =3D USB_QUIRK_DELAY_INIT }, =20 + /* MIDI keyboard WORLDE MINI */ + { USB_DEVICE(0x1c75, 0x0204), .driver_info =3D + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Acer C120 LED Projector */ { USB_DEVICE(0x1de1, 0xc102), .driver_info =3D USB_QUIRK_NO_LPM }, =20 diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index b8a961ba1d2b..38042f6d9c04 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1815,6 +1815,8 @@ static DEVICE_ATTR_RO(suspended); static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driv= er) { struct usb_composite_dev *cdev =3D get_gadget_data(gadget); + struct usb_gadget_strings *gstr =3D cdev->driver->strings[0]; + struct usb_string *dev_str =3D gstr->strings; =20 /* composite_disconnect() must already have been called * by the underlying peripheral controller driver! @@ -1834,6 +1836,9 @@ static void __composite_unbind(struct usb_gadget *gad= get, bool unbind_driver) =20 composite_dev_cleanup(cdev); =20 + if (dev_str[USB_GADGET_MANUFACTURER_IDX].s =3D=3D cdev->def_manufacturer) + dev_str[USB_GADGET_MANUFACTURER_IDX].s =3D ""; + kfree(cdev->def_manufacturer); kfree(cdev); set_gadget_data(gadget, NULL); diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index d20222e56419..8c73186fc0e8 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -173,6 +173,8 @@ struct dummy_hcd { =20 struct usb_device *udev; struct list_head urbp_list; + struct urbp *next_frame_urbp; + u32 stream_en_ep; u8 num_stream[30 / 2]; =20 @@ -189,11 +191,13 @@ struct dummy { */ struct dummy_ep ep[DUMMY_ENDPOINTS]; int address; + int callback_usage; struct usb_gadget gadget; struct usb_gadget_driver *driver; struct dummy_request fifo_req; u8 fifo_buf[FIFO_SIZE]; u16 devstatus; + unsigned ints_enabled:1; unsigned udc_suspended:1; unsigned pullup:1; =20 @@ -311,11 +315,10 @@ static void set_link_state_by_speed(struct dummy_hcd = *dum_hcd) USB_PORT_STAT_CONNECTION) =3D=3D 0) dum_hcd->port_status |=3D (USB_PORT_STAT_C_CONNECTION << 16); - if ((dum_hcd->port_status & - USB_PORT_STAT_ENABLE) =3D=3D 1 && - (dum_hcd->port_status & - USB_SS_PORT_LS_U0) =3D=3D 1 && - dum_hcd->rh_state !=3D DUMMY_RH_SUSPENDED) + if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) && + (dum_hcd->port_status & + USB_PORT_STAT_LINK_STATE) =3D=3D USB_SS_PORT_LS_U0 && + dum_hcd->rh_state !=3D DUMMY_RH_SUSPENDED) dum_hcd->active =3D 1; } } else { @@ -352,6 +355,7 @@ static void set_link_state_by_speed(struct dummy_hcd *d= um_hcd) static void set_link_state(struct dummy_hcd *dum_hcd) { struct dummy *dum =3D dum_hcd->dum; + unsigned int power_bit; =20 dum_hcd->active =3D 0; if (dum->pullup) @@ -362,36 +366,40 @@ static void set_link_state(struct dummy_hcd *dum_hcd) return; =20 set_link_state_by_speed(dum_hcd); + power_bit =3D (dummy_hcd_to_hcd(dum_hcd)->speed =3D=3D HCD_USB3 ? + USB_SS_PORT_STAT_POWER : USB_PORT_STAT_POWER); =20 if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) =3D=3D 0 || dum_hcd->active) dum_hcd->resuming =3D 0; =20 /* if !connected or reset */ - if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) =3D=3D 0 || + if ((dum_hcd->port_status & power_bit) =3D=3D 0 || (dum_hcd->port_status & USB_PORT_STAT_RESET) !=3D 0) { /* * We're connected and not reset (reset occurred now), * and driver attached - disconnect! */ - if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) !=3D 0 && + if ((dum_hcd->old_status & power_bit) !=3D 0 && (dum_hcd->old_status & USB_PORT_STAT_RESET) =3D=3D 0 && - dum->driver) { + dum->ints_enabled) { stop_activity(dum); + ++dum->callback_usage; spin_unlock(&dum->lock); dum->driver->disconnect(&dum->gadget); spin_lock(&dum->lock); + --dum->callback_usage; } - } else if (dum_hcd->active !=3D dum_hcd->old_active) { - if (dum_hcd->old_active && dum->driver->suspend) { - spin_unlock(&dum->lock); + } else if (dum_hcd->active !=3D dum_hcd->old_active && + dum->ints_enabled) { + ++dum->callback_usage; + spin_unlock(&dum->lock); + if (dum_hcd->old_active && dum->driver->suspend) dum->driver->suspend(&dum->gadget); - spin_lock(&dum->lock); - } else if (!dum_hcd->old_active && dum->driver->resume) { - spin_unlock(&dum->lock); + else if (!dum_hcd->old_active && dum->driver->resume) dum->driver->resume(&dum->gadget); - spin_lock(&dum->lock); - } + spin_lock(&dum->lock); + --dum->callback_usage; } =20 dum_hcd->old_status =3D dum_hcd->port_status; @@ -907,9 +915,12 @@ static int dummy_udc_start(struct usb_gadget *g, * can't enumerate without help from the driver we're binding. */ =20 + spin_lock_irq(&dum->lock); dum->devstatus =3D 0; =20 dum->driver =3D driver; + dum->ints_enabled =3D 1; + spin_unlock_irq(&dum->lock); dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n", driver->driver.name); return 0; @@ -925,7 +936,19 @@ static int dummy_udc_stop(struct usb_gadget *g, dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n", driver->driver.name); =20 + spin_lock_irq(&dum->lock); + dum->ints_enabled =3D 0; + stop_activity(dum); + + /* emulate synchronize_irq(): wait for callbacks to finish */ + while (dum->callback_usage > 0) { + spin_unlock_irq(&dum->lock); + usleep_range(1000, 2000); + spin_lock_irq(&dum->lock); + } + dum->driver =3D NULL; + spin_unlock_irq(&dum->lock); =20 return 0; } @@ -974,7 +997,12 @@ static int dummy_udc_probe(struct platform_device *pde= v) dum =3D *((void **)dev_get_platdata(&pdev->dev)); dum->gadget.name =3D gadget_name; dum->gadget.ops =3D &dummy_ops; - dum->gadget.max_speed =3D USB_SPEED_SUPER; + if (mod_data.is_super_speed) + dum->gadget.max_speed =3D USB_SPEED_SUPER; + else if (mod_data.is_high_speed) + dum->gadget.max_speed =3D USB_SPEED_HIGH; + else + dum->gadget.max_speed =3D USB_SPEED_FULL; =20 dum->gadget.dev.parent =3D &pdev->dev; init_dummy_udc_hw(dum); @@ -1184,6 +1212,8 @@ static int dummy_urb_enqueue( =20 list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list); urb->hcpriv =3D urbp; + if (!dum_hcd->next_frame_urbp) + dum_hcd->next_frame_urbp =3D urbp; if (usb_pipetype(urb->pipe) =3D=3D PIPE_CONTROL) urb->error_count =3D 1; /* mark as a new urb */ =20 @@ -1446,6 +1476,8 @@ static struct dummy_ep *find_endpoint(struct dummy *d= um, u8 address) if (!is_active((dum->gadget.speed =3D=3D USB_SPEED_SUPER ? dum->ss_hcd : dum->hs_hcd))) return NULL; + if (!dum->ints_enabled) + return NULL; if ((address & ~USB_DIR_IN) =3D=3D 0) return &dum->ep[0]; for (i =3D 1; i < DUMMY_ENDPOINTS; i++) { @@ -1687,6 +1719,7 @@ static void dummy_timer(unsigned long _dum_hcd) spin_unlock_irqrestore(&dum->lock, flags); return; } + dum_hcd->next_frame_urbp =3D NULL; =20 for (i =3D 0; i < DUMMY_ENDPOINTS; i++) { if (!ep_name[i]) @@ -1703,6 +1736,10 @@ static void dummy_timer(unsigned long _dum_hcd) int type; int status =3D -EINPROGRESS; =20 + /* stop when we reach URBs queued after the timer interrupt */ + if (urbp =3D=3D dum_hcd->next_frame_urbp) + break; + urb =3D urbp->urb; if (urb->unlinked) goto return_urb; @@ -1782,10 +1819,12 @@ static void dummy_timer(unsigned long _dum_hcd) * until setup() returns; no reentrancy issues etc. */ if (value > 0) { + ++dum->callback_usage; spin_unlock(&dum->lock); value =3D dum->driver->setup(&dum->gadget, &setup); spin_lock(&dum->lock); + --dum->callback_usage; =20 if (value >=3D 0) { /* no delays (max 64KB data stage) */ @@ -2490,8 +2529,6 @@ static struct hc_driver dummy_hcd =3D { .product_desc =3D "Dummy host controller", .hcd_priv_size =3D sizeof(struct dummy_hcd), =20 - .flags =3D HCD_USB3 | HCD_SHARED, - .reset =3D dummy_setup, .start =3D dummy_start, .stop =3D dummy_stop, @@ -2520,8 +2557,12 @@ static int dummy_hcd_probe(struct platform_device *p= dev) dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); dum =3D *((void **)dev_get_platdata(&pdev->dev)); =20 - if (!mod_data.is_super_speed) + if (mod_data.is_super_speed) + dummy_hcd.flags =3D HCD_USB3 | HCD_SHARED; + else if (mod_data.is_high_speed) dummy_hcd.flags =3D HCD_USB2; + else + dummy_hcd.flags =3D HCD_USB11; hs_hcd =3D usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); if (!hs_hcd) return -ENOMEM; diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mas= s_storage.c index 2234c3a5ed8e..f0db2ca816c0 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -307,8 +307,6 @@ struct fsg_common { struct completion thread_notifier; struct task_struct *thread_task; =20 - /* Callback functions. */ - const struct fsg_operations *ops; /* Gadget's private data. */ void *private_data; =20 @@ -2498,6 +2496,8 @@ static void handle_exception(struct fsg_common *commo= n) static int fsg_main_thread(void *common_) { struct fsg_common *common =3D common_; + struct fsg_lun **curlun_it; + unsigned i; =20 /* * Allow the thread to be killed by a signal, but set the signal mask @@ -2559,22 +2559,18 @@ static int fsg_main_thread(void *common_) common->thread_task =3D NULL; spin_unlock_irq(&common->lock); =20 - if (!common->ops || !common->ops->thread_exits - || common->ops->thread_exits(common) < 0) { - struct fsg_lun **curlun_it =3D common->luns; - unsigned i =3D common->nluns; + /* Eject media from all LUNs */ + curlun_it =3D common->luns; + i =3D common->nluns; =20 - down_write(&common->filesem); - for (; i--; ++curlun_it) { - struct fsg_lun *curlun =3D *curlun_it; - if (!curlun || !fsg_lun_is_open(curlun)) - continue; + down_write(&common->filesem); + for (; i--; ++curlun_it) { + struct fsg_lun *curlun =3D *curlun_it; =20 + if (curlun && fsg_lun_is_open(curlun)) fsg_lun_close(curlun); - curlun->unit_attention_data =3D SS_MEDIUM_NOT_PRESENT; - } - up_write(&common->filesem); } + up_write(&common->filesem); =20 /* Let fsg_unbind() know the thread has exited */ complete_and_exit(&common->thread_notifier, 0); @@ -2842,13 +2838,6 @@ int fsg_common_set_nluns(struct fsg_common *common, = int nluns) } EXPORT_SYMBOL_GPL(fsg_common_set_nluns); =20 -void fsg_common_set_ops(struct fsg_common *common, - const struct fsg_operations *ops) -{ - common->ops =3D ops; -} -EXPORT_SYMBOL_GPL(fsg_common_set_ops); - void fsg_common_free_buffers(struct fsg_common *common) { _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); diff --git a/drivers/usb/gadget/f_mass_storage.h b/drivers/usb/gadget/f_mas= s_storage.h index b4866fcef30b..bf0fe5cda863 100644 --- a/drivers/usb/gadget/f_mass_storage.h +++ b/drivers/usb/gadget/f_mass_storage.h @@ -60,17 +60,6 @@ struct fsg_module_parameters { struct fsg_common; =20 /* FSF callback functions */ -struct fsg_operations { - /* - * Callback function to call when thread exits. If no - * callback is set or it returns value lower then zero MSF - * will force eject all LUNs it operates on (including those - * marked as non-removable or with prevent_medium_removal flag - * set). - */ - int (*thread_exits)(struct fsg_common *common); -}; - struct fsg_lun_opts { struct config_group group; struct fsg_lun *lun; @@ -145,9 +134,6 @@ void fsg_common_free_luns(struct fsg_common *common); =20 int fsg_common_set_nluns(struct fsg_common *common, int nluns); =20 -void fsg_common_set_ops(struct fsg_common *common, - const struct fsg_operations *ops); - int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config= *cfg, unsigned int id, const char *name, const char **name_pfx); diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index ac3c91c7e627..0225e6dafaad 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -26,7 +26,7 @@ #include #include #include - +#include #include #include =20 @@ -113,6 +113,7 @@ enum ep0_state { struct dev_data { spinlock_t lock; atomic_t count; + int udc_usage; enum ep0_state state; /* P: lock */ struct usb_gadgetfs_event event [N_EVENT]; unsigned ev_next; @@ -620,9 +621,9 @@ static void ep_aio_complete(struct usb_ep *ep, struct u= sb_request *req) priv->actual =3D req->actual; schedule_work(&priv->work); } - spin_unlock(&epdata->dev->lock); =20 usb_ep_free_request(ep, req); + spin_unlock(&epdata->dev->lock); put_ep(epdata); } =20 @@ -1011,9 +1012,11 @@ ep0_read (struct file *fd, char __user *buf, size_t = len, loff_t *ptr) struct usb_request *req =3D dev->req; =20 if ((retval =3D setup_req (ep, req, 0)) =3D=3D 0) { + ++dev->udc_usage; spin_unlock_irq (&dev->lock); retval =3D usb_ep_queue (ep, req, GFP_KERNEL); spin_lock_irq (&dev->lock); + --dev->udc_usage; } dev->state =3D STATE_DEV_CONNECTED; =20 @@ -1055,11 +1058,14 @@ ep0_read (struct file *fd, char __user *buf, size_t= len, loff_t *ptr) retval =3D -EIO; else { len =3D min (len, (size_t)dev->req->actual); -// FIXME don't call this with the spinlock held ... + ++dev->udc_usage; + spin_unlock_irq(&dev->lock); if (copy_to_user (buf, dev->req->buf, len)) retval =3D -EFAULT; else retval =3D len; + spin_lock_irq(&dev->lock); + --dev->udc_usage; clean_req (dev->gadget->ep0, dev->req); /* NOTE userspace can't yet choose to stall */ } @@ -1205,6 +1211,7 @@ ep0_write (struct file *fd, const char __user *buf, s= ize_t len, loff_t *ptr) retval =3D setup_req (dev->gadget->ep0, dev->req, len); if (retval =3D=3D 0) { dev->state =3D STATE_DEV_CONNECTED; + ++dev->udc_usage; spin_unlock_irq (&dev->lock); if (copy_from_user (dev->req->buf, buf, len)) retval =3D -EFAULT; @@ -1215,12 +1222,13 @@ ep0_write (struct file *fd, const char __user *buf,= size_t len, loff_t *ptr) dev->gadget->ep0, dev->req, GFP_KERNEL); } + spin_lock_irq(&dev->lock); + --dev->udc_usage; if (retval < 0) { - spin_lock_irq (&dev->lock); clean_req (dev->gadget->ep0, dev->req); - spin_unlock_irq (&dev->lock); } else retval =3D len; + spin_unlock_irq(&dev->lock); =20 return retval; } @@ -1313,9 +1321,21 @@ static long dev_ioctl (struct file *fd, unsigned cod= e, unsigned long value) struct usb_gadget *gadget =3D dev->gadget; long ret =3D -ENOTTY; =20 - if (gadget->ops->ioctl) + spin_lock_irq(&dev->lock); + if (dev->state =3D=3D STATE_DEV_OPENED || + dev->state =3D=3D STATE_DEV_UNBOUND) { + /* Not bound to a UDC */ + } else if (gadget->ops->ioctl) { + ++dev->udc_usage; + spin_unlock_irq(&dev->lock); + ret =3D gadget->ops->ioctl (gadget, code, value); =20 + spin_lock_irq(&dev->lock); + --dev->udc_usage; + } + spin_unlock_irq(&dev->lock); + return ret; } =20 @@ -1546,10 +1566,12 @@ gadgetfs_setup (struct usb_gadget *gadget, const st= ruct usb_ctrlrequest *ctrl) if (value < 0) break; =20 + ++dev->udc_usage; spin_unlock (&dev->lock); value =3D usb_ep_queue (gadget->ep0, dev->req, GFP_KERNEL); spin_lock (&dev->lock); + --dev->udc_usage; if (value < 0) { clean_req (gadget->ep0, dev->req); break; @@ -1573,8 +1595,12 @@ gadgetfs_setup (struct usb_gadget *gadget, const str= uct usb_ctrlrequest *ctrl) req->length =3D value; req->zero =3D value < w_length; =20 + ++dev->udc_usage; spin_unlock (&dev->lock); value =3D usb_ep_queue (gadget->ep0, req, GFP_KERNEL); + spin_lock(&dev->lock); + --dev->udc_usage; + spin_unlock(&dev->lock); if (value < 0) { DBG (dev, "ep_queue --> %d\n", value); req->status =3D 0; @@ -1601,21 +1627,24 @@ static void destroy_ep_files (struct dev_data *dev) /* break link to FS */ ep =3D list_first_entry (&dev->epfiles, struct ep_data, epfiles); list_del_init (&ep->epfiles); + spin_unlock_irq (&dev->lock); + dentry =3D ep->dentry; ep->dentry =3D NULL; parent =3D dentry->d_parent->d_inode; =20 /* break link to controller */ + mutex_lock(&ep->lock); if (ep->state =3D=3D STATE_EP_ENABLED) (void) usb_ep_disable (ep->ep); ep->state =3D STATE_EP_UNBOUND; usb_ep_free_request (ep->ep, ep->req); ep->ep =3D NULL; + mutex_unlock(&ep->lock); + wake_up (&ep->wait); put_ep (ep); =20 - spin_unlock_irq (&dev->lock); - /* break link to dcache */ mutex_lock (&parent->i_mutex); d_delete (dentry); @@ -1688,6 +1717,11 @@ gadgetfs_unbind (struct usb_gadget *gadget) =20 spin_lock_irq (&dev->lock); dev->state =3D STATE_DEV_UNBOUND; + while (dev->udc_usage > 0) { + spin_unlock_irq(&dev->lock); + usleep_range(1000, 2000); + spin_lock_irq(&dev->lock); + } spin_unlock_irq (&dev->lock); =20 destroy_ep_files (dev); @@ -1764,9 +1798,10 @@ static void gadgetfs_suspend (struct usb_gadget *gadget) { struct dev_data *dev =3D get_gadget_data (gadget); + unsigned long flags; =20 INFO (dev, "suspended from state %d\n", dev->state); - spin_lock (&dev->lock); + spin_lock_irqsave(&dev->lock, flags); switch (dev->state) { case STATE_DEV_SETUP: // VERY odd... host died?? case STATE_DEV_CONNECTED: @@ -1777,7 +1812,7 @@ gadgetfs_suspend (struct usb_gadget *gadget) default: break; } - spin_unlock (&dev->lock); + spin_unlock_irqrestore(&dev->lock, flags); } =20 static struct usb_gadget_driver gadgetfs_driver =3D { diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_st= orage.c index 8e27a8c96444..c7ca12a109e1 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -121,15 +121,6 @@ static unsigned int fsg_num_buffers =3D CONFIG_USB_GAD= GET_STORAGE_NUM_BUFFERS; =20 FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); =20 -static unsigned long msg_registered; -static void msg_cleanup(void); - -static int msg_thread_exits(struct fsg_common *common) -{ - msg_cleanup(); - return 0; -} - static int __init msg_do_config(struct usb_configuration *c) { struct fsg_opts *opts; @@ -172,9 +163,6 @@ static struct usb_configuration msg_config_driver =3D { =20 static int __init msg_bind(struct usb_composite_dev *cdev) { - static const struct fsg_operations ops =3D { - .thread_exits =3D msg_thread_exits, - }; struct fsg_opts *opts; struct fsg_config config; int status; @@ -195,8 +183,6 @@ static int __init msg_bind(struct usb_composite_dev *cd= ev) if (status) goto fail_set_nluns; =20 - fsg_common_set_ops(opts->common, &ops); - status =3D fsg_common_set_cdev(opts->common, cdev, config.can_stall); if (status) goto fail_set_cdev; @@ -221,7 +207,6 @@ static int __init msg_bind(struct usb_composite_dev *cd= ev) usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&cdev->gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); - set_bit(0, &msg_registered); return 0; =20 fail_string_ids: @@ -268,9 +253,8 @@ static int __init msg_init(void) } module_init(msg_init); =20 -static void msg_cleanup(void) +static void __exit msg_cleanup(void) { - if (test_and_clear_bit(0, &msg_registered)) - usb_composite_unregister(&msg_driver); + usb_composite_unregister(&msg_driver); } module_exit(msg_cleanup); diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 300b3a71383b..b464ed5e129e 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -1941,11 +1941,8 @@ stop_activity (struct net2280 *dev, struct usb_gadge= t_driver *driver) nuke (&dev->ep [i]); =20 /* report disconnect; the driver is already quiesced */ - if (driver) { - spin_unlock(&dev->lock); + if (driver) driver->disconnect(&dev->gadget); - spin_lock(&dev->lock); - } =20 usb_reinit (dev); } diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 677b3714557e..67733f044c22 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -1024,7 +1024,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); * * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS. * It signals to the BIOS that the OS wants control of the host controller, - * and then waits 5 seconds for the BIOS to hand over control. + * and then waits 1 second for the BIOS to hand over control. * If we timeout, assume the BIOS is broken and take control anyway. */ static void quirk_usb_handoff_xhci(struct pci_dev *pdev) @@ -1070,9 +1070,9 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pd= ev) if (val & XHCI_HC_BIOS_OWNED) { writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset); =20 - /* Wait for 5 seconds with 10 microsecond polling interval */ + /* Wait for 1 second with 10 microsecond polling interval */ timeout =3D handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, - 0, 5000, 10); + 0, 1000000, 10); =20 /* Assume a buggy BIOS and take HC ownership anyway */ if (timeout) { @@ -1100,7 +1100,7 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pd= ev) * operational or runtime registers. Wait 5 seconds and no more. */ timeout =3D handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_CNR, 0, - 5000, 10); + 5000000, 10); /* Assume a buggy HC and start HC initialization anyway */ if (timeout) { val =3D readl(op_reg_base + XHCI_STS_OFFSET); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 76628f9e39ba..f16bf70b54ba 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -293,15 +293,25 @@ static int xhci_stop_device(struct xhci_hcd *xhci, in= t slot_id, int suspend) GFP_NOWAIT); if (!command) { spin_unlock_irqrestore(&xhci->lock, flags); - xhci_free_command(xhci, cmd); - return -ENOMEM; + ret =3D -ENOMEM; + goto cmd_cleanup; + } =20 + ret =3D xhci_queue_stop_endpoint(xhci, command, slot_id, + i, suspend); + if (ret) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_free_command(xhci, command); + goto cmd_cleanup; } - xhci_queue_stop_endpoint(xhci, command, slot_id, i, - suspend); } } - xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); + ret =3D xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); + if (ret) { + spin_unlock_irqrestore(&xhci->lock, flags); + goto cmd_cleanup; + } + xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); =20 @@ -312,6 +322,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int = slot_id, int suspend) xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); ret =3D -ETIME; } + +cmd_cleanup: xhci_free_command(xhci, cmd); return ret; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 746ffa720ae4..08057459c8e6 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1437,7 +1437,7 @@ struct xhci_bus_state { =20 static inline unsigned int hcd_index(struct usb_hcd *hcd) { - if (hcd->speed =3D=3D HCD_USB3) + if (hcd->speed >=3D HCD_USB3) return 0; else return 1; diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/f= ifo.c index 2a540e4b5c61..70d4b6ed21a3 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -261,11 +261,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo) { struct usbhs_priv *priv =3D usbhs_pipe_to_priv(pipe); + int ret =3D 0; =20 - if (!usbhs_pipe_is_dcp(pipe)) - usbhsf_fifo_barrier(priv, fifo); + if (!usbhs_pipe_is_dcp(pipe)) { + /* + * This driver checks the pipe condition first to avoid -EBUSY + * from usbhsf_fifo_barrier() with about 10 msec delay in + * the interrupt handler if the pipe is RX direction and empty. + */ + if (usbhs_pipe_is_dir_in(pipe)) + ret =3D usbhs_pipe_is_accessible(pipe); + if (!ret) + ret =3D usbhsf_fifo_barrier(priv, fifo); + } =20 - usbhs_write(priv, fifo->ctr, BCLR); + /* + * if non-DCP pipe, this driver should set BCLR when + * usbhsf_fifo_barrier() returns 0. + */ + if (!ret) + usbhs_write(priv, fifo->ctr, BCLR); } =20 static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, @@ -813,9 +828,9 @@ static void xfer_work(struct work_struct *work) dev_dbg(dev, " %s %d (%d/ %d)\n", fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); =20 - usbhsf_dma_start(pipe, fifo); usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); dma_async_issue_pending(chan); + usbhsf_dma_start(pipe, fifo); usbhs_pipe_enable(pipe); =20 xfer_work_end: diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8f8f4aed5fbb..13395320f9bc 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -170,6 +170,7 @@ static const struct usb_device_id id_table[] =3D { { 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, 0xE032) }, /* ELV TFD500 Data Logger */ { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9c0cfba2c803..bf2fbb0798fb 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1028,6 +1028,8 @@ static const struct usb_device_id id_table_combined[]= =3D { { USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) }, { USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID), .driver_info =3D (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) }, + { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) }, { } /* Terminating entry */ }; =20 diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_si= o_ids.h index f34bc435d90a..c03449e3665a 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -609,6 +609,13 @@ #define ADI_GNICE_PID 0xF000 #define ADI_GNICEPLUS_PID 0xF001 =20 +/* + * Cypress WICED USB UART + */ +#define CYPRESS_VID 0x04B4 +#define CYPRESS_WICED_BT_USB_PID 0x009B +#define CYPRESS_WICED_WL_USB_PID 0xF900 + /* * Microchip Technology, Inc. * diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 39e683096e94..45182c65fa1f 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -45,6 +45,7 @@ struct metrousb_private { static const struct usb_device_id id_table[] =3D { { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) }, { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, + { USB_DEVICE_INTERFACE_CLASS(0x0c2e, 0x0730, 0xff) }, /* MS7820 */ { }, /* Terminating entry. */ }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 17d28273e03c..ed203e1a4d96 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -524,6 +524,7 @@ static void option_instat_callback(struct urb *urb); =20 /* TP-LINK Incorporated products */ #define TPLINK_VENDOR_ID 0x2357 +#define TPLINK_PRODUCT_LTE 0x000D #define TPLINK_PRODUCT_MA180 0x0201 =20 /* Changhong products */ @@ -2022,6 +2023,7 @@ static const struct usb_device_id option_ids[] =3D { { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) }, { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) }, + { USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, TPLINK_PRODUCT_LTE, 0xf= f, 0x00, 0x00) }, /* TP-Link LTE Module */ { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), .driver_info =3D (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(TPLINK_VENDOR_ID, 0x9000), /* TP-Link MA260 */ diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 23c303b2a3a2..996dc09b00b8 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -172,6 +172,10 @@ static const struct usb_device_id id_table[] =3D { {DEVICE_SWI(0x413c, 0x81b3)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobi= le Broadband Card (rev3) */ {DEVICE_SWI(0x413c, 0x81b5)}, /* Dell Wireless 5811e QDL */ {DEVICE_SWI(0x413c, 0x81b6)}, /* Dell Wireless 5811e QDL */ + {DEVICE_SWI(0x413c, 0x81cf)}, /* Dell Wireless 5819 */ + {DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */ + {DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */ + {DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */ =20 /* Huawei devices */ {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawe= i me906e) */ diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transpor= t.c index 8988b268a69a..f848f52a756e 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -808,12 +808,24 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb,= struct us_data *us) if (result =3D=3D USB_STOR_TRANSPORT_GOOD) { srb->result =3D SAM_STAT_GOOD; srb->sense_buffer[0] =3D 0x0; + } + + /* + * ATA-passthru commands use sense data to report + * the command completion status, and often devices + * return Check Condition status when nothing is + * wrong. + */ + else if (srb->cmnd[0] =3D=3D ATA_16 || + srb->cmnd[0] =3D=3D ATA_12) { + /* leave the data alone */ + } =20 /* If there was a problem, report an unspecified * hardware error to prevent the higher layers from * entering an infinite retry loop. */ - } else { + else { srb->result =3D DID_ERROR << 16; if ((sshdr.response_code & 0x72) =3D=3D 0x72) srb->sense_buffer[1] =3D HARDWARE_ERROR; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusu= al_devs.h index 96379e715d4b..825625d62982 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1360,6 +1360,13 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ), =20 +/* Reported by Kris Lindgren */ +UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9999, + "Seagate", + "External", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_WP_DETECT ), + UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", "USB to SATA", diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index e75bbe5a10cd..1212b4b3c5a9 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c @@ -827,6 +827,8 @@ static int hwarc_probe(struct usb_interface *iface, =20 if (iface->cur_altsetting->desc.bNumEndpoints < 1) return -ENODEV; + if (!usb_endpoint_xfer_int(&iface->cur_altsetting->endpoint[0].desc)) + return -ENODEV; =20 result =3D -ENOMEM; uwb_rc =3D uwb_rc_alloc(); diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index bdcb13cc1d54..5c9828370217 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c @@ -303,18 +303,22 @@ static int uwbd(void *param) /** Start the UWB daemon */ void uwbd_start(struct uwb_rc *rc) { - rc->uwbd.task =3D kthread_run(uwbd, rc, "uwbd"); - if (rc->uwbd.task =3D=3D NULL) + struct task_struct *task =3D kthread_run(uwbd, rc, "uwbd"); + if (IS_ERR(task)) { + rc->uwbd.task =3D NULL; printk(KERN_ERR "UWB: Cannot start management daemon; " "UWB won't work\n"); - else + } else { + rc->uwbd.task =3D task; rc->uwbd.pid =3D rc->uwbd.task->pid; + } } =20 /* Stop the UWB daemon and free any unprocessed events */ void uwbd_stop(struct uwb_rc *rc) { - kthread_stop(rc->uwbd.task); + if (rc->uwbd.task) + kthread_stop(rc->uwbd.task); uwbd_flush(rc); } =20 diff --git a/fs/block_dev.c b/fs/block_dev.c index ab8652b89577..6b9811823b72 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -419,10 +419,12 @@ int bdev_write_page(struct block_device *bdev, sector= _t sector, return -EOPNOTSUPP; set_page_writeback(page); result =3D ops->rw_page(bdev, sector + get_start_sect(bdev), page, rw); - if (result) + if (result) { end_page_writeback(page); - else + } else { + clean_page_buffers(page); unlock_page(page); + } return result; } EXPORT_SYMBOL_GPL(bdev_write_page); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 04972508c98b..10d36d0dae33 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2745,9 +2745,9 @@ static long btrfs_ioctl_fs_info(struct btrfs_root *ro= ot, void __user *arg) } mutex_unlock(&fs_devices->device_list_mutex); =20 - fi_args->nodesize =3D root->fs_info->super_copy->nodesize; - fi_args->sectorsize =3D root->fs_info->super_copy->sectorsize; - fi_args->clone_alignment =3D root->fs_info->super_copy->sectorsize; + fi_args->nodesize =3D root->nodesize; + fi_args->sectorsize =3D root->sectorsize; + fi_args->clone_alignment =3D root->sectorsize; =20 if (copy_to_user(arg, fi_args, sizeof(*fi_args))) ret =3D -EFAULT; @@ -3980,6 +3980,10 @@ static long btrfs_ioctl_default_subvol(struct file *= file, void __user *argp) ret =3D PTR_ERR(new_root); goto out; } + if (!is_fstree(new_root->objectid)) { + ret =3D -ENOENT; + goto out; + } =20 path =3D btrfs_alloc_path(); if (!path) { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 281358942b64..a0bf3f135a92 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1294,7 +1294,7 @@ exit_cifs(void) exit_cifs_idmap(); #endif #ifdef CONFIG_CIFS_UPCALL - unregister_key_type(&cifs_spnego_key_type); + exit_cifs_spnego(); #endif cifs_destroy_request_bufs(); cifs_destroy_mids(); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2959522238c5..d7be06289ff8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3956,6 +3956,14 @@ cifs_setup_session(const unsigned int xid, struct ci= fs_ses *ses, cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n", server->sec_mode, server->capabilities, server->timeAdj); =20 + if (ses->auth_key.response) { + cifs_dbg(VFS, "Free previous auth_key.response =3D %p\n", + ses->auth_key.response); + kfree(ses->auth_key.response); + ses->auth_key.response =3D NULL; + ses->auth_key.len =3D 0; + } + if (server->ops->sess_setup) rc =3D server->ops->sess_setup(xid, ses, nls_info); =20 diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 0ae3f55290e9..a1feb13c7590 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -225,6 +225,13 @@ cifs_nt_open(char *full_path, struct inode *inode, str= uct cifs_sb_info *cifs_sb, if (backup_cred(cifs_sb)) create_options |=3D CREATE_OPEN_BACKUP_INTENT; =20 + /* O_SYNC also has bit for O_DSYNC so following check picks up either */ + if (f_flags & O_SYNC) + create_options |=3D CREATE_WRITE_THROUGH; + + if (f_flags & O_DIRECT) + create_options |=3D CREATE_NO_BUFFER; + oparms.tcon =3D tcon; oparms.cifs_sb =3D cifs_sb; oparms.desired_access =3D desired_access; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 8add863a81fd..038e428b5173 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -479,22 +479,29 @@ int smb3_validate_negotiate(const unsigned int xid, s= truct cifs_tcon *tcon) { int rc =3D 0; struct validate_negotiate_info_req vneg_inbuf; - struct validate_negotiate_info_rsp *pneg_rsp; + struct validate_negotiate_info_rsp *pneg_rsp =3D NULL; u32 rsplen; =20 cifs_dbg(FYI, "validate negotiate\n"); =20 /* * validation ioctl must be signed, so no point sending this if we - * can not sign it. We could eventually change this to selectively + * can not sign it (ie are not known user). Even if signing is not + * required (enabled but not negotiated), in those cases we selectively * sign just this, the first and only signed request on a connection. - * This is good enough for now since a user who wants better security - * would also enable signing on the mount. Having validation of - * negotiate info for signed connections helps reduce attack vectors + * Having validation of negotiate info helps reduce attack vectors. */ - if (tcon->ses->server->sign =3D=3D false) + if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) return 0; /* validation requires signing */ =20 + if (tcon->ses->user_name =3D=3D NULL) { + cifs_dbg(FYI, "Can't validate negotiate: null user mount\n"); + return 0; /* validation requires signing */ + } + + if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) + cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server= \n"); + vneg_inbuf.Capabilities =3D cpu_to_le32(tcon->ses->server->vals->req_capabilities); memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid, @@ -528,8 +535,9 @@ int smb3_validate_negotiate(const unsigned int xid, str= uct cifs_tcon *tcon) rsplen); =20 /* relax check since Mac returns max bufsize allowed on ioctl */ - if (rsplen > CIFSMaxBufSize) - return -EIO; + if ((rsplen > CIFSMaxBufSize) + || (rsplen < sizeof(struct validate_negotiate_info_rsp))) + goto err_rsp_free; } =20 /* check validate negotiate info response matches what we got earlier */ @@ -548,10 +556,13 @@ int smb3_validate_negotiate(const unsigned int xid, s= truct cifs_tcon *tcon) =20 /* validate negotiate successful */ cifs_dbg(FYI, "validate negotiate info successful\n"); + kfree(pneg_rsp); return 0; =20 vneg_out: cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); +err_rsp_free: + kfree(pneg_rsp); return -EIO; } =20 @@ -1114,7 +1125,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_pa= rms *oparms, __le16 *path, struct TCP_Server_Info *server; struct cifs_tcon *tcon =3D oparms->tcon; struct cifs_ses *ses =3D tcon->ses; - struct kvec iov[4]; + struct kvec iov[4] =3D {{NULL, 0}}; int resp_buftype; int uni_path_len; __le16 *copy_path =3D NULL; @@ -1215,7 +1226,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_pa= rms *oparms, __le16 *path, =20 if (rc !=3D 0) { cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); - if (err_buf) + if (err_buf && rsp) *err_buf =3D kmemdup(rsp, get_rfc1002_length(rsp) + 4, GFP_KERNEL); goto creat_exit; @@ -1331,6 +1342,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *= tcon, u64 persistent_fid, } else iov[0].iov_len =3D get_rfc1002_length(req) + 4; =20 + /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ + if (opcode =3D=3D FSCTL_VALIDATE_NEGOTIATE_INFO) + req->hdr.Flags |=3D SMB2_FLAGS_SIGNED; =20 rc =3D SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); rsp =3D (struct smb2_ioctl_rsp *)iov[0].iov_base; diff --git a/fs/direct-io.c b/fs/direct-io.c index e181b6b2e297..a325d8c5ec2d 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -812,7 +812,8 @@ submit_page_section(struct dio *dio, struct dio_submit = *sdio, struct page *page, */ if (sdio->boundary) { ret =3D dio_send_cur_page(dio, sdio, map_bh); - dio_bio_submit(dio, sdio); + if (sdio->bio) + dio_bio_submit(dio, sdio); page_cache_release(sdio->cur_page); sdio->cur_page =3D NULL; } diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 90d1882b306f..4682bef34bb6 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -84,11 +84,16 @@ struct ecryptfs_page_crypt_context { static inline struct ecryptfs_auth_tok * ecryptfs_get_encrypted_key_payload_data(struct key *key) { - if (key->type =3D=3D &key_type_encrypted) - return (struct ecryptfs_auth_tok *) - (&((struct encrypted_key_payload *)key->payload.data)->payload_data); - else + struct encrypted_key_payload *payload; + + if (key->type !=3D &key_type_encrypted) return NULL; + + payload =3D key->payload.data; + if (!payload) + return ERR_PTR(-EKEYREVOKED); + + return (struct ecryptfs_auth_tok *)payload->payload_data; } =20 static inline struct key *ecryptfs_get_encrypted_key(char *sig) @@ -114,13 +119,17 @@ static inline struct ecryptfs_auth_tok * ecryptfs_get_key_payload_data(struct key *key) { struct ecryptfs_auth_tok *auth_tok; + struct user_key_payload *ukp; =20 auth_tok =3D ecryptfs_get_encrypted_key_payload_data(key); - if (!auth_tok) - return (struct ecryptfs_auth_tok *) - (((struct user_key_payload *)key->payload.data)->data); - else + if (auth_tok) return auth_tok; + + ukp =3D key->payload.data; + if (!ukp) + return ERR_PTR(-EKEYREVOKED); + + return (struct ecryptfs_auth_tok *)ukp->data; } =20 #define ECRYPTFS_MAX_KEYSET_SIZE 1024 diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 4725a07f003c..bb10b3158b49 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -459,7 +459,8 @@ static int ecryptfs_verify_version(u16 version) * @auth_tok_key: key containing the authentication token * @auth_tok: authentication token * - * Returns zero on valid auth tok; -EINVAL otherwise + * Returns zero on valid auth tok; -EINVAL if the payload is invalid; or + * -EKEYREVOKED if the key was revoked before we acquired its semaphore. */ static int ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, @@ -468,6 +469,12 @@ ecryptfs_verify_auth_tok_from_key(struct key *auth_tok= _key, int rc =3D 0; =20 (*auth_tok) =3D ecryptfs_get_key_payload_data(auth_tok_key); + if (IS_ERR(*auth_tok)) { + rc =3D PTR_ERR(*auth_tok); + *auth_tok =3D NULL; + goto out; + } + if (ecryptfs_verify_version((*auth_tok)->version)) { printk(KERN_ERR "Data structure version mismatch. Userspace " "tools must match eCryptfs kernel module with major " diff --git a/fs/exec.c b/fs/exec.c index fa3604731bae..70c31796a314 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -56,6 +56,7 @@ #include #include #include +#include =20 #include #include @@ -1129,8 +1130,22 @@ EXPORT_SYMBOL(flush_old_exec); =20 void would_dump(struct linux_binprm *bprm, struct file *file) { - if (inode_permission(file_inode(file), MAY_READ) < 0) + struct inode *inode =3D file_inode(file); + if (inode_permission(inode, MAY_READ) < 0) { + struct user_namespace *old, *user_ns; bprm->interp_flags |=3D BINPRM_FLAGS_ENFORCE_NONDUMP; + + /* Ensure mm->user_ns contains the executable */ + user_ns =3D old =3D bprm->mm->user_ns; + while ((user_ns !=3D &init_user_ns) && + !privileged_wrt_inode_uidgid(user_ns, inode)) + user_ns =3D user_ns->parent; + + if (old !=3D user_ns) { + bprm->mm->user_ns =3D get_user_ns(user_ns); + put_user_ns(old); + } + } } EXPORT_SYMBOL(would_dump); =20 @@ -1160,7 +1175,6 @@ void setup_new_exec(struct linux_binprm * bprm) !gid_eq(bprm->cred->gid, current_egid())) { current->pdeath_signal =3D 0; } else { - would_dump(bprm, bprm->file); if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) set_dumpable(current->mm, suid_dumpable); } @@ -1259,7 +1273,7 @@ static void check_unsafe_exec(struct linux_binprm *bp= rm) unsigned n_fs; =20 if (p->ptrace) { - if (p->ptrace & PT_PTRACE_CAP) + if (ptracer_capable(p, current_user_ns())) bprm->unsafe |=3D LSM_UNSAFE_PTRACE_CAP; else bprm->unsafe |=3D LSM_UNSAFE_PTRACE; @@ -1564,6 +1578,8 @@ static int do_execve_common(struct filename *filename, if (retval < 0) goto out; =20 + would_dump(bprm, bprm->file); + retval =3D exec_binprm(bprm); if (retval < 0) goto out; diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index b8179ca6bf9d..8a96aeb2391f 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c @@ -330,6 +330,13 @@ static void fscache_objlist_config(struct fscache_objl= ist_data *data) rcu_read_lock(); =20 confkey =3D key->payload.data; + if (!confkey) { + /* key was revoked */ + rcu_read_unlock(); + key_put(key); + goto no_config; + } + buf =3D confkey->data; =20 for (len =3D confkey->datalen - 1; len >=3D 0; len--) { diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index a5c32420bfc8..373494f247b1 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1382,7 +1382,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes= , struct file *file, */ over =3D !dir_emit(ctx, dirent->name, dirent->namelen, dirent->ino, dirent->type); - ctx->pos =3D dirent->off; + if (!over) + ctx->pos =3D dirent->off; } =20 buf +=3D reclen; diff --git a/fs/mpage.c b/fs/mpage.c index 5f9ed622274f..895ee9af5be3 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -457,6 +457,16 @@ static void clean_buffers(struct page *page, unsigned = first_unmapped) try_to_free_buffers(page); } =20 +/* + * For situations where we want to clean all buffers attached to a page. + * We don't need to calculate how many buffers are attached to the page, + * we just need to specify a number larger than the maximum number of buff= ers. + */ +void clean_page_buffers(struct page *page) +{ + clean_buffers(page, ~0U); +} + static int __mpage_writepage(struct page *page, struct writeback_control *= wbc, void *data) { @@ -594,10 +604,8 @@ static int __mpage_writepage(struct page *page, struct= writeback_control *wbc, if (bio =3D=3D NULL) { if (first_unmapped =3D=3D blocks_per_page) { if (!bdev_write_page(bdev, blocks[0] << (blkbits - 9), - page, wbc)) { - clean_buffers(page, first_unmapped); + page, wbc)) goto out; - } } bio =3D mpage_alloc(bdev, blocks[0] << (blkbits - 9), bio_get_nr_vecs(bdev), GFP_NOFS|__GFP_HIGH); diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 9d8fcf2f3b94..296f48c6f43d 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -7226,13 +7226,24 @@ int ocfs2_truncate_inline(struct inode *inode, stru= ct buffer_head *di_bh, =20 static int ocfs2_trim_extent(struct super_block *sb, struct ocfs2_group_desc *gd, - u32 start, u32 count) + u64 group, u32 start, u32 count) { u64 discard, bcount; + struct ocfs2_super *osb =3D OCFS2_SB(sb); =20 bcount =3D ocfs2_clusters_to_blocks(sb, count); - discard =3D le64_to_cpu(gd->bg_blkno) + - ocfs2_clusters_to_blocks(sb, start); + discard =3D ocfs2_clusters_to_blocks(sb, start); + + /* + * For the first cluster group, the gd->bg_blkno is not at the start + * of the group, but at an offset from the start. If we add it while + * calculating discard for first group, we will wrongly start fstrim a + * few blocks after the desried start block and the range can cross + * over into the next cluster group. So, add it only if this is not + * the first cluster group. + */ + if (group !=3D osb->first_cluster_group_blkno) + discard +=3D le64_to_cpu(gd->bg_blkno); =20 trace_ocfs2_trim_extent(sb, (unsigned long long)discard, bcount); =20 @@ -7240,7 +7251,7 @@ static int ocfs2_trim_extent(struct super_block *sb, } =20 static int ocfs2_trim_group(struct super_block *sb, - struct ocfs2_group_desc *gd, + struct ocfs2_group_desc *gd, u64 group, u32 start, u32 max, u32 minbits) { int ret =3D 0, count =3D 0, next; @@ -7259,7 +7270,7 @@ static int ocfs2_trim_group(struct super_block *sb, next =3D ocfs2_find_next_bit(bitmap, max, start); =20 if ((next - start) >=3D minbits) { - ret =3D ocfs2_trim_extent(sb, gd, + ret =3D ocfs2_trim_extent(sb, gd, group, start, next - start); if (ret < 0) { mlog_errno(ret); @@ -7357,7 +7368,8 @@ int ocfs2_trim_fs(struct super_block *sb, struct fstr= im_range *range) } =20 gd =3D (struct ocfs2_group_desc *)gd_bh->b_data; - cnt =3D ocfs2_trim_group(sb, gd, first_bit, last_bit, minlen); + cnt =3D ocfs2_trim_group(sb, gd, group, + first_bit, last_bit, minlen); brelse(gd_bh); gd_bh =3D NULL; if (cnt < 0) { diff --git a/fs/read_write.c b/fs/read_write.c index 009d8542a889..07053752c148 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -116,7 +116,7 @@ generic_file_llseek_size(struct file *file, loff_t offs= et, int whence, * In the generic case the entire file is data, so as long as * offset isn't at the end of the file then the offset is data. */ - if (offset >=3D eof) + if ((unsigned long long)offset >=3D eof) return -ENXIO; break; case SEEK_HOLE: @@ -124,7 +124,7 @@ generic_file_llseek_size(struct file *file, loff_t offs= et, int whence, * There is a virtual hole at the end of the file, so as long as * offset isn't i_size or larger, return i_size. */ - if (offset >=3D eof) + if ((unsigned long long)offset >=3D eof) return -ENXIO; offset =3D eof; break; diff --git a/fs/xattr.c b/fs/xattr.c index 7325e2ecbae9..6b57cbd8c962 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -163,7 +163,7 @@ xattr_getsecurity(struct inode *inode, const char *name= , void *value, } memcpy(value, buffer, len); out: - security_release_secctx(buffer, len); + kfree(buffer); out_noalloc: return len; } diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index 66fc42c57aff..27f5fa488ad0 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -83,6 +83,14 @@ int ahash_register_instance(struct crypto_template *tmpl, struct ahash_instance *inst); void ahash_free_instance(struct crypto_instance *inst); =20 +int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, + unsigned int keylen); + +static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) +{ + return alg->setkey !=3D shash_no_setkey; +} + int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, struct hash_alg_common *alg, struct crypto_instance *inst); diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index e6797ded700e..f8d39f7a56f2 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -222,6 +222,7 @@ int generic_write_end(struct file *, struct address_spa= ce *, loff_t, unsigned, unsigned, struct page *, void *); void page_zero_new_buffers(struct page *page, unsigned from, unsigned to); +void clean_page_buffers(struct page *page); int cont_write_begin(struct file *, struct address_space *, loff_t, unsigned, unsigned, struct page **, void **, get_block_t *, loff_t *); diff --git a/include/linux/capability.h b/include/linux/capability.h index aa93e5ef594c..4a12b8d51f1b 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -213,8 +213,10 @@ extern bool has_ns_capability_noaudit(struct task_stru= ct *t, struct user_namespace *ns, int cap); extern bool capable(int cap); extern bool ns_capable(struct user_namespace *ns, int cap); +extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const s= truct inode *inode); extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap); extern bool file_ns_capable(const struct file *file, struct user_namespace= *ns, int cap); +extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace= *ns); =20 /* audit system wants to get cap info from files as well */ extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_= vfs_cap_data *cpu_caps); diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc= /ad_sigma_delta.h index e7fdec4db9da..6cc48ac55fd2 100644 --- a/include/linux/iio/adc/ad_sigma_delta.h +++ b/include/linux/iio/adc/ad_sigma_delta.h @@ -111,6 +111,9 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta,= unsigned int reg, int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, unsigned int size, unsigned int *val); =20 +int ad_sd_reset(struct ad_sigma_delta *sigma_delta, + unsigned int reset_length); + int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, int *val); int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta, diff --git a/include/linux/input.h b/include/linux/input.h index 82ce323b9986..25476b19ea54 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -527,6 +527,7 @@ int input_ff_event(struct input_dev *dev, unsigned int = type, unsigned int code, =20 int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struc= t file *file); int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file= ); +int input_ff_flush(struct input_dev *dev, struct file *file); =20 int input_ff_create_memless(struct input_dev *dev, void *data, int (*play_effect)(struct input_dev *, void *, struct ff_effect *)); diff --git a/include/linux/key.h b/include/linux/key.h index 017b0826642f..f04f6dd6c6f7 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -170,6 +170,7 @@ struct key { #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ #define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ #define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to tr= usted keys */ +#define KEY_FLAG_UID_KEYRING 11 /* set if key is a user or user session ke= yring */ =20 /* the key type and key description string * - the desc is used to match a key against search criteria @@ -221,6 +222,7 @@ extern struct key *key_alloc(struct key_type *type, #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if ove= rrun */ #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ #define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ +#define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session= keyring */ =20 extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); diff --git a/include/linux/mbus.h b/include/linux/mbus.h index 550c88fb0267..0ae20395bf5a 100644 --- a/include/linux/mbus.h +++ b/include/linux/mbus.h @@ -29,8 +29,8 @@ struct mbus_dram_target_info struct mbus_dram_window { u8 cs_index; u8 mbus_attr; - u32 base; - u32 size; + u64 base; + u64 size; } cs[4]; }; =20 diff --git a/include/linux/mm.h b/include/linux/mm.h index 35f8b59b37a7..65a4dc2da9de 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1209,6 +1209,8 @@ static inline int fixup_user_fault(struct task_struct= *tsk, extern int access_process_vm(struct task_struct *tsk, unsigned long addr, = void *buf, int len, int write); extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, void *buf, int len, int write); +extern int __access_remote_vm(struct task_struct *tsk, struct mm_struct *m= m, + unsigned long addr, void *buf, int len, int write); =20 long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, unsigned long nr_pages, diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 761fc630f150..489c1307f81e 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -419,6 +419,7 @@ struct mm_struct { */ struct task_struct __rcu *owner; #endif + struct user_namespace *user_ns; =20 /* store ref to file /proc//exe symlink points to */ struct file *exe_file; diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 6cbd1b6c3d20..c7eb42235fbe 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -1094,8 +1094,14 @@ static inline unsigned long early_pfn_to_nid(unsigne= d long pfn) #error Allocator MAX_ORDER exceeds SECTION_SIZE #endif =20 -#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT) -#define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT) +static inline unsigned long pfn_to_section_nr(unsigned long pfn) +{ + return pfn >> PFN_SECTION_SHIFT; +} +static inline unsigned long section_nr_to_pfn(unsigned long sec) +{ + return sec << PFN_SECTION_SHIFT; +} =20 #define SECTION_ALIGN_UP(pfn) (((pfn) + PAGES_PER_SECTION - 1) & PAGE_SECT= ION_MASK) #define SECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SECTION_MASK) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e5145f8e4004..1d2c25984890 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3000,6 +3000,9 @@ void ether_setup(struct net_device *dev); struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, void (*setup)(struct net_device *), unsigned int txqs, unsigned int rxqs); +int dev_get_valid_name(struct net *net, struct net_device *dev, + const char *name); + #define alloc_netdev(sizeof_priv, name, setup) \ alloc_netdev_mqs(sizeof_priv, name, setup, 1, 1) =20 diff --git a/include/linux/of.h b/include/linux/of.h index 55452d38ae06..0c220cf91e92 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -503,6 +503,16 @@ static inline struct device_node *of_get_cpu_node(int = cpu, return NULL; } =20 +static inline int of_n_addr_cells(struct device_node *np) +{ + return 0; + +} +static inline int of_n_size_cells(struct device_node *np) +{ + return 0; +} + static inline int of_property_read_u64(const struct device_node *np, const char *propname, u64 *out_value) { diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 32709bcecfdd..0117cdf84e95 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -520,6 +520,8 @@ #define PCI_DEVICE_ID_AMD_15H_M10H_F3 0x1403 #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e +#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F3 0x1573 +#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F4 0x1574 #define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600 #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 diff --git a/include/linux/preempt_mask.h b/include/linux/preempt_mask.h index 5cb25f17331a..7ee3562f70f4 100644 --- a/include/linux/preempt_mask.h +++ b/include/linux/preempt_mask.h @@ -57,19 +57,24 @@ =20 /* * Are we doing bottom half or hardware interrupt processing? - * Are we in a softirq context? Interrupt context? - * in_softirq - Are we currently processing softirq or have bh disabled? - * in_serving_softirq - Are we currently processing softirq? + * + * in_irq() - We're in (hard) IRQ context + * in_softirq() - We have BH disabled, or are processing softirqs + * in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled + * in_serving_softirq() - We're in softirq context + * in_nmi() - We're in NMI context + * in_task() - We're in task context + * + * Note: due to the BH disabled confusion: in_softirq(),in_interrupt() rea= lly + * should not be used in new code. */ #define in_irq() (hardirq_count()) #define in_softirq() (softirq_count()) #define in_interrupt() (irq_count()) #define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET) - -/* - * Are we in NMI context? - */ -#define in_nmi() (preempt_count() & NMI_MASK) +#define in_nmi() (preempt_count() & NMI_MASK) +#define in_task() (!(preempt_count() & \ + (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET))) =20 /* * The preempt_count offset after preempt_disable(); diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 608d90444b6f..5af4994cac23 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -8,6 +8,9 @@ #include /* For task_active_pid_ns. */ #include =20 +extern int ptrace_access_vm(struct task_struct *tsk, unsigned long addr, + void *buf, int len, int write); + /* * Ptrace flags * @@ -19,7 +22,6 @@ #define PT_SEIZED 0x00010000 /* SEIZE used, enable new behavior */ #define PT_PTRACED 0x00000001 #define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */ -#define PT_PTRACE_CAP 0x00000004 /* ptracer can follow suid-exec */ =20 #define PT_OPT_FLAG_SHIFT 3 /* PT_TRACE_* event enable flags */ @@ -50,7 +52,8 @@ extern int ptrace_request(struct task_struct *child, long= request, unsigned long addr, unsigned long data); extern void ptrace_notify(int exit_code); extern void __ptrace_link(struct task_struct *child, - struct task_struct *new_parent); + struct task_struct *new_parent, + const struct cred *ptracer_cred); extern void __ptrace_unlink(struct task_struct *child); extern void exit_ptrace(struct task_struct *tracer); #define PTRACE_MODE_READ 0x01 @@ -202,7 +205,7 @@ static inline void ptrace_init_task(struct task_struct = *child, bool ptrace) =20 if (unlikely(ptrace) && current->ptrace) { child->ptrace =3D current->ptrace; - __ptrace_link(child, current->parent); + __ptrace_link(child, current->parent, current->ptracer_cred); =20 if (child->ptrace & PT_SEIZED) task_set_jobctl_pending(child, JOBCTL_TRAP_STOP); @@ -211,6 +214,8 @@ static inline void ptrace_init_task(struct task_struct = *child, bool ptrace) =20 set_tsk_thread_flag(child, TIF_SIGPENDING); } + else + child->ptracer_cred =3D NULL; } =20 /** diff --git a/include/linux/sched.h b/include/linux/sched.h index 25ad8f0bbdcb..ca9589027893 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1385,6 +1385,7 @@ struct task_struct { struct list_head cpu_timers[3]; =20 /* process credentials */ + const struct cred __rcu *ptracer_cred; /* Tracer's credentials at attach = */ const struct cred __rcu *real_cred; /* objective and real subjective task * credentials (COW) */ const struct cred __rcu *cred; /* effective (overridable) subjective task diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 63c9d381e0d9..93431a42f2f9 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2965,6 +2965,13 @@ static inline void nf_reset_trace(struct sk_buff *sk= b) #endif } =20 +static inline void ipvs_reset(struct sk_buff *skb) +{ +#if IS_ENABLED(CONFIG_IP_VS) + skb->ipvs_property =3D 0; +#endif +} + /* Note: This doesn't put any conntrack and bridge info in dst. */ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *sr= c) { diff --git a/include/net/protocol.h b/include/net/protocol.h index d6fcc1fcdb5b..035971919ced 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -39,7 +39,7 @@ =20 /* This is used to register protocols. */ struct net_protocol { - void (*early_demux)(struct sk_buff *skb); + int (*early_demux)(struct sk_buff *skb); int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, u32 info); unsigned int no_policy:1, diff --git a/include/net/route.h b/include/net/route.h index b17cf28f996e..671d5b1c813b 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -159,7 +159,9 @@ static inline struct rtable *ip_route_output_gre(struct= net *net, struct flowi4 fl4->fl4_gre_key =3D gre_key; return ip_route_output_key(net, fl4); } - +int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr, + u8 tos, struct net_device *dev, + struct in_device *in_dev, u32 *itag); int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src, u8 tos, struct net_device *devin); =20 diff --git a/include/net/tcp.h b/include/net/tcp.h index ceaa03fdccf2..6f404e98876a 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -350,7 +350,7 @@ void tcp_v4_err(struct sk_buff *skb, u32); =20 void tcp_shutdown(struct sock *sk, int how); =20 -void tcp_v4_early_demux(struct sk_buff *skb); +int tcp_v4_early_demux(struct sk_buff *skb); int tcp_v4_rcv(struct sk_buff *skb); =20 int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw); @@ -1515,12 +1515,12 @@ static inline void tcp_highest_sack_reset(struct so= ck *sk) tcp_sk(sk)->highest_sack =3D tcp_write_queue_head(sk); } =20 -/* Called when old skb is about to be deleted (to be combined with new skb= ) */ -static inline void tcp_highest_sack_combine(struct sock *sk, +/* Called when old skb is about to be deleted and replaced by new skb */ +static inline void tcp_highest_sack_replace(struct sock *sk, struct sk_buff *old, struct sk_buff *new) { - if (tcp_sk(sk)->sacked_out && (old =3D=3D tcp_sk(sk)->highest_sack)) + if (old =3D=3D tcp_highest_sack(sk)) tcp_sk(sk)->highest_sack =3D new; } =20 diff --git a/include/net/udp.h b/include/net/udp.h index 68a1fefe3dfe..12f4f5b02986 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -177,7 +177,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short sn= um, unsigned int hash2_nulladdr); =20 /* net/ipv4/udp.c */ -void udp_v4_early_demux(struct sk_buff *skb); +int udp_v4_early_demux(struct sk_buff *skb); int udp_get_port(struct sock *sk, unsigned short snum, int (*saddr_cmp)(const struct sock *, const struct sock *)); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 6868a5ca183c..ab5bfaa8f9de 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -175,6 +175,7 @@ struct scsi_device { unsigned wce_default_on:1; /* Cache is ON by default */ unsigned no_dif:1; /* T10 PI (DIF) should be disabled */ unsigned broken_fua:1; /* Don't set FUA bit */ + unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */ =20 atomic_t disk_events_disable_depth; /* disable depth for disk events */ =20 diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h index 96e3f56519e7..b29faa3471ed 100644 --- a/include/scsi/scsi_devinfo.h +++ b/include/scsi/scsi_devinfo.h @@ -37,5 +37,6 @@ #define BLIST_TRY_VPD_PAGES 0x10000000 /* Attempt to read VPD pages */ #define BLIST_NO_RSOC 0x20000000 /* don't try to issue RSOC */ #define BLIST_MAX_1024 0x40000000 /* maximum 1024 sector cdb length */ +#define BLIST_UNMAP_LIMIT_WS 0x80000000 /* Use UNMAP limit for WRITE SAME = */ =20 #endif diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h index 2398521f0998..d06bb8109cdc 100644 --- a/include/sound/seq_kernel.h +++ b/include/sound/seq_kernel.h @@ -55,7 +55,8 @@ typedef union snd_seq_timestamp snd_seq_timestamp_t; #define SNDRV_SEQ_DEFAULT_CLIENT_EVENTS 200 =20 /* max delivery path length */ -#define SNDRV_SEQ_MAX_HOPS 10 +/* NOTE: this shouldn't be greater than MAX_LOCKDEP_SUBCLASSES */ +#define SNDRV_SEQ_MAX_HOPS 8 =20 /* max size of event size */ #define SNDRV_SEQ_MAX_EVENT_LEN 0x3fffffff diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h index a03acd0d398a..695257ae64ac 100644 --- a/include/sound/seq_virmidi.h +++ b/include/sound/seq_virmidi.h @@ -60,6 +60,7 @@ struct snd_virmidi_dev { int port; /* created/attached port */ unsigned int flags; /* SNDRV_VIRMIDI_* */ rwlock_t filelist_lock; + struct rw_semaphore filelist_sem; struct list_head filelist; }; =20 diff --git a/include/sound/timer.h b/include/sound/timer.h index 7990469a44ce..b0489b850c93 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -90,6 +90,8 @@ struct snd_timer { struct list_head ack_list_head; struct list_head sack_list_head; /* slow ack list head */ struct tasklet_struct task_queue; + int max_instances; /* upper limit of timer instances */ + int num_instances; /* current number of timer instances */ }; =20 struct snd_timer_instance { diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h index 131a0bda7aec..bb71db2d884d 100644 --- a/include/trace/events/kvm.h +++ b/include/trace/events/kvm.h @@ -163,7 +163,7 @@ TRACE_EVENT(kvm_ack_irq, { KVM_TRACE_MMIO_WRITE, "write" } =20 TRACE_EVENT(kvm_mmio, - TP_PROTO(int type, int len, u64 gpa, u64 val), + TP_PROTO(int type, int len, u64 gpa, void *val), TP_ARGS(type, len, gpa, val), =20 TP_STRUCT__entry( @@ -177,7 +177,10 @@ TRACE_EVENT(kvm_mmio, __entry->type =3D type; __entry->len =3D len; __entry->gpa =3D gpa; - __entry->val =3D val; + __entry->val =3D 0; + if (val) + memcpy(&__entry->val, val, + min_t(u32, sizeof(__entry->val), len)); ), =20 TP_printk("mmio %s len %u gpa 0x%llx val 0x%llx", diff --git a/include/uapi/linux/spi/spidev.h b/include/uapi/linux/spi/spide= v.h index dd5f21e75805..856de39d0b89 100644 --- a/include/uapi/linux/spi/spidev.h +++ b/include/uapi/linux/spi/spidev.h @@ -23,6 +23,7 @@ #define SPIDEV_H =20 #include +#include =20 /* User space versions of kernel symbols for SPI clocking modes, * matching diff --git a/kernel/capability.c b/kernel/capability.c index 989f5bfc57dc..4a840b038303 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -427,6 +427,19 @@ bool capable(int cap) } EXPORT_SYMBOL(capable); =20 +/** + * privileged_wrt_inode_uidgid - Do capabilities in the namespace work ove= r the inode? + * @ns: The user namespace in question + * @inode: The inode in question + * + * Return true if the inode uid and gid are within the namespace. + */ +bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct i= node *inode) +{ + return kuid_has_mapping(ns, inode->i_uid) && + kgid_has_mapping(ns, inode->i_gid); +} + /** * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped * @inode: The inode in question @@ -440,7 +453,26 @@ bool capable_wrt_inode_uidgid(const struct inode *inod= e, int cap) { struct user_namespace *ns =3D current_user_ns(); =20 - return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) && - kgid_has_mapping(ns, inode->i_gid); + return ns_capable(ns, cap) && privileged_wrt_inode_uidgid(ns, inode); } EXPORT_SYMBOL(capable_wrt_inode_uidgid); + +/** + * ptracer_capable - Determine if the ptracer holds CAP_SYS_PTRACE in the = namespace + * @tsk: The task that may be ptraced + * @ns: The user namespace to search for CAP_SYS_PTRACE in + * + * Return true if the task that is ptracing the current task had CAP_SYS_P= TRACE + * in the specified user namespace. + */ +bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns) +{ + int ret =3D 0; /* An absent tracer adds no restrictions */ + const struct cred *cred; + rcu_read_lock(); + cred =3D rcu_dereference(tsk->ptracer_cred); + if (cred) + ret =3D security_capable_noaudit(cred, ns, CAP_SYS_PTRACE); + rcu_read_unlock(); + return (ret =3D=3D 0); +} diff --git a/kernel/fork.c b/kernel/fork.c index f6422f07d133..0a2f907b1302 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -527,7 +527,8 @@ static void mm_init_aio(struct mm_struct *mm) #endif } =20 -static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct = *p) +static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct = *p, + struct user_namespace *user_ns) { atomic_set(&mm->mm_users, 1); atomic_set(&mm->mm_count, 1); @@ -551,6 +552,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, = struct task_struct *p) =20 if (likely(!mm_alloc_pgd(mm))) { mmu_notifier_mm_init(mm); + mm->user_ns =3D get_user_ns(user_ns); return mm; } =20 @@ -588,7 +590,7 @@ struct mm_struct *mm_alloc(void) =20 memset(mm, 0, sizeof(*mm)); mm_init_cpumask(mm); - return mm_init(mm, current); + return mm_init(mm, current, current_user_ns()); } =20 /* @@ -603,6 +605,7 @@ void __mmdrop(struct mm_struct *mm) destroy_context(mm); mmu_notifier_mm_destroy(mm); check_mm(mm); + put_user_ns(mm->user_ns); free_mm(mm); } EXPORT_SYMBOL_GPL(__mmdrop); @@ -822,7 +825,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk) #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS mm->pmd_huge_pte =3D NULL; #endif - if (!mm_init(mm, tsk)) + if (!mm_init(mm, tsk, mm->user_ns)) goto fail_nomem; =20 if (init_new_context(tsk, mm)) diff --git a/kernel/params.c b/kernel/params.c index 1e52ca233fd9..20b5f8fe7eef 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -581,7 +581,7 @@ EXPORT_SYMBOL(__kernel_param_unlock); /* * add_sysfs_param - add a parameter to sysfs * @mk: struct module_kobject - * @kparam: the actual parameter definition to add to sysfs + * @kp: the actual parameter definition to add to sysfs * @name: name of parameter * * Create a kobject if for a (per-module) parameter if mp NULL, and diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 7660e8eae6f6..96a418e507e6 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -27,6 +27,35 @@ #include #include =20 +/* + * Access another process' address space via ptrace. + * Source/target buffer must be kernel space, + * Do not walk the page table directly, use get_user_pages + */ +int ptrace_access_vm(struct task_struct *tsk, unsigned long addr, + void *buf, int len, int write) +{ + struct mm_struct *mm; + int ret; + + mm =3D get_task_mm(tsk); + if (!mm) + return 0; + + if (!tsk->ptrace || + (current !=3D tsk->parent) || + ((get_dumpable(mm) !=3D SUID_DUMP_USER) && + !ptracer_capable(tsk, mm->user_ns))) { + mmput(mm); + return 0; + } + + ret =3D __access_remote_vm(tsk, mm, addr, buf, len, write); + mmput(mm); + + return ret; +} + =20 static int ptrace_trapping_sleep_fn(void *flags) { @@ -34,17 +63,26 @@ static int ptrace_trapping_sleep_fn(void *flags) return 0; } =20 +void __ptrace_link(struct task_struct *child, struct task_struct *new_pare= nt, + const struct cred *ptracer_cred) +{ + BUG_ON(!list_empty(&child->ptrace_entry)); + list_add(&child->ptrace_entry, &new_parent->ptraced); + child->parent =3D new_parent; + child->ptracer_cred =3D get_cred(ptracer_cred); +} + /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. * * Must be called with the tasklist lock write-held. */ -void __ptrace_link(struct task_struct *child, struct task_struct *new_pare= nt) +static void ptrace_link(struct task_struct *child, struct task_struct *new= _parent) { - BUG_ON(!list_empty(&child->ptrace_entry)); - list_add(&child->ptrace_entry, &new_parent->ptraced); - child->parent =3D new_parent; + rcu_read_lock(); + __ptrace_link(child, new_parent, __task_cred(new_parent)); + rcu_read_unlock(); } =20 /** @@ -77,14 +115,17 @@ void __ptrace_link(struct task_struct *child, struct t= ask_struct *new_parent) */ void __ptrace_unlink(struct task_struct *child) { + const struct cred *old_cred; BUG_ON(!child->ptrace); =20 - child->ptrace =3D 0; child->parent =3D child->real_parent; list_del_init(&child->ptrace_entry); + old_cred =3D child->ptracer_cred; + child->ptracer_cred =3D NULL; + put_cred(old_cred); =20 spin_lock(&child->sighand->siglock); - + child->ptrace =3D 0; /* * Clear all pending traps and TRAPPING. TRAPPING should be * cleared regardless of JOBCTL_STOP_PENDING. Do it explicitly. @@ -231,7 +272,7 @@ static int ptrace_has_cap(struct user_namespace *ns, un= signed int mode) static int __ptrace_may_access(struct task_struct *task, unsigned int mode) { const struct cred *cred =3D current_cred(), *tcred; - int dumpable =3D 0; + struct mm_struct *mm; kuid_t caller_uid; kgid_t caller_gid; =20 @@ -282,16 +323,11 @@ static int __ptrace_may_access(struct task_struct *ta= sk, unsigned int mode) return -EPERM; ok: rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable =3D get_dumpable(task->mm); - rcu_read_lock(); - if (dumpable !=3D SUID_DUMP_USER && - !ptrace_has_cap(__task_cred(task)->user_ns, mode)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); + mm =3D task->mm; + if (mm && + ((get_dumpable(mm) !=3D SUID_DUMP_USER) && + !ptrace_has_cap(mm->user_ns, mode))) + return -EPERM; =20 return security_ptrace_access_check(task, mode); } @@ -355,13 +391,9 @@ static int ptrace_attach(struct task_struct *task, lon= g request, =20 if (seize) flags |=3D PT_SEIZED; - rcu_read_lock(); - if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE)) - flags |=3D PT_PTRACE_CAP; - rcu_read_unlock(); task->ptrace =3D flags; =20 - __ptrace_link(task, current); + ptrace_link(task, current); =20 /* SEIZE doesn't trap tracee on attach */ if (!seize) @@ -428,7 +460,7 @@ static int ptrace_traceme(void) */ if (!ret && !(current->real_parent->flags & PF_EXITING)) { current->ptrace =3D PT_PTRACED; - __ptrace_link(current, current->real_parent); + ptrace_link(current, current->real_parent); } } write_unlock_irq(&tasklist_lock); @@ -561,7 +593,8 @@ int ptrace_readdata(struct task_struct *tsk, unsigned l= ong src, char __user *dst int this_len, retval; =20 this_len =3D (len > sizeof(buf)) ? sizeof(buf) : len; - retval =3D access_process_vm(tsk, src, buf, this_len, 0); + retval =3D ptrace_access_vm(tsk, src, buf, this_len, 0); + if (!retval) { if (copied) break; @@ -588,7 +621,7 @@ int ptrace_writedata(struct task_struct *tsk, char __us= er *src, unsigned long ds this_len =3D (len > sizeof(buf)) ? sizeof(buf) : len; if (copy_from_user(buf, src, this_len)) return -EFAULT; - retval =3D access_process_vm(tsk, dst, buf, this_len, 1); + retval =3D ptrace_access_vm(tsk, dst, buf, this_len, 1); if (!retval) { if (copied) break; @@ -1133,7 +1166,7 @@ int generic_ptrace_peekdata(struct task_struct *tsk, = unsigned long addr, unsigned long tmp; int copied; =20 - copied =3D access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); + copied =3D ptrace_access_vm(tsk, addr, &tmp, sizeof(tmp), 0); if (copied !=3D sizeof(tmp)) return -EIO; return put_user(tmp, (unsigned long __user *)data); @@ -1144,7 +1177,7 @@ int generic_ptrace_pokedata(struct task_struct *tsk, = unsigned long addr, { int copied; =20 - copied =3D access_process_vm(tsk, addr, &data, sizeof(data), 1); + copied =3D ptrace_access_vm(tsk, addr, &data, sizeof(data), 1); return (copied =3D=3D sizeof(data)) ? 0 : -EIO; } =20 @@ -1162,7 +1195,7 @@ int compat_ptrace_request(struct task_struct *child, = compat_long_t request, switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: - ret =3D access_process_vm(child, addr, &word, sizeof(word), 0); + ret =3D ptrace_access_vm(child, addr, &word, sizeof(word), 0); if (ret !=3D sizeof(word)) ret =3D -EIO; else @@ -1171,7 +1204,7 @@ int compat_ptrace_request(struct task_struct *child, = compat_long_t request, =20 case PTRACE_POKETEXT: case PTRACE_POKEDATA: - ret =3D access_process_vm(child, addr, &data, sizeof(data), 1); + ret =3D ptrace_access_vm(child, addr, &data, sizeof(data), 1); ret =3D (ret !=3D sizeof(data) ? -EIO : 0); break; =20 diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 0940ee9603ae..e6c9458f4b49 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5782,14 +5782,14 @@ enum s_alloc { static void build_group_mask(struct sched_domain *sd, struct sched_group *sg, struct c= pumask *mask) { - const struct cpumask *span =3D sched_domain_span(sd); + const struct cpumask *sg_span =3D sched_group_cpus(sg); struct sd_data *sdd =3D sd->private; struct sched_domain *sibling; int i; =20 cpumask_clear(mask); =20 - for_each_cpu(i, span) { + for_each_cpu(i, sg_span) { sibling =3D *per_cpu_ptr(sdd->sd, i); =20 /* @@ -5801,7 +5801,7 @@ build_group_mask(struct sched_domain *sd, struct sche= d_group *sg, struct cpumask continue; =20 /* If we would not end up here, we can't continue from here */ - if (!cpumask_equal(span, sched_domain_span(sibling->child))) + if (!cpumask_equal(sg_span, sched_domain_span(sibling->child))) continue; =20 cpumask_set_cpu(i, mask); @@ -5869,7 +5869,7 @@ static void init_overlap_sched_group(struct sched_dom= ain *sd, static int build_overlap_sched_groups(struct sched_domain *sd, int cpu) { - struct sched_group *first =3D NULL, *last =3D NULL, *groups =3D NULL, *sg; + struct sched_group *first =3D NULL, *last =3D NULL, *sg; const struct cpumask *span =3D sched_domain_span(sd); struct cpumask *covered =3D sched_domains_tmpmask; struct sd_data *sdd =3D sd->private; @@ -5899,15 +5899,6 @@ build_overlap_sched_groups(struct sched_domain *sd, = int cpu) =20 init_overlap_sched_group(sd, sg); =20 - /* - * Make sure the first group of this domain contains the - * canonical balance cpu. Otherwise the sched_domain iteration - * breaks. See update_sg_lb_stats(). - */ - if ((!groups && cpumask_test_cpu(cpu, sg_span)) || - group_balance_cpu(sg) =3D=3D cpu) - groups =3D sg; - if (!first) first =3D sg; if (last) @@ -5915,7 +5906,7 @@ build_overlap_sched_groups(struct sched_domain *sd, i= nt cpu) last =3D sg; last->next =3D first; } - sd->groups =3D groups; + sd->groups =3D first; =20 return 0; =20 @@ -6631,7 +6622,7 @@ static int build_sched_domains(const struct cpumask *= cpu_map, sd =3D build_sched_domain(tl, cpu_map, attr, sd, i); if (tl =3D=3D sched_domain_topology) *per_cpu_ptr(d.sd, i) =3D sd; - if (tl->flags & SDTL_OVERLAP || sched_feat(FORCE_SD_OVERLAP)) + if (tl->flags & SDTL_OVERLAP) sd->flags |=3D SD_OVERLAP; if (cpumask_equal(cpu_map, sched_domain_span(sd))) break; diff --git a/kernel/sched/features.h b/kernel/sched/features.h index 90284d117fe6..79bad00ea840 100644 --- a/kernel/sched/features.h +++ b/kernel/sched/features.h @@ -56,7 +56,6 @@ SCHED_FEAT(NONTASK_CAPACITY, true) */ SCHED_FEAT(TTWU_QUEUE, true) =20 -SCHED_FEAT(FORCE_SD_OVERLAP, false) SCHED_FEAT(RT_RUNTIME_SHARE, true) SCHED_FEAT(LB_MIN, false) =20 diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3a3172559b22..e918a641b1a0 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -342,7 +342,8 @@ static struct ctl_table kern_table[] =3D { .data =3D &sysctl_sched_time_avg, .maxlen =3D sizeof(unsigned int), .mode =3D 0644, - .proc_handler =3D proc_dointvec, + .proc_handler =3D proc_dointvec_minmax, + .extra1 =3D &one, }, { .procname =3D "sched_shares_window_ns", diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 591bbffc2384..99b46db656e0 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3191,11 +3191,17 @@ static int tracing_open(struct inode *inode, struct= file *file) /* If this file was open for write, then erase contents */ if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { int cpu =3D tracing_get_cpu(inode); + struct trace_buffer *trace_buf =3D &tr->trace_buffer; + +#ifdef CONFIG_TRACER_MAX_TRACE + if (tr->current_trace->print_max) + trace_buf =3D &tr->max_buffer; +#endif =20 if (cpu =3D=3D RING_BUFFER_ALL_CPUS) - tracing_reset_online_cpus(&tr->trace_buffer); + tracing_reset_online_cpus(trace_buf); else - tracing_reset(&tr->trace_buffer, cpu); + tracing_reset(trace_buf, cpu); } =20 if (file->f_mode & FMODE_READ) { @@ -4408,7 +4414,7 @@ static int tracing_wait_pipe(struct file *filp) * * iter->pos will be 0 if we haven't read anything. */ - if (!tracing_is_on() && iter->pos) + if (!tracer_tracing_is_on(iter->tr) && iter->pos) break; =20 mutex_unlock(&iter->mutex); diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 146fb7784900..9bf0b4bd3cc7 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -68,6 +68,7 @@ enum { * attach_mutex to avoid changing binding state while * worker_attach_to_pool() is in progress. */ + POOL_MANAGER_ACTIVE =3D 1 << 0, /* being managed */ POOL_DISASSOCIATED =3D 1 << 2, /* cpu can't serve workers */ =20 /* worker flags */ @@ -158,7 +159,6 @@ struct worker_pool { /* L: hash of busy workers */ =20 /* see manage_workers() for details on the two manager mutexes */ - struct mutex manager_arb; /* manager arbitration */ struct mutex attach_mutex; /* attach/detach exclusion */ struct list_head workers; /* A: attached workers */ struct completion *detach_completion; /* all workers detached */ @@ -288,6 +288,7 @@ static struct workqueue_attrs *wq_update_unbound_numa_a= ttrs_buf; =20 static DEFINE_MUTEX(wq_pool_mutex); /* protects pools and workqueues list = */ static DEFINE_SPINLOCK(wq_mayday_lock); /* protects wq->maydays list */ +static DECLARE_WAIT_QUEUE_HEAD(wq_manager_wait); /* wait for manager to go= away */ =20 static LIST_HEAD(workqueues); /* PL: list of all workqueues */ static bool workqueue_freezing; /* PL: have wqs started freezing? */ @@ -793,7 +794,7 @@ static bool need_to_create_worker(struct worker_pool *p= ool) /* Do we have too many workers and should some go away? */ static bool too_many_workers(struct worker_pool *pool) { - bool managing =3D mutex_is_locked(&pool->manager_arb); + bool managing =3D pool->flags & POOL_MANAGER_ACTIVE; int nr_idle =3D pool->nr_idle + managing; /* manager is considered idle */ int nr_busy =3D pool->nr_workers - nr_idle; =20 @@ -1996,22 +1997,15 @@ static bool manage_workers(struct worker *worker) { struct worker_pool *pool =3D worker->pool; =20 - /* - * Anyone who successfully grabs manager_arb wins the arbitration - * and becomes the manager. mutex_trylock() on pool->manager_arb - * failure while holding pool->lock reliably indicates that someone - * else is managing the pool and the worker which failed trylock - * can proceed to executing work items. This means that anyone - * grabbing manager_arb is responsible for actually performing - * manager duties. If manager_arb is grabbed and released without - * actual management, the pool may stall indefinitely. - */ - if (!mutex_trylock(&pool->manager_arb)) + if (pool->flags & POOL_MANAGER_ACTIVE) return false; =20 + pool->flags |=3D POOL_MANAGER_ACTIVE; + maybe_create_worker(pool); =20 - mutex_unlock(&pool->manager_arb); + pool->flags &=3D ~POOL_MANAGER_ACTIVE; + wake_up(&wq_manager_wait); return true; } =20 @@ -3490,7 +3484,6 @@ static int init_worker_pool(struct worker_pool *pool) setup_timer(&pool->mayday_timer, pool_mayday_timeout, (unsigned long)pool); =20 - mutex_init(&pool->manager_arb); mutex_init(&pool->attach_mutex); INIT_LIST_HEAD(&pool->workers); =20 @@ -3546,13 +3539,15 @@ static void put_unbound_pool(struct worker_pool *po= ol) hash_del(&pool->hash_node); =20 /* - * Become the manager and destroy all workers. Grabbing - * manager_arb prevents @pool's workers from blocking on - * attach_mutex. + * Become the manager and destroy all workers. This prevents + * @pool's workers from blocking on attach_mutex. We're the last + * manager and @pool gets freed with the flag set. */ - mutex_lock(&pool->manager_arb); - spin_lock_irq(&pool->lock); + wait_event_lock_irq(wq_manager_wait, + !(pool->flags & POOL_MANAGER_ACTIVE), pool->lock); + pool->flags |=3D POOL_MANAGER_ACTIVE; + while ((worker =3D first_idle_worker(pool))) destroy_worker(worker); WARN_ON(pool->nr_workers || pool->nr_idle); @@ -3566,8 +3561,6 @@ static void put_unbound_pool(struct worker_pool *pool) if (pool->detach_completion) wait_for_completion(pool->detach_completion); =20 - mutex_unlock(&pool->manager_arb); - /* shut down the timers */ del_timer_sync(&pool->idle_timer); del_timer_sync(&pool->mayday_timer); diff --git a/kernel/workqueue_internal.h b/kernel/workqueue_internal.h index 45215870ac6c..3fa9c146fccb 100644 --- a/kernel/workqueue_internal.h +++ b/kernel/workqueue_internal.h @@ -9,6 +9,7 @@ =20 #include #include +#include =20 struct worker_pool; =20 @@ -59,7 +60,7 @@ struct worker { */ static inline struct worker *current_wq_worker(void) { - if (current->flags & PF_WQ_WORKER) + if (in_task() && (current->flags & PF_WQ_WORKER)) return kthread_data(current); return NULL; } diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 806c5b6b4b3a..162b6d290622 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -220,7 +220,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, hdr =3D 2; =20 /* Extract a tag from the data */ - if (unlikely(dp >=3D datalen - 1)) + if (unlikely(datalen - dp < 2)) goto data_overrun_error; tag =3D data[dp++]; if (unlikely((tag & 0x1f) =3D=3D ASN1_LONG_TAG)) @@ -266,7 +266,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, int n =3D len - 0x80; if (unlikely(n > 2)) goto length_too_long; - if (unlikely(dp >=3D datalen - n)) + if (unlikely(n > datalen - dp)) goto data_overrun_error; hdr +=3D n; for (len =3D 0; n > 0; n--) { @@ -276,6 +276,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, if (unlikely(len > datalen - dp)) goto data_overrun_error; } + } else { + if (unlikely(len > datalen - dp)) + goto data_overrun_error; } =20 if (flags & FLAG_CONS) { diff --git a/lib/digsig.c b/lib/digsig.c index ae05ea393fc8..4b8ef0bd315b 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -86,6 +86,12 @@ static int digsig_verify_rsa(struct key *key, down_read(&key->sem); ukp =3D key->payload.data; =20 + if (!ukp) { + /* key was revoked before we acquired its semaphore */ + err =3D -EKEYREVOKED; + goto err1; + } + if (ukp->datalen < sizeof(*pkh)) goto err1; =20 diff --git a/mm/huge_memory.c b/mm/huge_memory.c index e1a6dce055a0..47c8bb45e781 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1230,17 +1230,11 @@ struct page *follow_trans_huge_pmd(struct vm_area_s= truct *vma, =20 if (flags & FOLL_TOUCH) { pmd_t _pmd; - /* - * We should set the dirty bit only for FOLL_WRITE but - * for now the dirty bit in the pmd is meaningless. - * And if the dirty bit will become meaningful and - * we'll only set it with FOLL_WRITE, an atomic - * set_bit will be required on the pmd to set the - * young bit, instead of the current set_pmd_at. - */ - _pmd =3D pmd_mkyoung(pmd_mkdirty(*pmd)); + _pmd =3D pmd_mkyoung(*pmd); + if (flags & FOLL_WRITE) + _pmd =3D pmd_mkdirty(_pmd); if (pmdp_set_access_flags(vma, addr & HPAGE_PMD_MASK, - pmd, _pmd, 1)) + pmd, _pmd, flags & FOLL_WRITE)) update_mmu_cache_pmd(vma, addr, pmd); } if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { diff --git a/mm/init-mm.c b/mm/init-mm.c index a56a851908d2..975e49f00f34 100644 --- a/mm/init-mm.c +++ b/mm/init-mm.c @@ -6,6 +6,7 @@ #include =20 #include +#include #include #include =20 @@ -21,5 +22,6 @@ struct mm_struct init_mm =3D { .mmap_sem =3D __RWSEM_INITIALIZER(init_mm.mmap_sem), .page_table_lock =3D __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock), .mmlist =3D LIST_HEAD_INIT(init_mm.mmlist), + .user_ns =3D &init_user_ns, INIT_MM_CONTEXT(init_mm) }; diff --git a/mm/memory.c b/mm/memory.c index e1bde862d6d3..4ab5b0c55f4a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3560,7 +3560,7 @@ EXPORT_SYMBOL_GPL(generic_access_phys); * Access another process' address space as given in mm. If non-NULL, use= the * given task for page fault accounting. */ -static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *m= m, +int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr, void *buf, int len, int write) { struct vm_area_struct *vma; diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 4174487a1261..1e0ec777523e 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -520,7 +520,7 @@ EXPORT_SYMBOL_GPL(__add_pages); =20 #ifdef CONFIG_MEMORY_HOTREMOVE /* find the smallest valid pfn in the range [start_pfn, end_pfn) */ -static int find_smallest_section_pfn(int nid, struct zone *zone, +static unsigned long find_smallest_section_pfn(int nid, struct zone *zone, unsigned long start_pfn, unsigned long end_pfn) { @@ -545,7 +545,7 @@ static int find_smallest_section_pfn(int nid, struct zo= ne *zone, } =20 /* find the biggest valid pfn in the range [start_pfn, end_pfn). */ -static int find_biggest_section_pfn(int nid, struct zone *zone, +static unsigned long find_biggest_section_pfn(int nid, struct zone *zone, unsigned long start_pfn, unsigned long end_pfn) { @@ -735,7 +735,7 @@ static int __remove_section(struct zone *zone, struct m= em_section *ms) return ret; =20 scn_nr =3D __section_nr(ms); - start_pfn =3D section_nr_to_pfn(scn_nr); + start_pfn =3D section_nr_to_pfn((unsigned long)scn_nr); __remove_zone(zone, start_pfn); =20 sparse_remove_one_section(zone, ms); diff --git a/mm/nommu.c b/mm/nommu.c index 53a59f41e2e5..7f2c901c555e 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -2007,7 +2007,7 @@ int generic_file_remap_pages(struct vm_area_struct *v= ma, unsigned long addr, } EXPORT_SYMBOL(generic_file_remap_pages); =20 -static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *m= m, +int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr, void *buf, int len, int write) { struct vm_area_struct *vma; diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 44ebd5c2cd4a..dcd897f9f95c 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -364,6 +364,9 @@ static int vlan_device_event(struct notifier_block *unu= sed, unsigned long event, dev->name); vlan_vid_add(dev, htons(ETH_P_8021Q), 0); } + if (event =3D=3D NETDEV_DOWN && + (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) + vlan_vid_del(dev, htons(ETH_P_8021Q), 0); =20 vlan_info =3D rtnl_dereference(dev->vlan_info); if (!vlan_info) @@ -408,9 +411,6 @@ static int vlan_device_event(struct notifier_block *unu= sed, unsigned long event, break; =20 case NETDEV_DOWN: - if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) - vlan_vid_del(dev, htons(ETH_P_8021Q), 0); - /* Put all VLANs for this dev in the down state too. */ vlan_group_for_each_dev(grp, i, vlandev) { flgs =3D vlandev->flags; diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index a841d3e776c5..c7a19a15d760 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -533,6 +533,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, s= truct socket *sock) =20 BT_DBG(""); =20 + if (!l2cap_is_socket(sock)) + return -EBADFD; + baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst); baswap((void *) src, &l2cap_pi(sock->sk)->chan->src); =20 diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 67fe5e84e68f..278a194e6af4 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -334,6 +334,9 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, s= truct socket *sock) =20 BT_DBG(""); =20 + if (!l2cap_is_socket(sock)) + return -EBADFD; + session =3D kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); if (!session) return -ENOMEM; diff --git a/net/core/dev.c b/net/core/dev.c index ee2177c0b186..37e2e5423af0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1056,9 +1056,8 @@ static int dev_alloc_name_ns(struct net *net, return ret; } =20 -static int dev_get_valid_name(struct net *net, - struct net_device *dev, - const char *name) +int dev_get_valid_name(struct net *net, struct net_device *dev, + const char *name) { BUG_ON(!net); =20 @@ -1074,6 +1073,7 @@ static int dev_get_valid_name(struct net *net, =20 return 0; } +EXPORT_SYMBOL(dev_get_valid_name); =20 /** * dev_change_name - change name of a device diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 66498c948405..a3ce3f2d7e98 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1187,7 +1187,10 @@ static const struct nla_policy ifla_policy[IFLA_MAX+= 1] =3D { [IFLA_LINKINFO] =3D { .type =3D NLA_NESTED }, [IFLA_NET_NS_PID] =3D { .type =3D NLA_U32 }, [IFLA_NET_NS_FD] =3D { .type =3D NLA_U32 }, - [IFLA_IFALIAS] =3D { .type =3D NLA_STRING, .len =3D IFALIASZ-1 }, + /* IFLA_IFALIAS is a string, but policy is set to NLA_BINARY to + * allow 0-length string (needed to remove an alias). + */ + [IFLA_IFALIAS] =3D { .type =3D NLA_BINARY, .len =3D IFALIASZ - 1 = }, [IFLA_VFINFO_LIST] =3D {. type =3D NLA_NESTED }, [IFLA_VF_PORTS] =3D { .type =3D NLA_NESTED }, [IFLA_PORT_SELF] =3D { .type =3D NLA_NESTED }, diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 8c5409067930..235c639d370b 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3961,6 +3961,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) if (!xnet) return; =20 + ipvs_reset(skb); skb_orphan(skb); skb->mark =3D 0; } diff --git a/net/dccp/proto.c b/net/dccp/proto.c index f8fa2d15115e..82068e0d9891 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -252,6 +252,7 @@ int dccp_disconnect(struct sock *sk, int flags) { struct inet_connection_sock *icsk =3D inet_csk(sk); struct inet_sock *inet =3D inet_sk(sk); + struct dccp_sock *dp =3D dccp_sk(sk); int err =3D 0; const int old_state =3D sk->sk_state; =20 @@ -271,6 +272,10 @@ int dccp_disconnect(struct sock *sk, int flags) sk->sk_err =3D ECONNRESET; =20 dccp_clear_xmit_timers(sk); + ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); + dp->dccps_hc_rx_ccid =3D NULL; + dp->dccps_hc_tx_ccid =3D NULL; =20 __skb_queue_purge(&sk->sk_receive_queue); __skb_queue_purge(&sk->sk_write_queue); diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 3d4da2c16b6a..1a04ea201f3b 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -313,6 +313,7 @@ static int ip_rcv_finish(struct sk_buff *skb) { const struct iphdr *iph =3D ip_hdr(skb); struct rtable *rt; + int err; =20 if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk =3D=3D NULL) { const struct net_protocol *ipprot; @@ -320,7 +321,9 @@ static int ip_rcv_finish(struct sk_buff *skb) =20 ipprot =3D rcu_dereference(inet_protos[protocol]); if (ipprot && ipprot->early_demux) { - ipprot->early_demux(skb); + err =3D ipprot->early_demux(skb); + if (unlikely(err)) + goto drop_error; /* must reload iph, skb->head might have changed */ iph =3D ip_hdr(skb); } @@ -331,14 +334,10 @@ static int ip_rcv_finish(struct sk_buff *skb) * how the packet travels inside Linux networking. */ if (!skb_dst(skb)) { - int err =3D ip_route_input_noref(skb, iph->daddr, iph->saddr, - iph->tos, skb->dev); - if (unlikely(err)) { - if (err =3D=3D -EXDEV) - NET_INC_STATS_BH(dev_net(skb->dev), - LINUX_MIB_IPRPFILTER); - goto drop; - } + err =3D ip_route_input_noref(skb, iph->daddr, iph->saddr, + iph->tos, skb->dev); + if (unlikely(err)) + goto drop_error; } =20 #ifdef CONFIG_IP_ROUTE_CLASSID @@ -368,6 +367,11 @@ static int ip_rcv_finish(struct sk_buff *skb) drop: kfree_skb(skb); return NET_RX_DROP; + +drop_error: + if (err =3D=3D -EXDEV) + NET_INC_STATS_BH(dev_net(skb->dev), LINUX_MIB_IPRPFILTER); + goto drop; } =20 /* diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index ea7525b1f996..ca0b7408614c 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -151,6 +151,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct= net_device *dev, struct ip_tunnel_parm *parms =3D &tunnel->parms; struct dst_entry *dst =3D skb_dst(skb); struct net_device *tdev; /* Device to other host */ + int pkt_len =3D skb->len; int err; =20 if (!dst) { @@ -194,7 +195,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct= net_device *dev, =20 err =3D dst_output(skb); if (net_xmit_eval(err) =3D=3D 0) - err =3D skb->len; + err =3D pkt_len; iptunnel_xmit_stats(err, &dev->stats, dev->tstats); return NETDEV_TX_OK; =20 diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 75b122645188..d0c1d3781b1d 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1440,40 +1440,53 @@ static struct rtable *rt_dst_alloc(struct net_devic= e *dev, } =20 /* called in rcu_read_lock() section */ -static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 sad= dr, - u8 tos, struct net_device *dev, int our) +int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr, + u8 tos, struct net_device *dev, + struct in_device *in_dev, u32 *itag) { - struct rtable *rth; - struct in_device *in_dev =3D __in_dev_get_rcu(dev); - u32 itag =3D 0; int err; =20 /* Primary sanity checks. */ - if (in_dev =3D=3D NULL) return -EINVAL; =20 if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) || skb->protocol !=3D htons(ETH_P_IP)) - goto e_inval; + return -EINVAL; =20 if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev))) if (ipv4_is_loopback(saddr)) - goto e_inval; + return -EINVAL; =20 if (ipv4_is_zeronet(saddr)) { if (!ipv4_is_local_multicast(daddr)) - goto e_inval; + return -EINVAL; } else { err =3D fib_validate_source(skb, saddr, 0, tos, 0, dev, - in_dev, &itag); + in_dev, itag); if (err < 0) - goto e_err; + return err; } + return 0; +} + +/* called in rcu_read_lock() section */ +static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 sad= dr, + u8 tos, struct net_device *dev, int our) +{ + struct in_device *in_dev =3D __in_dev_get_rcu(dev); + struct rtable *rth; + u32 itag =3D 0; + int err; + + err =3D ip_mc_validate_source(skb, daddr, saddr, tos, dev, in_dev, &itag); + if (err) + return err; + rth =3D rt_dst_alloc(dev_net(dev)->loopback_dev, IN_DEV_CONF_GET(in_dev, NOPOLICY), false, false); if (!rth) - goto e_nobufs; + return -ENOBUFS; =20 #ifdef CONFIG_IP_ROUTE_CLASSID rth->dst.tclassid =3D itag; @@ -1502,13 +1515,6 @@ static int ip_route_input_mc(struct sk_buff *skb, __= be32 daddr, __be32 saddr, =20 skb_dst_set(skb, &rth->dst); return 0; - -e_nobufs: - return -ENOBUFS; -e_inval: - return -EINVAL; -e_err: - return err; } =20 =20 diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 4984da1a31b3..964064325681 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1616,23 +1616,23 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *= skb) } EXPORT_SYMBOL(tcp_v4_do_rcv); =20 -void tcp_v4_early_demux(struct sk_buff *skb) +int tcp_v4_early_demux(struct sk_buff *skb) { const struct iphdr *iph; const struct tcphdr *th; struct sock *sk; =20 if (skb->pkt_type !=3D PACKET_HOST) - return; + return 0; =20 if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)= )) - return; + return 0; =20 iph =3D ip_hdr(skb); th =3D tcp_hdr(skb); =20 if (th->doff < sizeof(struct tcphdr) / 4) - return; + return 0; =20 sk =3D __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo, iph->saddr, th->source, @@ -1651,6 +1651,7 @@ void tcp_v4_early_demux(struct sk_buff *skb) skb_dst_set_noref(skb, dst); } } + return 0; } =20 /* Packet is added to VJ-style prequeue for processing in process diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6ad29aa904bf..52d89fc2b297 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1817,6 +1817,7 @@ static int tcp_mtu_probe(struct sock *sk) nskb->ip_summed =3D skb->ip_summed; =20 tcp_insert_write_queue_before(nskb, skb, sk); + tcp_highest_sack_replace(sk, skb, nskb); =20 len =3D 0; tcp_for_write_queue_from_safe(skb, next, sk) { @@ -2327,7 +2328,7 @@ static void tcp_collapse_retrans(struct sock *sk, str= uct sk_buff *skb) =20 BUG_ON(tcp_skb_pcount(skb) !=3D 1 || tcp_skb_pcount(next_skb) !=3D 1); =20 - tcp_highest_sack_combine(sk, next_skb, skb); + tcp_highest_sack_replace(sk, next_skb, skb); =20 tcp_unlink_write_queue(next_skb, sk); =20 @@ -3058,6 +3059,10 @@ static int tcp_send_syn_data(struct sock *sk, struct= sk_buff *syn) goto done; } =20 + /* data was not sent, this is our new send_head */ + sk->sk_send_head =3D syn_data; + tp->packets_out -=3D tcp_skb_pcount(syn_data); + fallback: /* Send a regular SYN with Fast Open cookie request option */ if (fo->cookie.len > 0) @@ -3104,6 +3109,11 @@ int tcp_connect(struct sock *sk) */ tp->snd_nxt =3D tp->write_seq; tp->pushed_seq =3D tp->write_seq; + buff =3D tcp_send_head(sk); + if (unlikely(buff)) { + tp->snd_nxt =3D TCP_SKB_CB(buff)->seq; + tp->pushed_seq =3D TCP_SKB_CB(buff)->seq; + } TCP_INC_STATS(sock_net(sk), TCP_MIB_ACTIVEOPENS); =20 /* Timer for repeating the SYN until an answer. */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 0a9aaab17e00..5877d782bdc1 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1950,9 +1950,10 @@ static struct sock *__udp4_lib_demux_lookup(struct n= et *net, return result; } =20 -void udp_v4_early_demux(struct sk_buff *skb) +int udp_v4_early_demux(struct sk_buff *skb) { struct net *net =3D dev_net(skb->dev); + struct in_device *in_dev =3D NULL; const struct iphdr *iph; const struct udphdr *uh; struct sock *sk; @@ -1962,33 +1963,33 @@ void udp_v4_early_demux(struct sk_buff *skb) =20 /* validate the packet */ if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)= )) - return; + return 0; =20 iph =3D ip_hdr(skb); uh =3D udp_hdr(skb); =20 - if (skb->pkt_type =3D=3D PACKET_BROADCAST || - skb->pkt_type =3D=3D PACKET_MULTICAST) { - struct in_device *in_dev =3D __in_dev_get_rcu(skb->dev); + if (skb->pkt_type =3D=3D PACKET_MULTICAST) { + in_dev =3D __in_dev_get_rcu(skb->dev); =20 if (!in_dev) - return; + return 0; =20 ours =3D ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, iph->protocol); if (!ours) - return; + return 0; + sk =3D __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, uh->source, iph->saddr, dif); } else if (skb->pkt_type =3D=3D PACKET_HOST) { sk =3D __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, uh->source, iph->saddr, dif); } else { - return; + return 0; } =20 if (!sk) - return; + return 0; =20 skb->sk =3D sk; skb->destructor =3D sock_edemux; @@ -1997,6 +1998,8 @@ void udp_v4_early_demux(struct sk_buff *skb) if (dst) dst =3D dst_check(dst, 0); if (dst) { + u32 itag =3D 0; + /* DST_NOCACHE can not be used without taking a reference */ if (dst->flags & DST_NOCACHE) { if (likely(atomic_inc_not_zero(&dst->__refcnt))) @@ -2004,7 +2007,16 @@ void udp_v4_early_demux(struct sk_buff *skb) } else { skb_dst_set_noref(skb, dst); } + + /* for unconnected multicast sockets we need to validate + * the source on each packet + */ + if (!inet_sk(sk)->inet_daddr && in_dev) + return ip_mc_validate_source(skb, iph->daddr, + iph->saddr, iph->tos, + skb->dev, in_dev, &itag); } + return 0; } =20 int udp_rcv(struct sk_buff *skb) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index f204efd21f50..b277098ed426 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -404,15 +404,18 @@ static void ip6gre_err(struct sk_buff *skb, struct in= et6_skb_parm *opt, struct ipv6_tlv_tnl_enc_lim *tel; __u32 mtu; case ICMPV6_DEST_UNREACH: - net_warn_ratelimited("%s: Path to destination invalid or inactive!\n", - t->parms.name); - break; + net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n", + t->parms.name); + if (code !=3D ICMPV6_PORT_UNREACH) + break; + return; case ICMPV6_TIME_EXCEED: if (code =3D=3D ICMPV6_EXC_HOPLIMIT) { - net_warn_ratelimited("%s: Too small hop limit or routing loop in tunnel= !\n", - t->parms.name); + net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!= \n", + t->parms.name); + break; } - break; + return; case ICMPV6_PARAMPROB: teli =3D 0; if (code =3D=3D ICMPV6_HDR_FIELD) @@ -421,20 +424,20 @@ static void ip6gre_err(struct sk_buff *skb, struct in= et6_skb_parm *opt, if (teli && teli =3D=3D be32_to_cpu(info) - 2) { tel =3D (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; if (tel->encap_limit =3D=3D 0) { - net_warn_ratelimited("%s: Too small encapsulation limit or routing loo= p in tunnel!\n", - t->parms.name); + net_dbg_ratelimited("%s: Too small encapsulation limit or routing loop= in tunnel!\n", + t->parms.name); } } else { - net_warn_ratelimited("%s: Recipient unable to parse tunneled packet!\n", - t->parms.name); + net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n", + t->parms.name); } - break; + return; case ICMPV6_PKT_TOOBIG: mtu =3D be32_to_cpu(info) - offset; if (mtu < IPV6_MIN_MTU) mtu =3D IPV6_MIN_MTU; t->dev->mtu =3D mtu; - break; + return; } =20 if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO)) @@ -1172,21 +1175,23 @@ static int ip6gre_tunnel_change_mtu(struct net_devi= ce *dev, int new_mtu) } =20 static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, - const void *daddr, const void *saddr, unsigned int len) + unsigned short type, const void *daddr, + const void *saddr, unsigned int len) { struct ip6_tnl *t =3D netdev_priv(dev); - struct ipv6hdr *ipv6h =3D (struct ipv6hdr *)skb_push(skb, t->hlen); - __be16 *p =3D (__be16 *)(ipv6h+1); + struct ipv6hdr *ipv6h; + __be16 *p; =20 + ipv6h =3D (struct ipv6hdr *)skb_push(skb, t->hlen + sizeof(*ipv6h)); ip6_flow_hdr(ipv6h, 0, t->fl.u.ip6.flowlabel); ipv6h->hop_limit =3D t->parms.hop_limit; ipv6h->nexthdr =3D NEXTHDR_GRE; ipv6h->saddr =3D t->parms.laddr; ipv6h->daddr =3D t->parms.raddr; =20 - p[0] =3D t->parms.o_flags; - p[1] =3D htons(type); + p =3D (__be16 *)(ipv6h + 1); + p[0] =3D t->parms.o_flags; + p[1] =3D htons(type); =20 /* * Set the source hardware address. diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 4e083dab7445..de67f5bd9bf9 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -407,6 +407,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, = struct flowi *fl) struct net_device_stats *stats =3D &t->dev->stats; struct dst_entry *dst =3D skb_dst(skb); struct net_device *tdev; + int pkt_len =3D skb->len; int err =3D -1; =20 if (!dst) @@ -441,7 +442,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, = struct flowi *fl) struct pcpu_sw_netstats *tstats =3D this_cpu_ptr(dev->tstats); =20 u64_stats_update_begin(&tstats->syncp); - tstats->tx_bytes +=3D skb->len; + tstats->tx_bytes +=3D pkt_len; tstats->tx_packets++; u64_stats_update_end(&tstats->syncp); } else { diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 35f97d9abc4b..1f3677610ad7 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1771,14 +1771,12 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create); =20 /* This function is used by the netlink TUNNEL_DELETE command. */ -int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) +void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) { - l2tp_tunnel_inc_refcount(tunnel); - if (false =3D=3D queue_work(l2tp_wq, &tunnel->del_work)) { - l2tp_tunnel_dec_refcount(tunnel); - return 1; + if (!test_and_set_bit(0, &tunnel->dead)) { + l2tp_tunnel_inc_refcount(tunnel); + queue_work(l2tp_wq, &tunnel->del_work); } - return 0; } EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); =20 diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 36c25b14bc6f..b56ca9346038 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -169,6 +169,9 @@ struct l2tp_tunnel_cfg { =20 struct l2tp_tunnel { int magic; /* Should be L2TP_TUNNEL_MAGIC */ + + unsigned long dead; + struct rcu_head rcu; rwlock_t hlist_lock; /* protect session_hlist */ bool acpt_newsess; /* Indicates whether this @@ -266,7 +269,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int ver= sion, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp); void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); -int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); +void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index ed819454a4e7..a719bf9afb04 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -41,7 +41,6 @@ struct l2tp_eth { struct net_device *dev; struct sock *tunnel_sock; struct l2tp_session *session; - struct list_head list; atomic_long_t tx_bytes; atomic_long_t tx_packets; atomic_long_t tx_dropped; @@ -55,17 +54,6 @@ struct l2tp_eth_sess { struct net_device *dev; }; =20 -/* per-net private data for this module */ -static unsigned int l2tp_eth_net_id; -struct l2tp_eth_net { - struct list_head l2tp_eth_dev_list; - spinlock_t l2tp_eth_lock; -}; - -static inline struct l2tp_eth_net *l2tp_eth_pernet(struct net *net) -{ - return net_generic(net, l2tp_eth_net_id); -} =20 static struct lock_class_key l2tp_eth_tx_busylock; static int l2tp_eth_dev_init(struct net_device *dev) @@ -81,12 +69,6 @@ static int l2tp_eth_dev_init(struct net_device *dev) =20 static void l2tp_eth_dev_uninit(struct net_device *dev) { - struct l2tp_eth *priv =3D netdev_priv(dev); - struct l2tp_eth_net *pn =3D l2tp_eth_pernet(dev_net(dev)); - - spin_lock(&pn->l2tp_eth_lock); - list_del_init(&priv->list); - spin_unlock(&pn->l2tp_eth_lock); dev_put(dev); } =20 @@ -216,7 +198,6 @@ static int l2tp_eth_create(struct net *net, struct l2tp= _tunnel *tunnel, struct l2tp_eth *priv; struct l2tp_eth_sess *spriv; int rc; - struct l2tp_eth_net *pn; =20 if (cfg->ifname) { dev =3D dev_get_by_name(net, cfg->ifname); @@ -251,7 +232,6 @@ static int l2tp_eth_create(struct net *net, struct l2tp= _tunnel *tunnel, priv =3D netdev_priv(dev); priv->dev =3D dev; priv->session =3D session; - INIT_LIST_HEAD(&priv->list); =20 priv->tunnel_sock =3D tunnel->sock; session->recv_skb =3D l2tp_eth_dev_recv; @@ -272,10 +252,6 @@ static int l2tp_eth_create(struct net *net, struct l2t= p_tunnel *tunnel, strlcpy(session->ifname, dev->name, IFNAMSIZ); =20 dev_hold(dev); - pn =3D l2tp_eth_pernet(dev_net(dev)); - spin_lock(&pn->l2tp_eth_lock); - list_add(&priv->list, &pn->l2tp_eth_dev_list); - spin_unlock(&pn->l2tp_eth_lock); =20 return 0; =20 @@ -288,22 +264,6 @@ static int l2tp_eth_create(struct net *net, struct l2t= p_tunnel *tunnel, return rc; } =20 -static __net_init int l2tp_eth_init_net(struct net *net) -{ - struct l2tp_eth_net *pn =3D net_generic(net, l2tp_eth_net_id); - - INIT_LIST_HEAD(&pn->l2tp_eth_dev_list); - spin_lock_init(&pn->l2tp_eth_lock); - - return 0; -} - -static struct pernet_operations l2tp_eth_net_ops =3D { - .init =3D l2tp_eth_init_net, - .id =3D &l2tp_eth_net_id, - .size =3D sizeof(struct l2tp_eth_net), -}; - =20 static const struct l2tp_nl_cmd_ops l2tp_eth_nl_cmd_ops =3D { .session_create =3D l2tp_eth_create, @@ -317,25 +277,18 @@ static int __init l2tp_eth_init(void) =20 err =3D l2tp_nl_register_ops(L2TP_PWTYPE_ETH, &l2tp_eth_nl_cmd_ops); if (err) - goto out; - - err =3D register_pernet_device(&l2tp_eth_net_ops); - if (err) - goto out_unreg; + goto err; =20 pr_info("L2TP ethernet pseudowire support (L2TPv3)\n"); =20 return 0; =20 -out_unreg: - l2tp_nl_unregister_ops(L2TP_PWTYPE_ETH); -out: +err: return err; } =20 static void __exit l2tp_eth_exit(void) { - unregister_pernet_device(&l2tp_eth_net_ops); l2tp_nl_unregister_ops(L2TP_PWTYPE_ETH); } =20 diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index d30f5c03d72f..67c59119d01d 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -122,6 +122,7 @@ static int l2tp_ip_recv(struct sk_buff *skb) unsigned char *ptr, *optr; struct l2tp_session *session; struct l2tp_tunnel *tunnel =3D NULL; + struct iphdr *iph; int length; =20 if (!pskb_may_pull(skb, 4)) @@ -177,21 +178,16 @@ static int l2tp_ip_recv(struct sk_buff *skb) goto discard; =20 tunnel_id =3D ntohl(*(__be32 *) &skb->data[4]); - tunnel =3D l2tp_tunnel_find(net, tunnel_id); - if (tunnel !=3D NULL) - sk =3D tunnel->sock; - else { - struct iphdr *iph =3D (struct iphdr *) skb_network_header(skb); - - read_lock_bh(&l2tp_ip_lock); - sk =3D __l2tp_ip_bind_lookup(net, iph->daddr, 0, tunnel_id); - read_unlock_bh(&l2tp_ip_lock); - } + iph =3D (struct iphdr *)skb_network_header(skb); =20 - if (sk =3D=3D NULL) + read_lock_bh(&l2tp_ip_lock); + sk =3D __l2tp_ip_bind_lookup(net, iph->daddr, 0, tunnel_id); + if (!sk) { + read_unlock_bh(&l2tp_ip_lock); goto discard; - + } sock_hold(sk); + read_unlock_bh(&l2tp_ip_lock); =20 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_put; diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index c052d2991f84..1615cb38828d 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -133,6 +133,7 @@ static int l2tp_ip6_recv(struct sk_buff *skb) unsigned char *ptr, *optr; struct l2tp_session *session; struct l2tp_tunnel *tunnel =3D NULL; + struct ipv6hdr *iph; int length; =20 if (!pskb_may_pull(skb, 4)) @@ -189,22 +190,16 @@ static int l2tp_ip6_recv(struct sk_buff *skb) goto discard; =20 tunnel_id =3D ntohl(*(__be32 *) &skb->data[4]); - tunnel =3D l2tp_tunnel_find(&init_net, tunnel_id); - if (tunnel !=3D NULL) - sk =3D tunnel->sock; - else { - struct ipv6hdr *iph =3D ipv6_hdr(skb); - - read_lock_bh(&l2tp_ip6_lock); - sk =3D __l2tp_ip6_bind_lookup(&init_net, &iph->daddr, - 0, tunnel_id); - read_unlock_bh(&l2tp_ip6_lock); - } + iph =3D ipv6_hdr(skb); =20 - if (sk =3D=3D NULL) + read_lock_bh(&l2tp_ip6_lock); + sk =3D __l2tp_ip6_bind_lookup(&init_net, &iph->daddr, 0, tunnel_id); + if (!sk) { + read_unlock_bh(&l2tp_ip6_lock); goto discard; - + } sock_hold(sk); + read_unlock_bh(&l2tp_ip6_lock); =20 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_put; diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 80d4cfa9fe38..22d74e6b6461 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -603,6 +603,7 @@ static int pppol2tp_connect(struct socket *sock, struct= sockaddr *uservaddr, u32 tunnel_id, peer_tunnel_id; u32 session_id, peer_session_id; bool drop_refcnt =3D false; + bool drop_tunnel =3D false; int ver =3D 2; int fd; =20 @@ -671,7 +672,9 @@ static int pppol2tp_connect(struct socket *sock, struct= sockaddr *uservaddr, if (tunnel_id =3D=3D 0) goto end; =20 - tunnel =3D l2tp_tunnel_find(sock_net(sk), tunnel_id); + tunnel =3D l2tp_tunnel_get(sock_net(sk), tunnel_id); + if (tunnel) + drop_tunnel =3D true; =20 /* Special case: create tunnel context if session_id and * peer_session_id is 0. Otherwise look up tunnel using supplied @@ -800,6 +803,8 @@ static int pppol2tp_connect(struct socket *sock, struct= sockaddr *uservaddr, end: if (drop_refcnt) l2tp_session_dec_refcount(session); + if (drop_tunnel) + l2tp_tunnel_dec_refcount(tunnel); release_sock(sk); =20 return error; @@ -1007,6 +1012,9 @@ static int pppol2tp_session_ioctl(struct l2tp_session= *session, session->name, cmd, arg); =20 sk =3D ps->sock; + if (!sk) + return -EBADR; + sock_hold(sk); =20 switch (cmd) { diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set= _core.c index 6850c3c4d6d3..59aaa4159a36 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -1982,24 +1982,28 @@ static struct pernet_operations ip_set_net_ops =3D { static int __init ip_set_init(void) { - int ret =3D nfnetlink_subsys_register(&ip_set_netlink_subsys); + int ret =3D register_pernet_subsys(&ip_set_net_ops); + + if (ret) { + pr_err("ip_set: cannot register pernet_subsys.\n"); + return ret; + } + + ret =3D nfnetlink_subsys_register(&ip_set_netlink_subsys); if (ret !=3D 0) { pr_err("ip_set: cannot register with nfnetlink.\n"); + unregister_pernet_subsys(&ip_set_net_ops); return ret; } + ret =3D nf_register_sockopt(&so_set); if (ret !=3D 0) { pr_err("SO_SET registry failed: %d\n", ret); nfnetlink_subsys_unregister(&ip_set_netlink_subsys); + unregister_pernet_subsys(&ip_set_net_ops); return ret; } - ret =3D register_pernet_subsys(&ip_set_net_ops); - if (ret) { - pr_err("ip_set: cannot register pernet_subsys.\n"); - nf_unregister_sockopt(&so_set); - nfnetlink_subsys_unregister(&ip_set_netlink_subsys); - return ret; - } + pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL); return 0; } @@ -2007,9 +2011,10 @@ ip_set_init(void) static void __exit ip_set_fini(void) { - unregister_pernet_subsys(&ip_set_net_ops); nf_unregister_sockopt(&so_set); nfnetlink_subsys_unregister(&ip_set_netlink_subsys); + + unregister_pernet_subsys(&ip_set_net_ops); pr_debug("these are the famous last words\n"); } =20 diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_c= thelper.c index 54330fb5efaf..17d9c9df3129 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include =20 @@ -295,6 +296,9 @@ nfnl_cthelper_new(struct sock *nfnl, struct sk_buff *sk= b, struct nf_conntrack_tuple tuple; int ret =3D 0, i; =20 + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE]) return -EINVAL; =20 @@ -509,6 +513,9 @@ nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *sk= b, struct nf_conntrack_tuple tuple; bool tuple_set =3D false; =20 + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c =3D { .dump =3D nfnl_cthelper_dump_table, @@ -581,6 +588,9 @@ nfnl_cthelper_del(struct sock *nfnl, struct sk_buff *sk= b, bool tuple_set =3D false, found =3D false; int i, j =3D 0, ret; =20 + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (tb[NFCTH_NAME]) helper_name =3D nla_data(tb[NFCTH_NAME]); =20 diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 3ca6db13af92..7a4e43a8acfa 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -860,7 +860,7 @@ void *xt_copy_counters_from_user(const void __user *use= r, unsigned int len, if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) !=3D 0) return ERR_PTR(-EFAULT); =20 - strlcpy(info->name, compat_tmp.name, sizeof(info->name)); + memcpy(info->name, compat_tmp.name, sizeof(info->name) - 1); info->num_counters =3D compat_tmp.num_counters; user +=3D sizeof(compat_tmp); } else @@ -873,9 +873,9 @@ void *xt_copy_counters_from_user(const void __user *use= r, unsigned int len, if (copy_from_user(info, user, sizeof(*info)) !=3D 0) return ERR_PTR(-EFAULT); =20 - info->name[sizeof(info->name) - 1] =3D '\0'; user +=3D sizeof(*info); } + info->name[sizeof(info->name) - 1] =3D '\0'; =20 size =3D sizeof(struct xt_counters); size *=3D info->num_counters; diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index c529161cdbf8..99f3146b7337 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c @@ -19,6 +19,7 @@ #include #include =20 +#include #include #include #include @@ -69,6 +70,9 @@ static int xt_osf_add_callback(struct sock *ctnl, struct = sk_buff *skb, struct xt_osf_finger *kf =3D NULL, *sf; int err =3D 0; =20 + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (!osf_attrs[OSF_ATTR_FINGER]) return -EINVAL; =20 @@ -112,6 +116,9 @@ static int xt_osf_remove_callback(struct sock *ctnl, st= ruct sk_buff *skb, struct xt_osf_finger *sf; int err =3D -ENOENT; =20 + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (!osf_attrs[OSF_ATTR_FINGER]) return -EINVAL; =20 diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 3bf0c16023ec..2eafcffb5f8e 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -216,6 +216,9 @@ static int __netlink_deliver_tap_skb(struct sk_buff *sk= b, struct sock *sk =3D skb->sk; int ret =3D -ENOMEM; =20 + if (!net_eq(dev_net(dev), sock_net(sk))) + return 0; + dev_hold(dev); =20 if (is_vmalloc_addr(skb->head)) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f5bf29c033bd..c7d91a0b51da 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2432,6 +2432,7 @@ static int packet_snd(struct socket *sock, struct msg= hdr *msg, size_t len) int offset =3D 0; int vnet_hdr_len; struct packet_sock *po =3D pkt_sk(sk); + bool has_vnet_hdr =3D false; unsigned short gso_type =3D 0; int hlen, tlen; int extra_len =3D 0; @@ -2466,6 +2467,7 @@ static int packet_snd(struct socket *sock, struct msg= hdr *msg, size_t len) reserve =3D dev->hard_header_len; if (po->has_vnet_hdr) { vnet_hdr_len =3D sizeof(vnet_hdr); + has_vnet_hdr =3D true; =20 err =3D -EINVAL; if (len < vnet_hdr_len) @@ -2557,7 +2559,7 @@ static int packet_snd(struct socket *sock, struct msg= hdr *msg, size_t len) skb->priority =3D sk->sk_priority; skb->mark =3D sk->sk_mark; =20 - if (po->has_vnet_hdr) { + if (has_vnet_hdr) { if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { if (!skb_partial_csum_set(skb, vnet_hdr.csum_start, vnet_hdr.csum_offset)) { diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index c0bdd3bce189..c15c37370f5a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -621,6 +621,7 @@ void qdisc_reset(struct Qdisc *qdisc) qdisc->gso_skb =3D NULL; qdisc->q.qlen =3D 0; } + qdisc->qstats.backlog =3D 0; } EXPORT_SYMBOL(qdisc_reset); =20 diff --git a/net/sctp/input.c b/net/sctp/input.c index f2e2cbd2d750..adedd61e2bc4 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -416,7 +416,7 @@ void sctp_icmp_redirect(struct sock *sk, struct sctp_tr= ansport *t, { struct dst_entry *dst; =20 - if (!t) + if (sock_owned_by_user(sk) || !t) return; dst =3D sctp_transport_dst_check(t); if (dst) diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 198ceb721794..4bfa6070ae68 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1627,8 +1627,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_ty= pe, case SCTP_CMD_PROCESS_CTSN: /* Dummy up a SACK for processing. */ sackh.cum_tsn_ack =3D cmd->obj.be32; - sackh.a_rwnd =3D asoc->peer.rwnd + - asoc->outqueue.outstanding_bytes; + sackh.a_rwnd =3D htonl(asoc->peer.rwnd + + asoc->outqueue.outstanding_bytes); sackh.num_gap_ack_blocks =3D 0; sackh.num_dup_tsns =3D 0; chunk->subh.sack_hdr =3D &sackh; diff --git a/net/unix/diag.c b/net/unix/diag.c index 27dd3dcb7739..83b90b62b736 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -256,6 +256,8 @@ static int unix_diag_get_exact(struct sk_buff *in_skb, err =3D -ENOENT; if (sk =3D=3D NULL) goto out_nosk; + if (!net_eq(sock_net(sk), net)) + goto out; =20 err =3D sock_diag_check_cookie(sk, req->udiag_cookie); if (err) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6fd21cab5ada..eb71b29eb647 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -464,6 +464,14 @@ nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX= + 1] =3D { [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] =3D { .type =3D NLA_U32 }, }; =20 +/* policy for packet pattern attributes */ +static const struct nla_policy +nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] =3D { + [NL80211_PKTPAT_MASK] =3D { .type =3D NLA_BINARY, }, + [NL80211_PKTPAT_PATTERN] =3D { .type =3D NLA_BINARY, }, + [NL80211_PKTPAT_OFFSET] =3D { .type =3D NLA_U32 }, +}; + static int nl80211_prepare_wdev_dump(struct sk_buff *skb, struct netlink_callback *cb, struct cfg80211_registered_device **rdev, @@ -8573,7 +8581,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, st= ruct genl_info *info) u8 *mask_pat; =20 nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), - nla_len(pat), NULL); + nla_len(pat), nl80211_packet_pattern_policy); err =3D -EINVAL; if (!pat_tb[NL80211_PKTPAT_MASK] || !pat_tb[NL80211_PKTPAT_PATTERN]) @@ -8801,7 +8809,7 @@ static int nl80211_parse_coalesce_rule(struct cfg8021= 1_registered_device *rdev, u8 *mask_pat; =20 nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), - nla_len(pat), NULL); + nla_len(pat), nl80211_packet_pattern_policy); if (!pat_tb[NL80211_PKTPAT_MASK] || !pat_tb[NL80211_PKTPAT_PATTERN]) return -EINVAL; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 725cf243860c..1f9558155e1e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1877,6 +1877,7 @@ int xfrm_user_policy(struct sock *sk, int optname, u8= __user *optval, int optlen if (err >=3D 0) { xfrm_sk_policy_insert(sk, err, pol); xfrm_pol_put(pol); + __sk_dst_reset(sk); err =3D 0; } =20 diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c28716452211..316c27f70560 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1570,7 +1570,8 @@ static int xfrm_dump_policy_done(struct netlink_callb= ack *cb) struct xfrm_policy_walk *walk =3D (struct xfrm_policy_walk *) &cb->args[1= ]; struct net *net =3D sock_net(cb->skb->sk); =20 - xfrm_policy_walk_done(walk, net); + if (cb->args[0]) + xfrm_policy_walk_done(walk, net); return 0; } =20 diff --git a/security/keys/big_key.c b/security/keys/big_key.c index 8137b27d641d..aa8f46f0918a 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c @@ -135,7 +135,7 @@ void big_key_destroy(struct key *key) path->mnt =3D NULL; path->dentry =3D NULL; } else { - kfree(key->payload.data); + kzfree(key->payload.data); key->payload.data =3D NULL; } } diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encry= pted-keys/encrypted.c index 9c321a25348f..cad4c1f415e3 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -315,6 +315,13 @@ static struct key *request_user_key(const char *master= _desc, u8 **master_key, =20 down_read(&ukey->sem); upayload =3D ukey->payload.data; + if (!upayload) { + /* key was revoked before we acquired its semaphore */ + up_read(&ukey->sem); + key_put(ukey); + ukey =3D ERR_PTR(-EKEYREVOKED); + goto error; + } *master_key =3D upayload->data; *master_keylen =3D upayload->datalen; error: diff --git a/security/keys/internal.h b/security/keys/internal.h index 5f20da01fd8d..31c70323cda9 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -137,7 +137,7 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_r= ef, extern key_ref_t search_my_process_keyrings(struct keyring_search_context = *ctx); extern key_ref_t search_process_keyrings(struct keyring_search_context *ct= x); =20 -extern struct key *find_keyring_by_name(const char *name, bool skip_perm_c= heck); +extern struct key *find_keyring_by_name(const char *name, bool uid_keyring= ); =20 extern int install_user_keyrings(void); extern int install_thread_keyring_to_cred(struct cred *); diff --git a/security/keys/key.c b/security/keys/key.c index 58ebea254519..c55a01471ea2 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -298,6 +298,8 @@ struct key *key_alloc(struct key_type *type, const char= *desc, key->flags |=3D 1 << KEY_FLAG_IN_QUOTA; if (flags & KEY_ALLOC_TRUSTED) key->flags |=3D 1 << KEY_FLAG_TRUSTED; + if (flags & KEY_ALLOC_UID_KEYRING) + key->flags |=3D 1 << KEY_FLAG_UID_KEYRING; =20 #ifdef KEY_DEBUGGING key->magic =3D KEY_DEBUG_MAGIC; diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4598617c66de..8cacd856d1ca 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -745,7 +745,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *b= uffer, size_t buflen) if (ret =3D=3D 0) goto can_read_key; if (ret !=3D -EACCES) - goto error; + goto error2; =20 /* we can't; see if it's searchable from this process's keyrings * - we automatically take account of the fact that it may be @@ -1401,11 +1401,9 @@ long keyctl_assume_authority(key_serial_t id) } =20 ret =3D keyctl_change_reqkey_auth(authkey); - if (ret < 0) - goto error; + if (ret =3D=3D 0) + ret =3D authkey->serial; key_put(authkey); - - ret =3D authkey->serial; error: return ret; } diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 796256db1004..0fa27abd3777 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -405,7 +405,7 @@ static void keyring_describe(const struct key *keyring,= struct seq_file *m) } =20 struct keyring_read_iterator_context { - size_t qty; + size_t buflen; size_t count; key_serial_t __user *buffer; }; @@ -417,9 +417,9 @@ static int keyring_read_iterator(const void *object, vo= id *data) int ret; =20 kenter("{%s,%d},,{%zu/%zu}", - key->type->name, key->serial, ctx->count, ctx->qty); + key->type->name, key->serial, ctx->count, ctx->buflen); =20 - if (ctx->count >=3D ctx->qty) + if (ctx->count >=3D ctx->buflen) return 1; =20 ret =3D put_user(key->serial, ctx->buffer); @@ -441,38 +441,33 @@ static long keyring_read(const struct key *keyring, char __user *buffer, size_t buflen) { struct keyring_read_iterator_context ctx; - unsigned long nr_keys; - int ret; + long ret; =20 kenter("{%d},,%zu", key_serial(keyring), buflen); =20 if (buflen & (sizeof(key_serial_t) - 1)) return -EINVAL; =20 - nr_keys =3D keyring->keys.nr_leaves_on_tree; - if (nr_keys =3D=3D 0) - return 0; - - /* Calculate how much data we could return */ - ctx.qty =3D nr_keys * sizeof(key_serial_t); - - if (!buffer || !buflen) - return ctx.qty; - - if (buflen > ctx.qty) - ctx.qty =3D buflen; - - /* Copy the IDs of the subscribed keys into the buffer */ - ctx.buffer =3D (key_serial_t __user *)buffer; - ctx.count =3D 0; - ret =3D assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx); - if (ret < 0) { - kleave(" =3D %d [iterate]", ret); - return ret; + /* Copy as many key IDs as fit into the buffer */ + if (buffer && buflen) { + ctx.buffer =3D (key_serial_t __user *)buffer; + ctx.buflen =3D buflen; + ctx.count =3D 0; + ret =3D assoc_array_iterate(&keyring->keys, + keyring_read_iterator, &ctx); + if (ret < 0) { + kleave(" =3D %ld [iterate]", ret); + return ret; + } } =20 - kleave(" =3D %zu [ok]", ctx.count); - return ctx.count; + /* Return the size of the buffer needed */ + ret =3D keyring->keys.nr_leaves_on_tree * sizeof(key_serial_t); + if (ret <=3D buflen) + kleave("=3D %ld [ok]", ret); + else + kleave("=3D %ld [buffer too small]", ret); + return ret; } =20 /* @@ -935,15 +930,15 @@ key_ref_t find_key_to_update(key_ref_t keyring_ref, /* * Find a keyring with the specified name. * - * All named keyrings in the current user namespace are searched, provided= they - * grant Search permission directly to the caller (unless this check is - * skipped). Keyrings whose usage points have reached zero or who have be= en - * revoked are skipped. + * Only keyrings that have nonzero refcount, are not revoked, and are owne= d by a + * user in the current user namespace are considered. If @uid_keyring is = %true, + * the keyring additionally must have been allocated as a user or user ses= sion + * keyring; otherwise, it must grant Search permission directly to the cal= ler. * * Returns a pointer to the keyring with the keyring's refcount having bei= ng * incremented on success. -ENOKEY is returned if a key could not be foun= d. */ -struct key *find_keyring_by_name(const char *name, bool skip_perm_check) +struct key *find_keyring_by_name(const char *name, bool uid_keyring) { struct key *keyring; int bucket; @@ -971,10 +966,15 @@ struct key *find_keyring_by_name(const char *name, bo= ol skip_perm_check) if (strcmp(keyring->description, name) !=3D 0) continue; =20 - if (!skip_perm_check && - key_permission(make_key_ref(keyring, 0), - KEY_NEED_SEARCH) < 0) - continue; + if (uid_keyring) { + if (!test_bit(KEY_FLAG_UID_KEYRING, + &keyring->flags)) + continue; + } else { + if (key_permission(make_key_ref(keyring, 0), + KEY_NEED_SEARCH) < 0) + continue; + } =20 /* we've got a match but we might end up racing with * key_cleanup() if the keyring is currently 'dead' diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 18bad7caf602..e56b57f04cf9 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -76,7 +76,9 @@ int install_user_keyrings(void) if (IS_ERR(uid_keyring)) { uid_keyring =3D keyring_alloc(buf, user->uid, INVALID_GID, cred, user_keyring_perm, - KEY_ALLOC_IN_QUOTA, NULL); + KEY_ALLOC_UID_KEYRING | + KEY_ALLOC_IN_QUOTA, + NULL); if (IS_ERR(uid_keyring)) { ret =3D PTR_ERR(uid_keyring); goto error; @@ -92,7 +94,9 @@ int install_user_keyrings(void) session_keyring =3D keyring_alloc(buf, user->uid, INVALID_GID, cred, user_keyring_perm, - KEY_ALLOC_IN_QUOTA, NULL); + KEY_ALLOC_UID_KEYRING | + KEY_ALLOC_IN_QUOTA, + NULL); if (IS_ERR(session_keyring)) { ret =3D PTR_ERR(session_keyring); goto error_release; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 9ea60a7bac78..c120a393ff2d 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -268,11 +268,12 @@ static int construct_key(struct key *key, const void = *callout_info, * The keyring selected is returned with an extra reference upon it which = the * caller must release. */ -static void construct_get_dest_keyring(struct key **_dest_keyring) +static int construct_get_dest_keyring(struct key **_dest_keyring) { struct request_key_auth *rka; const struct cred *cred =3D current_cred(); struct key *dest_keyring =3D *_dest_keyring, *authkey; + int ret; =20 kenter("%p", dest_keyring); =20 @@ -281,6 +282,8 @@ static void construct_get_dest_keyring(struct key **_de= st_keyring) /* the caller supplied one */ key_get(dest_keyring); } else { + bool do_perm_check =3D true; + /* use a default keyring; falling through the cases until we * find one that we actually have */ switch (cred->jit_keyring) { @@ -295,8 +298,10 @@ static void construct_get_dest_keyring(struct key **_d= est_keyring) dest_keyring =3D key_get(rka->dest_keyring); up_read(&authkey->sem); - if (dest_keyring) + if (dest_keyring) { + do_perm_check =3D false; break; + } } =20 case KEY_REQKEY_DEFL_THREAD_KEYRING: @@ -331,11 +336,29 @@ static void construct_get_dest_keyring(struct key **_= dest_keyring) default: BUG(); } + + /* + * Require Write permission on the keyring. This is essential + * because the default keyring may be the session keyring, and + * joining a keyring only requires Search permission. + * + * However, this check is skipped for the "requestor keyring" so + * that /sbin/request-key can itself use request_key() to add + * keys to the original requestor's destination keyring. + */ + if (dest_keyring && do_perm_check) { + ret =3D key_permission(make_key_ref(dest_keyring, 1), + KEY_NEED_WRITE); + if (ret) { + key_put(dest_keyring); + return ret; + } + } } =20 *_dest_keyring =3D dest_keyring; kleave(" [dk %d]", key_serial(dest_keyring)); - return; + return 0; } =20 /* @@ -460,11 +483,15 @@ static struct key *construct_key_and_link(struct keyr= ing_search_context *ctx, if (ctx->index_key.type =3D=3D &key_type_keyring) return ERR_PTR(-EPERM); =09 - user =3D key_user_lookup(current_fsuid()); - if (!user) - return ERR_PTR(-ENOMEM); + ret =3D construct_get_dest_keyring(&dest_keyring); + if (ret) + goto error; =20 - construct_get_dest_keyring(&dest_keyring); + user =3D key_user_lookup(current_fsuid()); + if (!user) { + ret =3D -ENOMEM; + goto error_put_dest_keyring; + } =20 ret =3D construct_alloc_key(ctx, dest_keyring, flags, user, &key); key_user_put(user); @@ -479,7 +506,7 @@ static struct key *construct_key_and_link(struct keyrin= g_search_context *ctx, } else if (ret =3D=3D -EINPROGRESS) { ret =3D 0; } else { - goto couldnt_alloc_key; + goto error_put_dest_keyring; } =20 key_put(dest_keyring); @@ -489,8 +516,9 @@ static struct key *construct_key_and_link(struct keyrin= g_search_context *ctx, construction_failed: key_negate_and_link(key, key_negative_timeout, NULL, NULL); key_put(key); -couldnt_alloc_key: +error_put_dest_keyring: key_put(dest_keyring); +error: kleave(" =3D %d", ret); return ERR_PTR(ret); } diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_a= uth.c index 7495a93b4b90..74e3fe9b47be 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -107,6 +107,18 @@ static void request_key_auth_revoke(struct key *key) } } =20 +static void free_request_key_auth(struct request_key_auth *rka) +{ + if (!rka) + return; + key_put(rka->target_key); + key_put(rka->dest_keyring); + if (rka->cred) + put_cred(rka->cred); + kfree(rka->callout_info); + kfree(rka); +} + /* * Destroy an instantiation authorisation token key. */ @@ -116,15 +128,7 @@ static void request_key_auth_destroy(struct key *key) =20 kenter("{%d}", key->serial); =20 - if (rka->cred) { - put_cred(rka->cred); - rka->cred =3D NULL; - } - - key_put(rka->target_key); - key_put(rka->dest_keyring); - kfree(rka->callout_info); - kfree(rka); + free_request_key_auth(rka); } =20 /* @@ -138,22 +142,17 @@ struct key *request_key_auth_new(struct key *target, = const void *callout_info, const struct cred *cred =3D current->cred; struct key *authkey =3D NULL; char desc[20]; - int ret; + int ret =3D -ENOMEM; =20 kenter("%d,", target->serial); =20 /* allocate a auth record */ - rka =3D kmalloc(sizeof(*rka), GFP_KERNEL); - if (!rka) { - kleave(" =3D -ENOMEM"); - return ERR_PTR(-ENOMEM); - } + rka =3D kzalloc(sizeof(*rka), GFP_KERNEL); + if (!rka) + goto error; rka->callout_info =3D kmalloc(callout_len, GFP_KERNEL); - if (!rka->callout_info) { - kleave(" =3D -ENOMEM"); - kfree(rka); - return ERR_PTR(-ENOMEM); - } + if (!rka->callout_info) + goto error_free_rka; =20 /* see if the calling process is already servicing the key request of * another process */ @@ -163,8 +162,12 @@ struct key *request_key_auth_new(struct key *target, c= onst void *callout_info, =20 /* if the auth key has been revoked, then the key we're * servicing is already instantiated */ - if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags)) - goto auth_key_revoked; + if (test_bit(KEY_FLAG_REVOKED, + &cred->request_key_auth->flags)) { + up_read(&cred->request_key_auth->sem); + ret =3D -EKEYREVOKED; + goto error_free_rka; + } =20 irka =3D cred->request_key_auth->payload.data; rka->cred =3D get_cred(irka->cred); @@ -192,32 +195,22 @@ struct key *request_key_auth_new(struct key *target, = const void *callout_info, KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); if (IS_ERR(authkey)) { ret =3D PTR_ERR(authkey); - goto error_alloc; + goto error_free_rka; } =20 /* construct the auth key */ ret =3D key_instantiate_and_link(authkey, rka, 0, NULL, NULL); if (ret < 0) - goto error_inst; + goto error_put_authkey; =20 kleave(" =3D {%d,%d}", authkey->serial, atomic_read(&authkey->usage)); return authkey; =20 -auth_key_revoked: - up_read(&cred->request_key_auth->sem); - kfree(rka->callout_info); - kfree(rka); - kleave("=3D -EKEYREVOKED"); - return ERR_PTR(-EKEYREVOKED); - -error_inst: - key_revoke(authkey); +error_put_authkey: key_put(authkey); -error_alloc: - key_put(rka->target_key); - key_put(rka->dest_keyring); - kfree(rka->callout_info); - kfree(rka); +error_free_rka: + free_request_key_auth(rka); +error: kleave("=3D %d", ret); return ERR_PTR(ret); } diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 6b804aa4529a..2ee504a8c13f 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -69,7 +69,7 @@ static int TSS_sha1(const unsigned char *data, unsigned i= nt datalen, } =20 ret =3D crypto_shash_digest(&sdesc->shash, data, datalen, digest); - kfree(sdesc); + kzfree(sdesc); return ret; } =20 @@ -113,7 +113,7 @@ static int TSS_rawhmac(unsigned char *digest, const uns= igned char *key, if (!ret) ret =3D crypto_shash_final(&sdesc->shash, digest); out: - kfree(sdesc); + kzfree(sdesc); return ret; } =20 @@ -164,7 +164,7 @@ static int TSS_authhmac(unsigned char *digest, const un= signed char *key, paramdigest, TPM_NONCE_SIZE, h1, TPM_NONCE_SIZE, h2, 1, &c, 0, 0); out: - kfree(sdesc); + kzfree(sdesc); return ret; } =20 @@ -245,7 +245,7 @@ static int TSS_checkhmac1(unsigned char *buffer, if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) ret =3D -EINVAL; out: - kfree(sdesc); + kzfree(sdesc); return ret; } =20 @@ -346,7 +346,7 @@ static int TSS_checkhmac2(unsigned char *buffer, if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) ret =3D -EINVAL; out: - kfree(sdesc); + kzfree(sdesc); return ret; } =20 @@ -563,7 +563,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytyp= e, *bloblen =3D storedsize; } out: - kfree(td); + kzfree(td); return ret; } =20 @@ -677,7 +677,7 @@ static int key_seal(struct trusted_key_payload *p, if (ret < 0) pr_info("trusted_key: srkseal failed (%d)\n", ret); =20 - kfree(tb); + kzfree(tb); return ret; } =20 @@ -702,7 +702,7 @@ static int key_unseal(struct trusted_key_payload *p, /* pull migratable flag out of sealed key */ p->migratable =3D p->key[--p->key_len]; =20 - kfree(tb); + kzfree(tb); return ret; } =20 @@ -961,12 +961,12 @@ static int trusted_instantiate(struct key *key, if (!ret && options->pcrlock) ret =3D pcrlock(options->pcrlock); out: - kfree(datablob); - kfree(options); + kzfree(datablob); + kzfree(options); if (!ret) rcu_assign_keypointer(key, payload); else - kfree(payload); + kzfree(payload); return ret; } =20 @@ -975,8 +975,7 @@ static void trusted_rcu_free(struct rcu_head *rcu) struct trusted_key_payload *p; =20 p =3D container_of(rcu, struct trusted_key_payload, rcu); - memset(p->key, 0, p->key_len); - kfree(p); + kzfree(p); } =20 /* @@ -1015,7 +1014,7 @@ static int trusted_update(struct key *key, struct key= _preparsed_payload *prep) ret =3D datablob_parse(datablob, new_p, new_o); if (ret !=3D Opt_update) { ret =3D -EINVAL; - kfree(new_p); + kzfree(new_p); goto out; } /* copy old key values, and reseal with new pcrs */ @@ -1028,22 +1027,22 @@ static int trusted_update(struct key *key, struct k= ey_preparsed_payload *prep) ret =3D key_seal(new_p, new_o); if (ret < 0) { pr_info("trusted_key: key_seal failed (%d)\n", ret); - kfree(new_p); + kzfree(new_p); goto out; } if (new_o->pcrlock) { ret =3D pcrlock(new_o->pcrlock); if (ret < 0) { pr_info("trusted_key: pcrlock failed (%d)\n", ret); - kfree(new_p); + kzfree(new_p); goto out; } } rcu_assign_keypointer(key, new_p); call_rcu(&p->rcu, trusted_rcu_free); out: - kfree(datablob); - kfree(new_o); + kzfree(datablob); + kzfree(new_o); return ret; } =20 @@ -1062,34 +1061,30 @@ static long trusted_read(const struct key *key, cha= r __user *buffer, p =3D rcu_dereference_key(key); if (!p) return -EINVAL; - if (!buffer || buflen <=3D 0) - return 2 * p->blob_len; - ascii_buf =3D kmalloc(2 * p->blob_len, GFP_KERNEL); - if (!ascii_buf) - return -ENOMEM; =20 - bufp =3D ascii_buf; - for (i =3D 0; i < p->blob_len; i++) - bufp =3D hex_byte_pack(bufp, p->blob[i]); - if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) !=3D 0) { - kfree(ascii_buf); - return -EFAULT; + if (buffer && buflen >=3D 2 * p->blob_len) { + ascii_buf =3D kmalloc(2 * p->blob_len, GFP_KERNEL); + if (!ascii_buf) + return -ENOMEM; + + bufp =3D ascii_buf; + for (i =3D 0; i < p->blob_len; i++) + bufp =3D hex_byte_pack(bufp, p->blob[i]); + if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) !=3D 0) { + kzfree(ascii_buf); + return -EFAULT; + } + kzfree(ascii_buf); } - kfree(ascii_buf); return 2 * p->blob_len; } =20 /* - * trusted_destroy - before freeing the key, clear the decrypted data + * trusted_destroy - clear and free the key's payload */ static void trusted_destroy(struct key *key) { - struct trusted_key_payload *p =3D key->payload.data; - - if (!p) - return; - memset(p->key, 0, p->key_len); - kfree(key->payload.data); + kzfree(key->payload.data); } =20 struct key_type key_type_trusted =3D { diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 40cdee62097e..a6a3482e4d7e 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -163,12 +163,10 @@ static int smk_copy_rules(struct list_head *nhead, st= ruct list_head *ohead, */ static inline unsigned int smk_ptrace_mode(unsigned int mode) { - switch (mode) { - case PTRACE_MODE_READ: - return MAY_READ; - case PTRACE_MODE_ATTACH: + if (mode & PTRACE_MODE_ATTACH) return MAY_READWRITE; - } + if (mode & PTRACE_MODE_READ) + return MAY_READ; =20 return 0; } @@ -674,7 +672,7 @@ static int smack_inode_init_security(struct inode *inod= e, struct inode *dir, } =20 if (len) - *len =3D strlen(isp) + 1; + *len =3D strlen(isp); =20 return 0; } @@ -1060,7 +1058,7 @@ static int smack_inode_removexattr(struct dentry *den= try, const char *name) * @inode: the object * @name: attribute name * @buffer: where to put the result - * @alloc: unused + * @alloc: duplicate memory * * Returns the size of the attribute or an error code */ @@ -1073,43 +1071,38 @@ static int smack_inode_getsecurity(const struct ino= de *inode, struct super_block *sbp; struct inode *ip =3D (struct inode *)inode; char *isp; - int ilen; - int rc =3D 0; =20 - if (strcmp(name, XATTR_SMACK_SUFFIX) =3D=3D 0) { + if (strcmp(name, XATTR_SMACK_SUFFIX) =3D=3D 0) isp =3D smk_of_inode(inode); - ilen =3D strlen(isp) + 1; - *buffer =3D isp; - return ilen; - } - - /* - * The rest of the Smack xattrs are only on sockets. - */ - sbp =3D ip->i_sb; - if (sbp->s_magic !=3D SOCKFS_MAGIC) - return -EOPNOTSUPP; + else { + /* + * The rest of the Smack xattrs are only on sockets. + */ + sbp =3D ip->i_sb; + if (sbp->s_magic !=3D SOCKFS_MAGIC) + return -EOPNOTSUPP; =20 - sock =3D SOCKET_I(ip); - if (sock =3D=3D NULL || sock->sk =3D=3D NULL) - return -EOPNOTSUPP; + sock =3D SOCKET_I(ip); + if (sock =3D=3D NULL || sock->sk =3D=3D NULL) + return -EOPNOTSUPP; =20 - ssp =3D sock->sk->sk_security; + ssp =3D sock->sk->sk_security; =20 - if (strcmp(name, XATTR_SMACK_IPIN) =3D=3D 0) - isp =3D ssp->smk_in->smk_known; - else if (strcmp(name, XATTR_SMACK_IPOUT) =3D=3D 0) - isp =3D ssp->smk_out->smk_known; - else - return -EOPNOTSUPP; + if (strcmp(name, XATTR_SMACK_IPIN) =3D=3D 0) + isp =3D ssp->smk_in->smk_known; + else if (strcmp(name, XATTR_SMACK_IPOUT) =3D=3D 0) + isp =3D ssp->smk_out->smk_known; + else + return -EOPNOTSUPP; + } =20 - ilen =3D strlen(isp) + 1; - if (rc =3D=3D 0) { - *buffer =3D isp; - rc =3D ilen; + if (alloc) { + *buffer =3D kstrdup(isp, GFP_KERNEL); + if (*buffer =3D=3D NULL) + return -ENOMEM; } =20 - return rc; + return strlen(isp); } =20 =20 diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 13c88fbcf037..0038834b558e 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -292,7 +292,7 @@ int yama_ptrace_access_check(struct task_struct *child, return rc; =20 /* require ptrace target be a child of ptracer on attach */ - if (mode =3D=3D PTRACE_MODE_ATTACH) { + if (mode & PTRACE_MODE_ATTACH) { switch (ptrace_scope) { case YAMA_SCOPE_DISABLED: /* No additional restrictions. */ @@ -318,7 +318,7 @@ int yama_ptrace_access_check(struct task_struct *child, } } =20 - if (rc) { + if (rc && (mode & PTRACE_MODE_NOAUDIT) =3D=3D 0) { printk_ratelimited(KERN_NOTICE "ptrace of pid %d was attempted by: %s (pid %d)\n", child->pid, current->comm, current->pid); diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 38514ed6e55c..9b3445922645 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -144,6 +144,7 @@ static int __init snd_hrtimer_init(void) timer->hw =3D hrtimer_hw; timer->hw.resolution =3D resolution; timer->hw.ticks =3D NANO_SEC / resolution; + timer->max_instances =3D 100; /* lower the limit */ =20 err =3D snd_timer_global_register(timer); if (err < 0) { diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss= _midi.c index 3a4569669efa..86353dc0439c 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -615,9 +615,7 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_= seq_event *ev, struct seq if (!dp->timer->running) len =3D snd_seq_oss_timer_start(dp->timer); if (ev->type =3D=3D SNDRV_SEQ_EVENT_SYSEX) { - if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) =3D=3D SNDRV_SEQ_EVENT_LEN= GTH_VARIABLE) - snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, - ev->data.ext.ptr, ev->data.ext.len); + snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev); } else { len =3D snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev); if (len > 0) diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_os= s_readq.c index 654d17a5023c..dffc27374bdf 100644 --- a/sound/core/seq/oss/seq_oss_readq.c +++ b/sound/core/seq/oss/seq_oss_readq.c @@ -119,6 +119,35 @@ snd_seq_oss_readq_puts(struct seq_oss_readq *q, int de= v, unsigned char *data, in return 0; } =20 +/* + * put MIDI sysex bytes; the event buffer may be chained, thus it has + * to be expanded via snd_seq_dump_var_event(). + */ +struct readq_sysex_ctx { + struct seq_oss_readq *readq; + int dev; +}; + +static int readq_dump_sysex(void *ptr, void *buf, int count) +{ + struct readq_sysex_ctx *ctx =3D ptr; + + return snd_seq_oss_readq_puts(ctx->readq, ctx->dev, buf, count); +} + +int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev, + struct snd_seq_event *ev) +{ + struct readq_sysex_ctx ctx =3D { + .readq =3D q, + .dev =3D dev + }; + + if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) !=3D SNDRV_SEQ_EVENT_LENGTH= _VARIABLE) + return 0; + return snd_seq_dump_var_event(ev, readq_dump_sysex, &ctx); +} + /* * copy an event to input queue: * return zero if enqueued diff --git a/sound/core/seq/oss/seq_oss_readq.h b/sound/core/seq/oss/seq_os= s_readq.h index f1463f1f449e..8d033ca2d23f 100644 --- a/sound/core/seq/oss/seq_oss_readq.h +++ b/sound/core/seq/oss/seq_oss_readq.h @@ -44,6 +44,8 @@ void snd_seq_oss_readq_delete(struct seq_oss_readq *q); void snd_seq_oss_readq_clear(struct seq_oss_readq *readq); unsigned int snd_seq_oss_readq_poll(struct seq_oss_readq *readq, struct fi= le *file, poll_table *wait); int snd_seq_oss_readq_puts(struct seq_oss_readq *readq, int dev, unsigned = char *data, int len); +int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev, + struct snd_seq_event *ev); int snd_seq_oss_readq_put_event(struct seq_oss_readq *readq, union evrec *= ev); int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *readq, unsigned = long curt, int seq_mode); int snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec); diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index a3988a4bcfd6..0a52e377a617 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -676,7 +676,7 @@ static int deliver_to_subscribers(struct snd_seq_client= *client, if (atomic) read_lock(&grp->list_lock); else - down_read(&grp->list_mutex); + down_read_nested(&grp->list_mutex, hop); list_for_each_entry(subs, &grp->list_head, src_list) { /* both ports ready? */ if (atomic_read(&subs->ref_count) !=3D 2) diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 81134e067184..3b126af4a026 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -77,13 +77,17 @@ static void snd_virmidi_init_event(struct snd_virmidi *= vmidi, * decode input event and put to read buffer of each opened file */ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, - struct snd_seq_event *ev) + struct snd_seq_event *ev, + bool atomic) { struct snd_virmidi *vmidi; unsigned char msg[4]; int len; =20 - read_lock(&rdev->filelist_lock); + if (atomic) + read_lock(&rdev->filelist_lock); + else + down_read(&rdev->filelist_sem); list_for_each_entry(vmidi, &rdev->filelist, list) { if (!vmidi->trigger) continue; @@ -97,7 +101,10 @@ static int snd_virmidi_dev_receive_event(struct snd_vir= midi_dev *rdev, snd_rawmidi_receive(vmidi->substream, msg, len); } } - read_unlock(&rdev->filelist_lock); + if (atomic) + read_unlock(&rdev->filelist_lock); + else + up_read(&rdev->filelist_sem); =20 return 0; } @@ -115,7 +122,7 @@ int snd_virmidi_receive(struct snd_rawmidi *rmidi, stru= ct snd_seq_event *ev) struct snd_virmidi_dev *rdev; =20 rdev =3D rmidi->private_data; - return snd_virmidi_dev_receive_event(rdev, ev); + return snd_virmidi_dev_receive_event(rdev, ev, true); } #endif /* 0 */ =20 @@ -130,7 +137,7 @@ static int snd_virmidi_event_input(struct snd_seq_event= *ev, int direct, rdev =3D private_data; if (!(rdev->flags & SNDRV_VIRMIDI_USE)) return 0; /* ignored */ - return snd_virmidi_dev_receive_event(rdev, ev); + return snd_virmidi_dev_receive_event(rdev, ev, atomic); } =20 /* @@ -209,7 +216,6 @@ static int snd_virmidi_input_open(struct snd_rawmidi_su= bstream *substream) struct snd_virmidi_dev *rdev =3D substream->rmidi->private_data; struct snd_rawmidi_runtime *runtime =3D substream->runtime; struct snd_virmidi *vmidi; - unsigned long flags; =20 vmidi =3D kzalloc(sizeof(*vmidi), GFP_KERNEL); if (vmidi =3D=3D NULL) @@ -223,9 +229,11 @@ static int snd_virmidi_input_open(struct snd_rawmidi_s= ubstream *substream) vmidi->client =3D rdev->client; vmidi->port =3D rdev->port;=09 runtime->private_data =3D vmidi; - write_lock_irqsave(&rdev->filelist_lock, flags); + down_write(&rdev->filelist_sem); + write_lock_irq(&rdev->filelist_lock); list_add_tail(&vmidi->list, &rdev->filelist); - write_unlock_irqrestore(&rdev->filelist_lock, flags); + write_unlock_irq(&rdev->filelist_lock); + up_write(&rdev->filelist_sem); vmidi->rdev =3D rdev; return 0; } @@ -264,9 +272,11 @@ static int snd_virmidi_input_close(struct snd_rawmidi_= substream *substream) struct snd_virmidi_dev *rdev =3D substream->rmidi->private_data; struct snd_virmidi *vmidi =3D substream->runtime->private_data; =20 + down_write(&rdev->filelist_sem); write_lock_irq(&rdev->filelist_lock); list_del(&vmidi->list); write_unlock_irq(&rdev->filelist_lock); + up_write(&rdev->filelist_sem); snd_midi_event_free(vmidi->parser); substream->runtime->private_data =3D NULL; kfree(vmidi); @@ -520,6 +530,7 @@ int snd_virmidi_new(struct snd_card *card, int device, = struct snd_rawmidi **rrmi rdev->rmidi =3D rmidi; rdev->device =3D device; rdev->client =3D -1; + init_rwsem(&rdev->filelist_sem); rwlock_init(&rdev->filelist_lock); INIT_LIST_HEAD(&rdev->filelist); rdev->seq_mode =3D SNDRV_VIRMIDI_SEQ_DISPATCH; diff --git a/sound/core/timer.c b/sound/core/timer.c index 8bdfec237ada..762da0a59ba0 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -181,7 +181,7 @@ static void snd_timer_request(struct snd_timer_id *tid) * * call this with register_mutex down. */ -static void snd_timer_check_slave(struct snd_timer_instance *slave) +static int snd_timer_check_slave(struct snd_timer_instance *slave) { struct snd_timer *timer; struct snd_timer_instance *master; @@ -191,16 +191,21 @@ static void snd_timer_check_slave(struct snd_timer_in= stance *slave) list_for_each_entry(master, &timer->open_list_head, open_list) { if (slave->slave_class =3D=3D master->slave_class && slave->slave_id =3D=3D master->slave_id) { + if (master->timer->num_instances >=3D + master->timer->max_instances) + return -EBUSY; list_move_tail(&slave->open_list, &master->slave_list_head); + master->timer->num_instances++; spin_lock_irq(&slave_active_lock); slave->master =3D master; slave->timer =3D master->timer; spin_unlock_irq(&slave_active_lock); - return; + return 0; } } } + return 0; } =20 /* @@ -209,7 +214,7 @@ static void snd_timer_check_slave(struct snd_timer_inst= ance *slave) * * call this with register_mutex down. */ -static void snd_timer_check_master(struct snd_timer_instance *master) +static int snd_timer_check_master(struct snd_timer_instance *master) { struct snd_timer_instance *slave, *tmp; =20 @@ -217,7 +222,11 @@ static void snd_timer_check_master(struct snd_timer_in= stance *master) list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) { if (slave->slave_class =3D=3D master->slave_class && slave->slave_id =3D=3D master->slave_id) { + if (master->timer->num_instances >=3D + master->timer->max_instances) + return -EBUSY; list_move_tail(&slave->open_list, &master->slave_list_head); + master->timer->num_instances++; spin_lock_irq(&slave_active_lock); spin_lock(&master->timer->lock); slave->master =3D master; @@ -229,8 +238,11 @@ static void snd_timer_check_master(struct snd_timer_in= stance *master) spin_unlock_irq(&slave_active_lock); } } + return 0; } =20 +static int snd_timer_close_locked(struct snd_timer_instance *timeri); + /* * open a timer instance * when opening a master, the slave id must be here given. @@ -241,6 +253,7 @@ int snd_timer_open(struct snd_timer_instance **ti, { struct snd_timer *timer; struct snd_timer_instance *timeri =3D NULL; + int err; =20 if (tid->dev_class =3D=3D SNDRV_TIMER_CLASS_SLAVE) { /* open a slave instance */ @@ -260,10 +273,14 @@ int snd_timer_open(struct snd_timer_instance **ti, timeri->slave_id =3D tid->device; timeri->flags |=3D SNDRV_TIMER_IFLG_SLAVE; list_add_tail(&timeri->open_list, &snd_timer_slave_list); - snd_timer_check_slave(timeri); + err =3D snd_timer_check_slave(timeri); + if (err < 0) { + snd_timer_close_locked(timeri); + timeri =3D NULL; + } mutex_unlock(®ister_mutex); *ti =3D timeri; - return 0; + return err; } =20 /* open a master instance */ @@ -289,6 +306,10 @@ int snd_timer_open(struct snd_timer_instance **ti, return -EBUSY; } } + if (timer->num_instances >=3D timer->max_instances) { + mutex_unlock(®ister_mutex); + return -EBUSY; + } timeri =3D snd_timer_instance_new(owner, timer); if (!timeri) { mutex_unlock(®ister_mutex); @@ -315,44 +336,36 @@ int snd_timer_open(struct snd_timer_instance **ti, } =20 list_add_tail(&timeri->open_list, &timer->open_list_head); - snd_timer_check_master(timeri); + timer->num_instances++; + err =3D snd_timer_check_master(timeri); + if (err < 0) { + snd_timer_close_locked(timeri); + timeri =3D NULL; + } mutex_unlock(®ister_mutex); *ti =3D timeri; - return 0; + return err; } =20 static int _snd_timer_stop(struct snd_timer_instance *timeri, int event); =20 /* * close a timer instance + * call this with register_mutex down. */ -int snd_timer_close(struct snd_timer_instance *timeri) +static int snd_timer_close_locked(struct snd_timer_instance *timeri) { struct snd_timer *timer =3D NULL; struct snd_timer_instance *slave, *tmp; =20 - if (snd_BUG_ON(!timeri)) - return -ENXIO; + list_del(&timeri->open_list); =20 /* force to stop the timer */ snd_timer_stop(timeri); =20 - if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { - /* wait, until the active callback is finished */ - spin_lock_irq(&slave_active_lock); - while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { - spin_unlock_irq(&slave_active_lock); - udelay(10); - spin_lock_irq(&slave_active_lock); - } - spin_unlock_irq(&slave_active_lock); - mutex_lock(®ister_mutex); - list_del(&timeri->open_list); - mutex_unlock(®ister_mutex); - } else { - timer =3D timeri->timer; - if (snd_BUG_ON(!timer)) - goto out; + timer =3D timeri->timer; + if (timer) { + timer->num_instances--; /* wait, until the active callback is finished */ spin_lock_irq(&timer->lock); while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { @@ -361,17 +374,14 @@ int snd_timer_close(struct snd_timer_instance *timeri) spin_lock_irq(&timer->lock); } spin_unlock_irq(&timer->lock); - mutex_lock(®ister_mutex); - list_del(&timeri->open_list); - if (list_empty(&timer->open_list_head) && - timer->hw.close) - timer->hw.close(timer); + /* remove slave links */ spin_lock_irq(&slave_active_lock); spin_lock(&timer->lock); list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, open_list) { list_move_tail(&slave->open_list, &snd_timer_slave_list); + timer->num_instances--; slave->master =3D NULL; slave->timer =3D NULL; list_del_init(&slave->ack_list); @@ -379,21 +389,45 @@ int snd_timer_close(struct snd_timer_instance *timeri) } spin_unlock(&timer->lock); spin_unlock_irq(&slave_active_lock); - /* release a card refcount for safe disconnection */ - if (timer->card) - put_device(&timer->card->card_dev); - mutex_unlock(®ister_mutex); + + /* slave doesn't need to release timer resources below */ + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) + timer =3D NULL; } - out: + if (timeri->private_free) timeri->private_free(timeri); kfree(timeri->owner); kfree(timeri); - if (timer) + + if (timer) { + if (list_empty(&timer->open_list_head) && timer->hw.close) + timer->hw.close(timer); + /* release a card refcount for safe disconnection */ + if (timer->card) + put_device(&timer->card->card_dev); module_put(timer->module); + } + return 0; } =20 +/* + * close a timer instance + */ +int snd_timer_close(struct snd_timer_instance *timeri) +{ + int err; + + if (snd_BUG_ON(!timeri)) + return -ENXIO; + + mutex_lock(®ister_mutex); + err =3D snd_timer_close_locked(timeri); + mutex_unlock(®ister_mutex); + return err; +} + unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) { struct snd_timer * timer; @@ -872,6 +906,7 @@ int snd_timer_new(struct snd_card *card, char *id, stru= ct snd_timer_id *tid, spin_lock_init(&timer->lock); tasklet_init(&timer->task_queue, snd_timer_tasklet, (unsigned long)timer); + timer->max_instances =3D 1000; /* default limit per timer */ if (card !=3D NULL) { timer->module =3D card->module; err =3D snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops); diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 2e908225d754..0b4b028e8e98 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c @@ -106,7 +106,8 @@ enum { #endif /* CONFIG_X86_X32 */ }; =20 -static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cm= d, unsigned long arg) +static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int = cmd, + unsigned long arg) { void __user *argp =3D compat_ptr(arg); =20 @@ -127,7 +128,7 @@ static long snd_timer_user_ioctl_compat(struct file *fi= le, unsigned int cmd, uns case SNDRV_TIMER_IOCTL_PAUSE: case SNDRV_TIMER_IOCTL_PAUSE_OLD: case SNDRV_TIMER_IOCTL_NEXT_DEVICE: - return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); + return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp); case SNDRV_TIMER_IOCTL_INFO32: return snd_timer_user_info_compat(file, argp); case SNDRV_TIMER_IOCTL_STATUS32: @@ -139,3 +140,15 @@ static long snd_timer_user_ioctl_compat(struct file *f= ile, unsigned int cmd, uns } return -ENOIOCTLCMD; } + +static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cm= d, + unsigned long arg) +{ + struct snd_timer_user *tu =3D file->private_data; + long ret; + + mutex_lock(&tu->ioctl_lock); + ret =3D __snd_timer_user_ioctl_compat(file, cmd, arg); + mutex_unlock(&tu->ioctl_lock); + return ret; +} diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 22b7038cff0d..fc1f09a8e5d3 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2791,7 +2791,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *k= ctl, int *step_to_check) return -1; if (*step_to_check && *step_to_check !=3D step) { snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (= %d!=3D%d)\n", -- *step_to_check, step); + *step_to_check, step); return -1; } *step_to_check =3D step; diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 2961fae9670a..eb8e4065c4c5 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -88,6 +88,27 @@ static int adau17x1_pll_event(struct snd_soc_dapm_widget= *w, return 0; } =20 +static int adau17x1_adc_fixup(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec =3D snd_soc_dapm_to_codec(w->dapm); + struct adau *adau =3D snd_soc_codec_get_drvdata(codec); + + /* + * If we are capturing, toggle the ADOSR bit in Converter Control 0 to + * avoid losing SNR (workaround from ADI). This must be done after + * the ADC(s) have been enabled. According to the data sheet, it is + * normally illegal to set this bit when the sampling rate is 96 kHz, + * but according to ADI it is acceptable for this workaround. + */ + regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, + ADAU17X1_CONVERTER0_ADOSR, ADAU17X1_CONVERTER0_ADOSR); + regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, + ADAU17X1_CONVERTER0_ADOSR, 0); + + return 0; +} + static const char * const adau17x1_mono_stereo_text[] =3D { "Stereo", "Mono Left Channel (L+R)", @@ -119,7 +140,8 @@ static const struct snd_soc_dapm_widget adau17x1_dapm_w= idgets[] =3D { SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0, &adau17x1_dac_mode_mux), =20 - SND_SOC_DAPM_ADC("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0), + SND_SOC_DAPM_ADC_E("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0, + adau17x1_adc_fixup, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0), SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0), SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0), diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h index 3ffabaf4c7a8..664db5dd8c20 100644 --- a/sound/soc/codecs/adau17x1.h +++ b/sound/soc/codecs/adau17x1.h @@ -120,5 +120,7 @@ bool adau17x1_has_dsp(struct adau *adau); =20 #define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7 =20 +#define ADAU17X1_CONVERTER0_ADOSR BIT(3) + =20 #endif diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index b871ba407e4e..4458190149d1 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -469,10 +469,12 @@ static int init_card(struct snd_usb_caiaqdev *cdev) =20 err =3D snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0= ); if (err) - return err; + goto err_kill_urb; =20 - if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) - return -ENODEV; + if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) { + err =3D -ENODEV; + goto err_kill_urb; + } =20 usb_string(usb_dev, usb_dev->descriptor.iManufacturer, cdev->vendor_name, CAIAQ_USB_STR_LEN); @@ -507,6 +509,10 @@ static int init_card(struct snd_usb_caiaqdev *cdev) =20 setup_card(cdev); return 0; + + err_kill_urb: + usb_kill_urb(&cdev->ep1_in_urb); + return err; } =20 static int snd_probe(struct usb_interface *intf, diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index bf618e1500ac..e7b934f4d837 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -191,7 +191,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_ker= nel *sk, } =20 pg =3D get_order(read_size); - sk->s =3D (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); + sk->s =3D (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| + __GFP_NOWARN, pg); if (!sk->s) { snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); goto out; @@ -211,7 +212,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_ker= nel *sk, pg =3D get_order(write_size); =20 sk->write_page =3D - (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); + (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| + __GFP_NOWARN, pg); if (!sk->write_page) { snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); usb_stream_free(sk); --+b2GFy/wpzNn/yIF-- --fkwCrey//1f/3EP1 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUBWkuK+Oe/yOyVhhEJAQrPwQ/+MxFkdbyYm65HcHyA/ziZoBEXAFGF30ps qlC5PFZSCmtJ9HYZD2tPPbMjVgMNUPtfXgXHDCgYW3CLOgHQBnMQU8aNfcaNXoBd le7/X8cR6aEZvsfeb+BVGPSVejQwGkSfUf5v0de0TKr8NqOXOrqZAyl+UZ48odlz 5m++RpzAVOOnmss0JEyrfVRw4BwSkrBKKvH7EwkOvKV2o7BtBpexKpBMH5a7jyYZ hlyg6Aba9AwhUwd9wWBR91CeVpTJcp3FLWNLuuf175DQQlxV2379je5XpkxcB1jK lgeTA08XZnDYNWmeYMjjJCTxiPH6H1wrygl8KxBINlba7hyFfXVhHcCuI9rpjrZU pIdXr3742QcI6dRzlTbCuj+SVrRSSIT5mB675LMUhXvMMRWG6yq92TOGCrlNodm8 Jn9VYAeHYiBWQxFWSAdPw8HvcMLIYacLBWO/hDGQ4STtTj9RcDiJsUJJDo9AV92M ctCn4OLypA0iAyINspqSfyX9N2i/VslOqYh4/snXcgTWWbgeWZiXVVV+LHlKlIzw vwEBpMptdyXU9D8ywd8dfrINKQoWKtZ795VrcpYLEnccUXCCl2/MW8kDUWuXcpbX DV2A1W0GoNFveVst3jdQOask5fXCuULux75qsh/OKPFajyvx9OL7HldPWyoAOfLe xb34/pYd8Fk= =wcEL -----END PGP SIGNATURE----- --fkwCrey//1f/3EP1--