4.19.103-stable review
Subsystems (3)
Greg Kroah-Hartman
maintainercover 4.19.103-stable review
This is the start of the stable review cycle for the 4.19.103 release. There are 195 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 Feb 2020 12:18:57 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.19.103-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.19.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 4.19.103-rc1
David Howells <[email protected]>
rxrpc: Fix service call disconnection
Song Liu <[email protected]>
perf/core: Fix mlock accounting in perf_mmap()
Konstantin Khlebnikov <[email protected]>
clocksource: Prevent double add_timer_on() for watchdog_timer
Thomas Gleixner <[email protected]>
x86/apic/msi: Plug non-maskable MSI affinity race
Ronnie Sahlberg <[email protected]>
cifs: fail i/o on soft mounts if sessionsetup errors out
David Hildenbrand <[email protected]>
mm/page_alloc.c: fix uninitialized memmaps on a partially populated last section
Pavel Tatashin <[email protected]>
mm: return zero_resv_unavail optimization
Naoya Horiguchi <[email protected]>
mm: zero remaining unavailable struct pages
Sean Christopherson <[email protected]>
KVM: Play nice with read-only memslots when querying host page size
Sean Christopherson <[email protected]>
KVM: Use vcpu-specific gva->hva translation when querying host page size
Miaohe Lin <[email protected]>
KVM: nVMX: vmread should not set rflags to specify success in case of #PF
Sean Christopherson <[email protected]>
KVM: VMX: Add non-canonical check on writes to RTIT address MSRs
Sean Christopherson <[email protected]>
KVM: x86: Use gpa_t for cr2/gpa to fix TDP support on 32-bit KVM
Sean Christopherson <[email protected]>
KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM
Josef Bacik <[email protected]>
btrfs: flush write bio if we loop in extent_write_cache_pages
Wayne Lin <[email protected]>
drm/dp_mst: Remove VCPI while disabling topology mgr
Claudiu Beznea <[email protected]>
drm: atmel-hlcdc: enable clock before configuring timing engine
Josef Bacik <[email protected]>
btrfs: free block groups after free'ing fs trees
Anand Jain <[email protected]>
btrfs: use bool argument in free_root_pointers()
Eric Biggers <[email protected]>
ext4: fix deadlock allocating crypto bounce page from mempool
Florian Fainelli <[email protected]>
net: dsa: b53: Always use dev->vlan_enabled in b53_configure_vlan()
Harini Katakam <[email protected]>
net: macb: Limit maximum GEM TX length in TSO
Harini Katakam <[email protected]>
net: macb: Remove unnecessary alignment check for TSO
Raed Salem <[email protected]>
net/mlx5: IPsec, fix memory leak at mlx5_fpga_ipsec_delete_sa_ctx
Raed Salem <[email protected]>
net/mlx5: IPsec, Fix esp modify function attribute
Florian Fainelli <[email protected]>
net: systemport: Avoid RBUF stuck in Wake-on-LAN mode
Cong Wang <[email protected]>
net_sched: fix a resource leak in tcindex_set_parms()
Lorenzo Bianconi <[email protected]>
net: mvneta: move rx_dropped and rx_errors in per-cpu stats
Florian Fainelli <[email protected]>
net: dsa: bcm_sf2: Only 7278 supports 2Gb/sec IMP port
Eric Dumazet <[email protected]>
bonding/alb: properly access headers in bond_alb_xmit()
Andreas Kemnade <[email protected]>
mfd: rn5t618: Mark ADC control register volatile
Marco Felsch <[email protected]>
mfd: da9062: Fix watchdog compatible string
Dan Carpenter <[email protected]>
ubi: Fix an error pointer dereference in error handling code
Sascha Hauer <[email protected]>
ubi: fastmap: Fix inverted logic in seen selfcheck
Trond Myklebust <[email protected]>
nfsd: Return the correct number of bytes written to the file
Arnd Bergmann <[email protected]>
nfsd: fix jiffies/time_t mixup in LRU list
Arnd Bergmann <[email protected]>
nfsd: fix delay timer on 32-bit architectures
Yishai Hadas <[email protected]>
IB/core: Fix ODP get user pages flow
Prabhath Sajeepa <[email protected]>
IB/mlx5: Fix outstanding_pi index for GSI qps
Nathan Chancellor <[email protected]>
net: tulip: Adjust indentation in {dmfe, uli526x}_init_module
Nathan Chancellor <[email protected]>
net: smc911x: Adjust indentation in smc911x_phy_configure
Nathan Chancellor <[email protected]>
ppp: Adjust indentation into ppp_async_input
Nathan Chancellor <[email protected]>
NFC: pn544: Adjust indentation in pn544_hci_check_presence
Nathan Chancellor <[email protected]>
drm: msm: mdp4: Adjust indentation in mdp4_dsi_encoder_enable
Nathan Chancellor <[email protected]>
powerpc/44x: Adjust indentation in ibm4xx_denali_fixup_memsize
Nathan Chancellor <[email protected]>
ext2: Adjust indentation in ext2_fill_super
Nathan Chancellor <[email protected]>
phy: qualcomm: Adjust indentation in read_poll_timeout
Asutosh Das <[email protected]>
scsi: ufs: Recheck bkops level if bkops is disabled
Nathan Chancellor <[email protected]>
scsi: qla4xxx: Adjust indentation in qla4xxx_mem_free
Nathan Chancellor <[email protected]>
scsi: csiostor: Adjust indentation in csio_device_reset
Bart Van Assche <[email protected]>
scsi: qla2xxx: Fix the endianness of the qla82xx_get_fw_size() return type
Erdem Aktas <[email protected]>
percpu: Separate decrypted varaibles anytime encryption can be enabled
Lyude Paul <[email protected]>
drm/amd/dm/mst: Ignore payload update failures
Stephen Warren <[email protected]>
clk: tegra: Mark fuse clock as critical
Christian Borntraeger <[email protected]>
KVM: s390: do not clobber registers during guest reset/store status
Sean Christopherson <[email protected]>
KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails
Sean Christopherson <[email protected]>
KVM: x86: Don't let userspace set host-reserved cr4 bits
Boris Ostrovsky <[email protected]>
x86/kvm: Be careful not to clear KVM_VCPU_FLUSH_TLB bit
Sean Christopherson <[email protected]>
KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
Sean Christopherson <[email protected]>
KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
Sean Christopherson <[email protected]>
KVM: x86: Fix potential put_fpu() w/o load_fpu() on MPX platform
Marios Pomonis <[email protected]>
KVM: x86: Protect MSR-based index computations in fixed_msr_to_seg_unit() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c
Marios Pomonis <[email protected]>
KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect MSR-based index computations in pmu.h from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect kvm_hv_msr_[get|set]_crash_data() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect pmu_intel.c from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Refactor prefix decoding to prevent Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
Jens Axboe <[email protected]>
aio: prevent potential eventfd recursion on poll
Jens Axboe <[email protected]>
eventfd: track eventfd_signal() recursion depth
Coly Li <[email protected]>
bcache: add readahead cache policy options via sysfs interface
Vladis Dronov <[email protected]>
watchdog: fix UAF in reboot notifier handling in watchdog core code
Juergen Gross <[email protected]>
xen/balloon: Support xend-based toolstack take two
Gavin Shan <[email protected]>
tools/kvm_stat: Fix kvm_exit filter name
Sean Young <[email protected]>
media: rc: ensure lirc is initialized before registering input device
Ville Syrjälä <[email protected]>
drm/rect: Avoid division by zero
Andreas Gruenbacher <[email protected]>
gfs2: fix O_SYNC write handling
Christoph Hellwig <[email protected]>
gfs2: move setting current->backing_dev_info
Roberto Bergantinos Corpas <[email protected]>
sunrpc: expiry_time should be seconds not timeval
Brian Norris <[email protected]>
mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
Luca Coelho <[email protected]>
iwlwifi: don't throw error when trying to remove IGTK
Stephen Warren <[email protected]>
ARM: tegra: Enable PLLP bypass during Tegra124 LP1
Filipe Manana <[email protected]>
Btrfs: fix race between adding and putting tree mod seq elements and nodes
Josef Bacik <[email protected]>
btrfs: set trans->drity in btrfs_commit_transaction
Filipe Manana <[email protected]>
Btrfs: fix missing hole after hole punching and fsync when using NO_HOLES
Vasily Averin <[email protected]>
jbd2_seq_info_next should increase position index
Trond Myklebust <[email protected]>
NFS: Directory page cache pages need to be locked when read
Trond Myklebust <[email protected]>
NFS: Fix memory leaks and corruption in readdir
Arun Easi <[email protected]>
scsi: qla2xxx: Fix unbound NVME response length
Chuhong Yuan <[email protected]>
crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill
Herbert Xu <[email protected]>
crypto: api - Fix race condition in crypto_spawn_alg
Tudor Ambarus <[email protected]>
crypto: atmel-aes - Fix counter overflow in CTR mode
Herbert Xu <[email protected]>
crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
Ard Biesheuvel <[email protected]>
crypto: ccp - set max RSA modulus size for v3 platform devices as well
Toke Høiland-Jørgensen <[email protected]>
samples/bpf: Don't try to remove user's homedir on clean
Steven Rostedt (VMware) <[email protected]>
ftrace: Protect ftrace_graph_hash with ftrace_sync
Steven Rostedt (VMware) <[email protected]>
ftrace: Add comment to why rcu_dereference_sched() is open coded
Amol Grover <[email protected]>
tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu
Amol Grover <[email protected]>
tracing: Annotate ftrace_graph_hash pointer with __rcu
Herbert Xu <[email protected]>
padata: Remove broken queue flushing
Mikulas Patocka <[email protected]>
dm writecache: fix incorrect flush sequence when doing SSD mode commit
Mike Snitzer <[email protected]>
dm: fix potential for q->make_request_fn NULL pointer
Milan Broz <[email protected]>
dm crypt: fix benbi IV constructor crash if used in authenticated mode
Joe Thornber <[email protected]>
dm space map common: fix to ensure new block isn't already in use
Dmitry Fomichev <[email protected]>
dm zoned: support zone sizes smaller than 128MiB
Michael Ellerman <[email protected]>
of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
Rafael J. Wysocki <[email protected]>
PM: core: Fix handling of devices deleted during system-wide resume
Chengguang Xu <[email protected]>
f2fs: code cleanup for f2fs_statfs_project()
Chengguang Xu <[email protected]>
f2fs: fix miscounted block limit in f2fs_statfs_project()
Chengguang Xu <[email protected]>
f2fs: choose hardlimit when softlimit is larger than hardlimit in f2fs_statfs_project()
Amir Goldstein <[email protected]>
ovl: fix wrong WARN_ON() in ovl_cache_update_ino()
Sven Van Asbroeck <[email protected]>
power: supply: ltc2941-battery-gauge: fix use-after-free
Quinn Tran <[email protected]>
scsi: qla2xxx: Fix mtcp dump collection failure
Geert Uytterhoeven <[email protected]>
scripts/find-unused-docs: Fix massive false positives
Gilad Ben-Yossef <[email protected]>
crypto: ccree - fix PM race condition
Gilad Ben-Yossef <[email protected]>
crypto: ccree - fix pm wrongful error reporting
Gilad Ben-Yossef <[email protected]>
crypto: ccree - fix backlog memory leak
Herbert Xu <[email protected]>
crypto: api - Check spawn->alg under lock in crypto_drop_spawn
Samuel Holland <[email protected]>
mfd: axp20x: Mark AXP20X_VBUS_IPSOUT_MGMT as volatile
Tianyu Lan <[email protected]>
hv_balloon: Balloon up according to request page number
Michał Mirosław <[email protected]>
mmc: sdhci-of-at91: fix memleak on clk_get failure
Yurii Monakov <[email protected]>
PCI: keystone: Fix link training retries initiation
Eric Biggers <[email protected]>
crypto: geode-aes - convert to skcipher API and make thread-safe
Zhihao Cheng <[email protected]>
ubifs: Fix deadlock in concurrent bulk-read and writepage
Eric Biggers <[email protected]>
ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
Eric Biggers <[email protected]>
ubifs: don't trigger assertion on invalid no-key filename
Hou Tao <[email protected]>
ubifs: Reject unsupported ioctl flags explicitly
Stephen Boyd <[email protected]>
alarmtimer: Unregister wakeup source when module get fails
Hans de Goede <[email protected]>
ACPI / battery: Deal better with neither design nor full capacity not being reported
Hans de Goede <[email protected]>
ACPI / battery: Use design-cap for capacity calculations if full-cap is not available
Hans de Goede <[email protected]>
ACPI / battery: Deal with design or full capacity being reported as -1
Hans de Goede <[email protected]>
ACPI: video: Do not export a non working backlight interface on MSI MS-7721 boards
Linus Walleij <[email protected]>
mmc: spi: Toggle SPI polarity, do not hardcode it
David Engraf <[email protected]>
PCI: tegra: Fix return value check of pm_runtime_get_sync()
Steve French <[email protected]>
smb3: fix signing verification of large reads
Pingfan Liu <[email protected]>
powerpc/pseries: Advance pfn if section is not present in lmb_is_removable()
Sukadev Bhattiprolu <[email protected]>
powerpc/xmon: don't access ASDR in VMs
Gerald Schaefer <[email protected]>
s390/mm: fix dynamic pagetable upgrade for hugetlbfs
Alexander Lobakin <[email protected]>
MIPS: boot: fix typo in 'vmlinux.lzma.its' target
Alexander Lobakin <[email protected]>
MIPS: fix indentation of the 'RELOCS' message
Christoffer Dall <[email protected]>
KVM: arm64: Only sign-extend MMIO up to register width
Mark Rutland <[email protected]>
KVM: arm/arm64: Correct AArch32 SPSR on exception entry
Mark Rutland <[email protected]>
KVM: arm/arm64: Correct CPSR on exception entry
Mark Rutland <[email protected]>
KVM: arm64: Correct PSTATE on exception entry
Hans de Goede <[email protected]>
ALSA: hda: Add Clevo W65_67SB the power_save blacklist
Mika Westerberg <[email protected]>
platform/x86: intel_scu_ipc: Fix interrupt support
Kevin Hao <[email protected]>
irqdomain: Fix a memory leak in irq_domain_push_irq()
Gustavo A. R. Silva <[email protected]>
lib/test_kasan.c: fix memory leak in kmalloc_oob_krealloc_more()
Helen Koike <[email protected]>
media: v4l2-rect.h: fix v4l2_rect_map_inside() top/left adjustments
Arnd Bergmann <[email protected]>
media: v4l2-core: compat: ignore native command codes
John Hubbard <[email protected]>
media/v4l2-core: set pages dirty upon releasing DMA buffers
Yang Shi <[email protected]>
mm: move_pages: report the number of non-attempted pages
Dan Williams <[email protected]>
mm/memory_hotplug: fix remove_memory() lockdep splat
Takashi Iwai <[email protected]>
ALSA: dummy: Fix PCM format loop in proc output
Takashi Iwai <[email protected]>
ALSA: usb-audio: Fix endianess in descriptor validation
Bryan O'Donoghue <[email protected]>
usb: gadget: f_ecm: Use atomic_t to track in-flight request
Bryan O'Donoghue <[email protected]>
usb: gadget: f_ncm: Use atomic_t to track in-flight request
Roger Quadros <[email protected]>
usb: gadget: legacy: set max_speed to super-speed
Jun Li <[email protected]>
usb: typec: tcpci: mask event interrupts when remove driver
Navid Emamdoost <[email protected]>
brcmfmac: Fix memory leak in brcmf_usbdev_qinit
Eric Dumazet <[email protected]>
rcu: Avoid data-race in rcu_gp_fqs_check_wake()
Mathieu Desnoyers <[email protected]>
tracing: Fix sched switch start/stop refcount racy updates
Lu Shuaibing <[email protected]>
ipc/msg.c: consolidate all xxxctl_down() functions
Oliver Neukum <[email protected]>
mfd: dln2: More sanity checking for endpoints
Will Deacon <[email protected]>
media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors
David Howells <[email protected]>
rxrpc: Fix NULL pointer deref due to call->conn being cleared on disconnect
David Howells <[email protected]>
rxrpc: Fix missing active use pinning of rxrpc_local object
David Howells <[email protected]>
rxrpc: Fix insufficient receive notification generation
David Howells <[email protected]>
rxrpc: Fix use-after-free in rxrpc_put_local()
Eric Dumazet <[email protected]>
tcp: clear tp->segs_{in|out} in tcp_disconnect()Eric Dumazet <[email protected]>
tcp: clear tp->data_segs{in|out} in tcp_disconnect()Eric Dumazet <[email protected]>
tcp: clear tp->delivered in tcp_disconnect()
Eric Dumazet <[email protected]>
tcp: clear tp->total_retrans in tcp_disconnect()
Michael Chan <[email protected]>
bnxt_en: Fix TC queue mapping.
Nicolin Chen <[email protected]>
net: stmmac: Delete txtimer in suspend()
Cong Wang <[email protected]>
net_sched: fix an OOB access in cls_tcindex
Eric Dumazet <[email protected]>
net: hsr: fix possible NULL deref in hsr_handle_frame()
Ridge Kennedy <[email protected]>
l2tp: Allow duplicate session creation with UDP
Taehee Yoo <[email protected]>
gtp: use __GFP_NOWARN to avoid memalloc warning
Eric Dumazet <[email protected]>
cls_rsvp: fix rsvp_policy
Arnd Bergmann <[email protected]>
sparc32: fix struct ipc64_perm type definition
Luca Coelho <[email protected]>
iwlwifi: mvm: fix NVM check for 3168 devices
John Ogness <[email protected]>
printk: fix exclusive_console replaying
Jan Kara <[email protected]>
udf: Allow writing to 'Rewritable' partitions
Pawan Gupta <[email protected]>
x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR
Gang He <[email protected]>
ocfs2: fix oops when writing cloned file
Johan Hovold <[email protected]>
media: iguanair: fix endpoint sanity check
YueHaibing <[email protected]>
kernel/module: Fix memleak in module_add_modinfo_attrs()
Miklos Szeredi <[email protected]>
ovl: fix lseek overflow on 32bit
Icenowy Zheng <[email protected]>
Revert "drm/sun4i: dsi: Change the start delay calculation"
-------------
Diffstat:
Makefile | 4 +- arch/arm/include/asm/kvm_emulate.h | 22 + arch/arm/include/asm/kvm_mmio.h | 2 + arch/arm/mach-tegra/sleep-tegra30.S | 11 + arch/arm64/include/asm/kvm_emulate.h | 37 + arch/arm64/include/asm/kvm_mmio.h | 6 +- arch/arm64/include/asm/ptrace.h | 1 + arch/arm64/include/uapi/asm/ptrace.h | 1 + arch/arm64/kvm/inject_fault.c | 70 +- arch/mips/Makefile.postlink | 2 +- arch/mips/boot/Makefile | 2 +- arch/powerpc/Kconfig | 1 + arch/powerpc/boot/4xx.c | 2 +- arch/powerpc/kvm/book3s_hv.c | 4 +- arch/powerpc/kvm/book3s_pr.c | 4 +- arch/powerpc/platforms/pseries/hotplug-memory.c | 4 +- arch/powerpc/xmon/xmon.c | 9 +- arch/s390/include/asm/page.h | 2 + arch/s390/kvm/kvm-s390.c | 6 +- arch/s390/mm/hugetlbpage.c | 100 +- arch/sparc/include/uapi/asm/ipcbuf.h | 22 +- arch/x86/include/asm/apic.h | 8 + arch/x86/include/asm/kvm_host.h | 8 +- arch/x86/kernel/apic/msi.c | 128 +- arch/x86/kernel/cpu/tsx.c | 13 +- arch/x86/kvm/emulate.c | 27 +- arch/x86/kvm/hyperv.c | 10 +- arch/x86/kvm/i8259.c | 6 +- arch/x86/kvm/ioapic.c | 15 +- arch/x86/kvm/lapic.c | 13 +- arch/x86/kvm/mmu.c | 78 +- arch/x86/kvm/mmutrace.h | 12 +- arch/x86/kvm/mtrr.c | 8 +- arch/x86/kvm/paging_tmpl.h | 25 +- arch/x86/kvm/pmu.h | 18 +- arch/x86/kvm/pmu_intel.c | 24 +- arch/x86/kvm/vmx.c | 4 +- arch/x86/kvm/vmx/vmx.c | 8033 ++++++++++++++++++++ arch/x86/kvm/x86.c | 101 +- arch/x86/kvm/x86.h | 2 +- crypto/algapi.c | 22 +- crypto/api.c | 3 +- crypto/internal.h | 1 - crypto/pcrypt.c | 1 - drivers/acpi/battery.c | 75 +- drivers/acpi/video_detect.c | 13 + drivers/base/power/main.c | 42 +- drivers/clk/tegra/clk-tegra-periph.c | 6 +- drivers/crypto/atmel-aes.c | 37 +- drivers/crypto/ccp/ccp-dev-v3.c | 1 + drivers/crypto/ccree/cc_driver.h | 1 + drivers/crypto/ccree/cc_pm.c | 30 +- drivers/crypto/ccree/cc_request_mgr.c | 51 +- drivers/crypto/ccree/cc_request_mgr.h | 8 - drivers/crypto/geode-aes.c | 442 +- drivers/crypto/geode-aes.h | 15 +- drivers/crypto/picoxcell_crypto.c | 15 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 8 +- drivers/gpu/drm/drm_dp_mst_topology.c | 12 + drivers/gpu/drm/drm_rect.c | 7 +- drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c | 2 +- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 3 +- drivers/hv/hv_balloon.c | 13 +- drivers/infiniband/core/umem_odp.c | 2 +- drivers/infiniband/hw/mlx5/gsi.c | 3 +- drivers/md/bcache/bcache.h | 3 + drivers/md/bcache/request.c | 17 +- drivers/md/bcache/sysfs.c | 22 + drivers/md/dm-crypt.c | 10 +- drivers/md/dm-writecache.c | 41 +- drivers/md/dm-zoned-metadata.c | 23 +- drivers/md/dm.c | 9 +- drivers/md/persistent-data/dm-space-map-common.c | 27 + drivers/md/persistent-data/dm-space-map-common.h | 2 + drivers/md/persistent-data/dm-space-map-disk.c | 6 +- drivers/md/persistent-data/dm-space-map-metadata.c | 5 +- drivers/media/rc/iguanair.c | 2 +- drivers/media/rc/rc-main.c | 27 +- drivers/media/usb/uvc/uvc_driver.c | 12 + drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 148 +- drivers/media/v4l2-core/videobuf-dma-sg.c | 5 +- drivers/mfd/axp20x.c | 2 +- drivers/mfd/da9062-core.c | 2 +- drivers/mfd/dln2.c | 13 +- drivers/mfd/rn5t618.c | 1 + drivers/mmc/host/mmc_spi.c | 11 +- drivers/mmc/host/sdhci-of-at91.c | 9 +- drivers/mtd/ubi/fastmap.c | 23 +- drivers/net/bonding/bond_alb.c | 44 +- drivers/net/dsa/b53/b53_common.c | 2 +- drivers/net/dsa/bcm_sf2.c | 4 +- drivers/net/ethernet/broadcom/bcmsysport.c | 3 + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- drivers/net/ethernet/cadence/macb_main.c | 14 +- drivers/net/ethernet/dec/tulip/dmfe.c | 7 +- drivers/net/ethernet/dec/tulip/uli526x.c | 4 +- drivers/net/ethernet/marvell/mvneta.c | 27 +- .../net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 3 +- drivers/net/ethernet/smsc/smc911x.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 + drivers/net/gtp.c | 4 +- drivers/net/ppp/ppp_async.c | 18 +- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 1 + drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 10 +- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 1 + drivers/nfc/pn544/pn544.c | 2 +- drivers/of/Kconfig | 4 + drivers/of/address.c | 6 +- drivers/pci/controller/dwc/pci-keystone-dw.c | 2 +- drivers/pci/controller/pci-tegra.c | 2 +- drivers/phy/qualcomm/phy-qcom-apq8064-sata.c | 2 +- drivers/platform/x86/intel_scu_ipc.c | 21 +- drivers/power/supply/ltc2941-battery-gauge.c | 2 +- drivers/scsi/csiostor/csio_scsi.c | 2 +- drivers/scsi/qla2xxx/qla_dbg.c | 6 - drivers/scsi/qla2xxx/qla_dbg.h | 6 + drivers/scsi/qla2xxx/qla_isr.c | 12 + drivers/scsi/qla2xxx/qla_mbx.c | 3 +- drivers/scsi/qla2xxx/qla_nx.c | 7 +- drivers/scsi/qla4xxx/ql4_os.c | 2 +- drivers/scsi/ufs/ufshcd.c | 3 + drivers/usb/gadget/function/f_ecm.c | 16 +- drivers/usb/gadget/function/f_ncm.c | 17 +- drivers/usb/gadget/legacy/cdc2.c | 2 +- drivers/usb/gadget/legacy/g_ffs.c | 2 +- drivers/usb/gadget/legacy/multi.c | 2 +- drivers/usb/gadget/legacy/ncm.c | 2 +- drivers/usb/typec/tcpci.c | 6 + drivers/watchdog/watchdog_core.c | 35 + drivers/watchdog/watchdog_dev.c | 36 +- drivers/xen/xen-balloon.c | 2 +- fs/aio.c | 20 +- fs/btrfs/ctree.c | 8 +- fs/btrfs/ctree.h | 6 +- fs/btrfs/delayed-ref.c | 8 +- fs/btrfs/disk-io.c | 22 +- fs/btrfs/extent_io.c | 8 + fs/btrfs/tests/btrfs-tests.c | 1 - fs/btrfs/transaction.c | 8 + fs/btrfs/tree-log.c | 388 +- fs/cifs/smb2pdu.c | 14 +- fs/eventfd.c | 15 + fs/ext2/super.c | 6 +- fs/ext4/page-io.c | 19 +- fs/f2fs/super.c | 14 +- fs/gfs2/file.c | 72 +- fs/jbd2/journal.c | 1 + fs/nfs/dir.c | 47 +- fs/nfsd/nfs4layouts.c | 2 +- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/state.h | 2 +- fs/nfsd/vfs.c | 1 + fs/ocfs2/file.c | 14 +- fs/overlayfs/file.c | 2 +- fs/overlayfs/readdir.c | 8 +- fs/ubifs/dir.c | 2 + fs/ubifs/file.c | 4 +- fs/ubifs/ioctl.c | 11 +- fs/udf/super.c | 1 - include/linux/eventfd.h | 14 + include/linux/irq.h | 18 + include/linux/irqdomain.h | 7 + include/linux/kvm_host.h | 8 +- include/linux/memblock.h | 15 - include/linux/percpu-defs.h | 3 +- include/media/v4l2-rect.h | 8 +- include/net/ipx.h | 5 - ipc/msg.c | 19 +- kernel/events/core.c | 10 +- kernel/irq/debugfs.c | 1 + kernel/irq/irqdomain.c | 1 + kernel/irq/msi.c | 5 +- kernel/module.c | 2 + kernel/padata.c | 46 +- kernel/printk/printk.c | 4 +- kernel/rcu/tree_plugin.h | 11 +- kernel/time/alarmtimer.c | 8 +- kernel/time/clocksource.c | 11 +- kernel/trace/ftrace.c | 15 +- kernel/trace/trace.h | 29 +- kernel/trace/trace_sched_switch.c | 4 +- lib/test_kasan.c | 1 + mm/memory_hotplug.c | 9 +- mm/migrate.c | 25 +- mm/page_alloc.c | 64 +- net/hsr/hsr_slave.c | 2 + net/ipv4/tcp.c | 6 + net/l2tp/l2tp_core.c | 7 +- net/rxrpc/af_rxrpc.c | 2 + net/rxrpc/ar-internal.h | 11 + net/rxrpc/call_object.c | 4 +- net/rxrpc/conn_client.c | 3 +- net/rxrpc/conn_event.c | 31 +- net/rxrpc/conn_object.c | 3 +- net/rxrpc/input.c | 6 +- net/rxrpc/local_object.c | 23 +- net/rxrpc/output.c | 27 +- net/rxrpc/peer_event.c | 42 +- net/sched/cls_rsvp.h | 6 +- net/sched/cls_tcindex.c | 43 +- net/sunrpc/auth_gss/svcauth_gss.c | 4 + samples/bpf/Makefile | 2 +- scripts/find-unused-docs.sh | 2 +- sound/drivers/dummy.c | 2 +- sound/pci/hda/hda_intel.c | 2 + sound/usb/validate.c | 6 +- tools/kvm/kvm_stat/kvm_stat | 8 +- virt/kvm/arm/aarch32.c | 117 +- virt/kvm/arm/mmio.c | 6 + virt/kvm/async_pf.c | 10 +- virt/kvm/kvm_main.c | 4 +- 213 files changed, 10303 insertions(+), 1570 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/195 Revert "drm/sun4i: dsi: Change the start delay calculation"
From: Icenowy Zheng <[email protected]>
[ Upstream commit a00d17e0a71ae2e4fdaac46e1c12785d3346c3f2 ]
This reverts commit da676c6aa6413d59ab0a80c97bbc273025e640b2.
The original commit adds a start parameter to the calculation of the start delay according to some old BSP versions from Allwinner. However, there're two ways to add this delay -- add it in DSI controller or add it in the TCON. Add it in both controllers won't work.
The code before this commit is picked from new versions of BSP kernel, which has a comment for the 1 that says "put start_delay to tcon". By checking the sun4i_tcon0_mode_set_cpu() in sun4i_tcon driver, it has already added this delay, so we shouldn't repeat to add the delay in DSI controller, otherwise the timing won't match.
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +1 -2
@@ -357,8 +357,7 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,static u16 sun6i_dsi_get_video_start_delay (struct sun6i_dsi *dsi,struct drm_display_mode *mode) { -u16 start =clamp (mode->vtotal - mode->vdisplay -10 ,8 ,100 ); -u16 delay = mode->vtotal - (mode->vsync_end - mode->vdisplay) + start; +u16 delay = mode->vtotal - (mode->vsync_end - mode->vdisplay) +1 ;if (delay > mode->vtotal) delay = delay % mode->vtotal;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 2/195 ovl: fix lseek overflow on 32bit
In reply to Greg Kroah-HartmanFrom: Miklos Szeredi <[email protected]>
[ Upstream commit a4ac9d45c0cd14a2adc872186431c79804b77dbf ]
ovl_lseek() is using ssize_t to return the value from vfs_llseek(). On a 32-bit kernel ssize_t is a 32-bit signed int, which overflows above 2 GB.
Assign the return value of vfs_llseek() to loff_t to fix this.
--- fs/overlayfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/overlayfs/file.c +1 -1
@@ -149,7 +149,7 @@ static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)struct inode *inode =file_inode (file);struct fd real;const struct cred *old_cred; -ssize_t ret; +loff_t ret;/* * The two special cases below do not need to involve real fs,
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 3/195 kernel/module: Fix memleak in module_add_modinfo_attrs()
In reply to Greg Kroah-HartmanFrom: YueHaibing <[email protected]>
[ Upstream commit f6d061d617124abbd55396a3bc37b9bf7d33233c ]
In module_add_modinfo_attrs() if sysfs_create_file() fails on the first iteration of the loop (so i = 0), we forget to free the modinfo_attrs.
--- kernel/module.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/module.c +2 -0
@@ -1729,6 +1729,8 @@ static int module_add_modinfo_attrs(struct module *mod) error_out:if (i >0 )module_remove_modinfo_attrs (mod, --i); +else +kfree (mod->modinfo_attrs);return error; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 4/195 media: iguanair: fix endpoint sanity check
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
[ Upstream commit 1b257870a78b0a9ce98fdfb052c58542022ffb5b ]
Make sure to use the current alternate setting, which need not be the first one by index, when verifying the endpoint descriptors and initialising the URBs.
Failing to do so could cause the driver to misbehave or trigger a WARN() in usb_submit_urb() that kernels with panic_on_warn set would choke on.
--- drivers/media/rc/iguanair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/rc/iguanair.c +1 -1
@@ -424,7 +424,7 @@ static int iguanair_probe(struct usb_interface *intf,int ret, pipein, pipeout;struct usb_host_interface *idesc; - idesc = intf->altsetting; + idesc = intf->cur_altsetting;if (idesc->desc.bNumEndpoints <2 )return -ENODEV ;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 5/195 ocfs2: fix oops when writing cloned file
In reply to Greg Kroah-HartmanFrom: Gang He <[email protected]>
[ Upstream commit 2d797e9ff95ecbcf0a83d657928ed20579444857 ]
Writing a cloned file triggers a kernel oops and the user-space command process is also killed by the system. The bug can be reproduced stably via:
1) create a file under ocfs2 file system directory.
journalctl -b > aa.txt
2) create a cloned file for this file.
reflink aa.txt bb.txt
3) write the cloned file with dd command.
dd if=/dev/zero of=bb.txt bs=512 count=1 conv=notrunc
The dd command is killed by the kernel, then you can see the oops message via dmesg command.
[ 463.875404] BUG: kernel NULL pointer dereference, address: 0000000000000028 [ 463.875413] #PF: supervisor read access in kernel mode [ 463.875416] #PF: error_code(0x0000) - not-present page [ 463.875418] PGD 0 P4D 0 [ 463.875425] Oops: 0000 [#1] SMP PTI [ 463.875431] CPU: 1 PID: 2291 Comm: dd Tainted: G OE 5.3.16-2-default [ 463.875433] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 [ 463.875500] RIP: 0010:ocfs2_refcount_cow+0xa4/0x5d0 [ocfs2] [ 463.875505] Code: 06 89 6c 24 38 89 eb f6 44 24 3c 02 74 be 49 8b 47 28 [ 463.875508] RSP: 0018:ffffa2cb409dfce8 EFLAGS: 00010202 [ 463.875512] RAX: ffff8b1ebdca8000 RBX: 0000000000000001 RCX: ffff8b1eb73a9df0 [ 463.875515] RDX: 0000000000056a01 RSI: 0000000000000000 RDI: 0000000000000000 [ 463.875517] RBP: 0000000000000001 R08: ffff8b1eb73a9de0 R09: 0000000000000000 [ 463.875520] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 [ 463.875522] R13: ffff8b1eb922f048 R14: 0000000000000000 R15: ffff8b1eb922f048 [ 463.875526] FS: 00007f8f44d15540(0000) GS:ffff8b1ebeb00000(0000) knlGS:0000000000000000 [ 463.875529] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 463.875532] CR2: 0000000000000028 CR3: 000000003c17a000 CR4: 00000000000006e0 [ 463.875546] Call Trace: [ 463.875596] ? ocfs2_inode_lock_full_nested+0x18b/0x960 [ocfs2] [ 463.875648] ocfs2_file_write_iter+0xaf8/0xc70 [ocfs2] [ 463.875672] new_sync_write+0x12d/0x1d0 [ 463.875688] vfs_write+0xad/0x1a0 [ 463.875697] ksys_write+0xa1/0xe0 [ 463.875710] do_syscall_64+0x60/0x1f0 [ 463.875743] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 463.875758] RIP: 0033:0x7f8f4482ed44 [ 463.875762] Code: 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 80 00 00 00 [ 463.875765] RSP: 002b:00007fff300a79d8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 463.875769] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f8f4482ed44 [ 463.875771] RDX: 0000000000000200 RSI: 000055f771b5c000 RDI: 0000000000000001 [ 463.875774] RBP: 0000000000000200 R08: 00007f8f44af9c78 R09: 0000000000000003 [ 463.875776] R10: 000000000000089f R11: 0000000000000246 R12: 000055f771b5c000 [ 463.875779] R13: 0000000000000200 R14: 0000000000000000 R15: 000055f771b5c000
This regression problem was introduced by commit e74540b28556 ("ocfs2:
protect extent tree in ocfs2_prepare_inode_for_write()").
--- fs/ocfs2/file.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
fs/ocfs2/file.c +6 -8
@@ -2109,17 +2109,15 @@ static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)static int ocfs2_inode_lock_for_extent_tree (struct inode *inode,struct buffer_head **di_bh,int meta_level, -int overwrite_io,int write_sem,int wait) {int ret =0 ;if (wait) - ret =ocfs2_inode_lock (inode,NULL , meta_level); + ret =ocfs2_inode_lock (inode, di_bh, meta_level);else - ret =ocfs2_try_inode_lock (inode, - overwrite_io ?NULL : di_bh, meta_level); + ret =ocfs2_try_inode_lock (inode, di_bh, meta_level);if (ret <0 ) goto out;
@@ -2144,6 +2142,7 @@ static int ocfs2_inode_lock_for_extent_tree(struct inode *inode, out_unlock:brelse (*di_bh); + *di_bh =NULL ;ocfs2_inode_unlock (inode, meta_level); out:return ret;
@@ -2186,7 +2185,6 @@ static int ocfs2_prepare_inode_for_write(struct file *file, ret =ocfs2_inode_lock_for_extent_tree (inode, &di_bh, meta_level, - overwrite_io, write_sem, wait);if (ret <0 ) {
@@ -2244,13 +2242,13 @@ static int ocfs2_prepare_inode_for_write(struct file *file, &di_bh, meta_level, write_sem); + meta_level =1 ; + write_sem =1 ; ret =ocfs2_inode_lock_for_extent_tree (inode, &di_bh, meta_level, - overwrite_io, -1 , + write_sem, wait); - write_sem =1 ;if (ret <0 ) {if (ret != -EAGAIN )mlog_errno (ret);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 6/195 x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR
In reply to Greg Kroah-HartmanFrom: Pawan Gupta <[email protected]>
[ Upstream commit 5efc6fa9044c3356d6046c6e1da6d02572dbed6b ]
/proc/cpuinfo currently reports Hardware Lock Elision (HLE) feature to be present on boot cpu even if it was disabled during the bootup. This is because cpuinfo_x86->x86_capability HLE bit is not updated after TSX state is changed via the new MSR IA32_TSX_CTRL.
Update the cached HLE bit also since it is expected to change after an update to CPUID_CLEAR bit in MSR IA32_TSX_CTRL.
--- arch/x86/kernel/cpu/tsx.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
arch/x86/kernel/cpu/tsx.c +7 -6
@@ -115,11 +115,12 @@ void __init tsx_init(void)tsx_disable ();/* -* tsx_disable() will change the state of the -* RTM CPUID bit. Clear it here since it is now -* expected to be not set. +* tsx_disable() will change the state of the RTM and HLE CPUID +* bits. Clear them here since they are now expected to be not +* set. */ setup_clear_cpu_cap (X86_FEATURE_RTM ); +setup_clear_cpu_cap (X86_FEATURE_HLE ); }else if (tsx_ctrl_state ==TSX_CTRL_ENABLE ) {/*
@@ -131,10 +132,10 @@ void __init tsx_init(void)tsx_enable ();/* -* tsx_enable() will change the state of the -* RTM CPUID bit. Force it here since it is now -* expected to be set. +* tsx_enable() will change the state of the RTM and HLE CPUID +* bits. Force them here since they are now expected to be set. */ setup_force_cpu_cap (X86_FEATURE_RTM ); +setup_force_cpu_cap (X86_FEATURE_HLE ); } }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 7/195 udf: Allow writing to Rewritable partitions
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
[ Upstream commit 15fb05fd286ac57a0802d71624daeb5c1c2d5b07 ]
UDF 2.60 standard states in section 2.2.14.2:
A partition with Access Type 3 (rewritable) shall define a Freed Space Bitmap or a Freed Space Table, see 2.3.3. All other partitions shall not define a Freed Space Bitmap or a Freed Space Table.
Rewritable partitions are used on media that require some form of preprocessing before re-writing data (for example legacy MO). Such partitions shall use Access Type 3.
Overwritable partitions are used on media that do not require preprocessing before overwriting data (for example: CD-RW, DVD-RW, DVD+RW, DVD-RAM, BD-RE, HD DVD-Rewritable). Such partitions shall use Access Type 4.
however older versions of the standard didn't have this wording and there are tools out there that create UDF filesystems with rewritable partitions but that don't contain a Freed Space Bitmap or a Freed Space Table on media that does not require pre-processing before overwriting a block. So instead of forcing media with rewritable partition read-only, base this decision on presence of a Freed Space Bitmap or a Freed Space Table.
--- fs/udf/super.c | 1 - 1 file changed, 1 deletion(-)
fs/udf/super.c +0 -1
@@ -999,7 +999,6 @@ static int check_partition_desc(struct super_block *sb,switch (le32_to_cpu (p->accessType)) {case PD_ACCESS_TYPE_READ_ONLY :case PD_ACCESS_TYPE_WRITE_ONCE : -case PD_ACCESS_TYPE_REWRITABLE :case PD_ACCESS_TYPE_NONE : goto force_ro; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 8/195 printk: fix exclusive_console replaying
In reply to Greg Kroah-HartmanFrom: John Ogness <[email protected]>
[ Upstream commit def97da136515cb289a14729292c193e0a93bc64 ]
Commit f92b070f2dc8 ("printk: Do not miss new messages when replaying the log") introduced a new variable @exclusive_console_stop_seq to store when an exclusive console should stop printing. It should be set to the @console_seq value at registration. However, @console_seq is previously set to @syslog_seq so that the exclusive console knows where to begin. This results in the exclusive console immediately reactivating all the other consoles and thus repeating the messages for those consoles.
Set @console_seq after @exclusive_console_stop_seq has stored the current @console_seq value.
--- kernel/printk/printk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/printk/printk.c +2 -2
@@ -2717,8 +2717,6 @@ void register_console(struct console *newcon)* for us. */ logbuf_lock_irqsave (flags); - console_seq = syslog_seq; - console_idx = syslog_idx;/* * We're about to replay the log buffer. Only do this to the * just-registered console to avoid excessive message spam to
@@ -2730,6 +2728,8 @@ void register_console(struct console *newcon)*/ exclusive_console = newcon; exclusive_console_stop_seq = console_seq; + console_seq = syslog_seq; + console_idx = syslog_idx;logbuf_unlock_irqrestore (flags); }console_unlock ();
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 9/195 iwlwifi: mvm: fix NVM check for 3168 devices
In reply to Greg Kroah-HartmanFrom: Luca Coelho <[email protected]>
[ Upstream commit b3f20e098293892388d6a0491d6bbb2efb46fbff ]
We had a check on !NVM_EXT and then a check for NVM_SDP in the else block of this if. The else block, obviously, could only be reached if using NVM_EXT, so it would never be NVM_SDP.
Fix that by checking whether the nvm_type is IWL_NVM instead of checking for !IWL_NVM_EXT to solve this issue.
--- drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +1 -1
@@ -286,7 +286,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)int regulatory_type;/* Checking for required sections */ -if (mvm->trans->cfg->nvm_type !=IWL_NVM_EXT ) { +if (mvm->trans->cfg->nvm_type ==IWL_NVM ) {if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW ].data || !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {IWL_ERR (mvm,"Can't parse empty OTP/NVM sections\n" );
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 10/195 sparc32: fix struct ipc64_perm type definition
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
[ Upstream commit 34ca70ef7d3a9fa7e89151597db5e37ae1d429b4 ]
As discussed in the strace issue tracker, it appears that the sparc32 sysvipc support has been broken for the past 11 years. It was however working in compat mode, which is how it must have escaped most of the regular testing.
The problem is that a cleanup patch inadvertently changed the uid/gid fields in struct ipc64_perm from 32-bit types to 16-bit types in uapi headers.
Both glibc and uclibc-ng still use the original types, so they should work fine with compat mode, but not natively. Change the definitions to use __kernel_uid32_t and __kernel_gid32_t again.
--- arch/sparc/include/uapi/asm/ipcbuf.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
arch/sparc/include/uapi/asm/ipcbuf.h +11 -11
@@ -15,19 +15,19 @@struct ipc64_perm { -__kernel_key_t key; -__kernel_uid_t uid; -__kernel_gid_t gid; -__kernel_uid_t cuid; -__kernel_gid_t cgid; +__kernel_key_t key; +__kernel_uid32_t uid; +__kernel_gid32_t gid; +__kernel_uid32_t cuid; +__kernel_gid32_t cgid;#ifndef __arch64__ -unsigned short __pad0; +unsigned short __pad0;#endif -__kernel_mode_t mode; -unsigned short __pad1; -unsigned short seq; -unsigned long long __unused1; -unsigned long long __unused2; +__kernel_mode_t mode; +unsigned short __pad1; +unsigned short seq; +unsigned long long __unused1; +unsigned long long __unused2; };#endif /* __SPARC_IPCBUF_H */
Greg Kroah-Hartman
maintainerPATCH 11/195 cls_rsvp: fix rsvp_policy
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit cb3c0e6bdf64d0d124e94ce43cbe4ccbb9b37f51 ]
NLA_BINARY can be confusing, since .len value represents the max size of the blob.
cls_rsvp really wants user space to provide long enough data for TCA_RSVP_DST and TCA_RSVP_SRC attributes.
BUG: KMSAN: uninit-value in rsvp_get net/sched/cls_rsvp.h:258 [inline] BUG: KMSAN: uninit-value in gen_handle net/sched/cls_rsvp.h:402 [inline] BUG: KMSAN: uninit-value in rsvp_change+0x1ae9/0x4220 net/sched/cls_rsvp.h:572 CPU: 1 PID: 13228 Comm: syz-executor.1 Not tainted 5.5.0-rc5-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1c9/0x220 lib/dump_stack.c:118 kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:118 __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215 rsvp_get net/sched/cls_rsvp.h:258 [inline] gen_handle net/sched/cls_rsvp.h:402 [inline] rsvp_change+0x1ae9/0x4220 net/sched/cls_rsvp.h:572 tc_new_tfilter+0x31fe/0x5010 net/sched/cls_api.c:2104 rtnetlink_rcv_msg+0xcb7/0x1570 net/core/rtnetlink.c:5415 netlink_rcv_skb+0x451/0x650 net/netlink/af_netlink.c:2477 rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:5442 netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline] netlink_unicast+0xf9e/0x1100 net/netlink/af_netlink.c:1328 netlink_sendmsg+0x1248/0x14d0 net/netlink/af_netlink.c:1917 sock_sendmsg_nosec net/socket.c:639 [inline] sock_sendmsg net/socket.c:659 [inline] ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330 ___sys_sendmsg net/socket.c:2384 [inline] __sys_sendmsg+0x451/0x5f0 net/socket.c:2417 __do_sys_sendmsg net/socket.c:2426 [inline] __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424 __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424 do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x45b349 Code: ad b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 7b b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007f269d43dc78 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007f269d43e6d4 RCX: 000000000045b349 RDX: 0000000000000000 RSI: 00000000200001c0 RDI: 0000000000000003 RBP: 000000000075bfc8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff R13: 00000000000009c2 R14: 00000000004cb338 R15: 000000000075bfd4
Uninit was created at:
kmsan_save_stack_with_flags mm/kmsan/kmsan.c:144 [inline] kmsan_internal_poison_shadow+0x66/0xd0 mm/kmsan/kmsan.c:127 kmsan_slab_alloc+0x8a/0xe0 mm/kmsan/kmsan_hooks.c:82 slab_alloc_node mm/slub.c:2774 [inline] __kmalloc_node_track_caller+0xb40/0x1200 mm/slub.c:4382 __kmalloc_reserve net/core/skbuff.c:141 [inline] __alloc_skb+0x2fd/0xac0 net/core/skbuff.c:209 alloc_skb include/linux/skbuff.h:1049 [inline] netlink_alloc_large_skb net/netlink/af_netlink.c:1174 [inline] netlink_sendmsg+0x7d3/0x14d0 net/netlink/af_netlink.c:1892 sock_sendmsg_nosec net/socket.c:639 [inline] sock_sendmsg net/socket.c:659 [inline] ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330 ___sys_sendmsg net/socket.c:2384 [inline] __sys_sendmsg+0x451/0x5f0 net/socket.c:2417 __do_sys_sendmsg net/socket.c:2426 [inline] __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424 __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424 do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 entry_SYSCALL_64_after_hwframe+0x44/0xa9
--- net/sched/cls_rsvp.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/sched/cls_rsvp.h +2 -4
@@ -466,10 +466,8 @@ static u32 gen_tunnel(struct rsvp_head *static const struct nla_policy rsvp_policy[TCA_RSVP_MAX +1 ] = { [TCA_RSVP_CLASSID ] = { .type =NLA_U32 }, - [TCA_RSVP_DST ] = { .type =NLA_BINARY , - .len =RSVP_DST_LEN *sizeof (u32) }, - [TCA_RSVP_SRC ] = { .type =NLA_BINARY , - .len =RSVP_DST_LEN *sizeof (u32) }, + [TCA_RSVP_DST ] = { .len =RSVP_DST_LEN *sizeof (u32) }, + [TCA_RSVP_SRC ] = { .len =RSVP_DST_LEN *sizeof (u32) }, [TCA_RSVP_PINFO ] = { .len =sizeof (struct tc_rsvp_pinfo ) }, };
Greg Kroah-Hartman
maintainerPATCH 12/195 gtp: use __GFP_NOWARN to avoid memalloc warning
In reply to Greg Kroah-HartmanFrom: Taehee Yoo <[email protected]>
[ Upstream commit bd5cd35b782abf5437fbd01dfaee12437d20e832 ]
gtp hashtable size is received by user-space.
So, this hashtable size could be too large. If so, kmalloc will internally print a warning message.
This warning message is actually not necessary for the gtp module. So, this patch adds __GFP_NOWARN to avoid this message.
Splat looks like:
[ 2171.200049][ T1860] WARNING: CPU: 1 PID: 1860 at mm/page_alloc.c:4713 __alloc_pages_nodemask+0x2f3/0x740 [ 2171.238885][ T1860] Modules linked in: gtp veth openvswitch nsh nf_conncount nf_nat nf_conntrack nf_defrag_ipv] [ 2171.262680][ T1860] CPU: 1 PID: 1860 Comm: gtp-link Not tainted 5.5.0+ #321 [ 2171.263567][ T1860] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 2171.264681][ T1860] RIP: 0010:__alloc_pages_nodemask+0x2f3/0x740 [ 2171.265332][ T1860] Code: 64 fe ff ff 65 48 8b 04 25 c0 0f 02 00 48 05 f0 12 00 00 41 be 01 00 00 00 49 89 47 0 [ 2171.267301][ T1860] RSP: 0018:ffff8880b51af1f0 EFLAGS: 00010246 [ 2171.268320][ T1860] RAX: ffffed1016a35e43 RBX: 0000000000000000 RCX: 0000000000000000 [ 2171.269517][ T1860] RDX: 0000000000000000 RSI: 000000000000000b RDI: 0000000000000000 [ 2171.270305][ T1860] RBP: 0000000000040cc0 R08: ffffed1018893109 R09: dffffc0000000000 [ 2171.275973][ T1860] R10: 0000000000000001 R11: ffffed1018893108 R12: 1ffff11016a35e43 [ 2171.291039][ T1860] R13: 000000000000000b R14: 000000000000000b R15: 00000000000f4240 [ 2171.292328][ T1860] FS: 00007f53cbc83740(0000) GS:ffff8880da000000(0000) knlGS:0000000000000000 [ 2171.293409][ T1860] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2171.294586][ T1860] CR2: 000055f540014508 CR3: 00000000b49f2004 CR4: 00000000000606e0 [ 2171.295424][ T1860] Call Trace: [ 2171.295756][ T1860] ? mark_held_locks+0xa5/0xe0 [ 2171.296659][ T1860] ? __alloc_pages_slowpath+0x21b0/0x21b0 [ 2171.298283][ T1860] ? gtp_encap_enable_socket+0x13e/0x400 [gtp] [ 2171.298962][ T1860] ? alloc_pages_current+0xc1/0x1a0 [ 2171.299475][ T1860] kmalloc_order+0x22/0x80 [ 2171.299936][ T1860] kmalloc_order_trace+0x1d/0x140 [ 2171.300437][ T1860] __kmalloc+0x302/0x3a0 [ 2171.300896][ T1860] gtp_newlink+0x293/0xba0 [gtp]
[ ... ]
--- drivers/net/gtp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/gtp.c +2 -2
@@ -772,12 +772,12 @@ static int gtp_hashtable_new(struct gtp_int i; gtp->addr_hash =kmalloc_array (hsize,sizeof (struct hlist_head ), -GFP_KERNEL ); +GFP_KERNEL | __GFP_NOWARN);if (gtp->addr_hash ==NULL )return -ENOMEM ; gtp->tid_hash =kmalloc_array (hsize,sizeof (struct hlist_head ), -GFP_KERNEL ); +GFP_KERNEL | __GFP_NOWARN);if (gtp->tid_hash ==NULL ) goto err1;
Greg Kroah-Hartman
maintainerPATCH 13/195 l2tp: Allow duplicate session creation with UDP
In reply to Greg Kroah-HartmanFrom: Ridge Kennedy <[email protected]>
[ Upstream commit 0d0d9a388a858e271bb70e71e99e7fe2a6fd6f64 ]
In the past it was possible to create multiple L2TPv3 sessions with the same session id as long as the sessions belonged to different tunnels. The resulting sessions had issues when used with IP encapsulated tunnels, but worked fine with UDP encapsulated ones. Some applications began to rely on this behaviour to avoid having to negotiate unique session ids.
Some time ago a change was made to require session ids to be unique across all tunnels, breaking the applications making use of this "feature".
This change relaxes the duplicate session id check to allow duplicates if both of the colliding sessions belong to UDP encapsulated tunnels.
--- net/l2tp/l2tp_core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
net/l2tp/l2tp_core.c +6 -1
@@ -325,8 +325,13 @@ int l2tp_session_register(struct l2tp_sespin_lock_bh (&pn->l2tp_session_hlist_lock); +/* IP encap expects session IDs to be globally unique, while +* UDP encap doesn't. +*/ hlist_for_each_entry (session_walk, g_head, global_hlist) -if (session_walk->session_id == session->session_id) { +if (session_walk->session_id == session->session_id && + (session_walk->tunnel->encap ==L2TP_ENCAPTYPE_IP || + tunnel->encap ==L2TP_ENCAPTYPE_IP )) { err = -EEXIST ; goto err_tlock_pnlock; }
Greg Kroah-Hartman
maintainerPATCH 14/195 net: hsr: fix possible NULL deref in hsr_handle_frame()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 2b5b8251bc9fe2f9118411f037862ee17cf81e97 ]
hsr_port_get_rcu() can return NULL, so we need to be careful.
general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037] CPU: 1 PID: 10249 Comm: syz-executor.5 Not tainted 5.5.0-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:__read_once_size include/linux/compiler.h:199 [inline] RIP: 0010:hsr_addr_is_self+0x86/0x330 net/hsr/hsr_framereg.c:44 Code: 04 00 f3 f3 f3 65 48 8b 04 25 28 00 00 00 48 89 45 d0 31 c0 e8 6b ff 94 f9 4c 89 f2 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80> 3c 02 00 0f 85 75 02 00 00 48 8b 43 30 49 39 c6 49 89 47 c0 0f RSP: 0018:ffffc90000da8a90 EFLAGS: 00010206 RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff87e0cc33 RDX: 0000000000000006 RSI: ffffffff87e035d5 RDI: 0000000000000000 RBP: ffffc90000da8b20 R08: ffff88808e7de040 R09: ffffed1015d2707c R10: ffffed1015d2707b R11: ffff8880ae9383db R12: ffff8880a689bc5e R13: 1ffff920001b5153 R14: 0000000000000030 R15: ffffc90000da8af8 FS: 00007fd7a42be700(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000001b32338000 CR3: 00000000a928c000 CR4: 00000000001406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <IRQ> hsr_handle_frame+0x1c5/0x630 net/hsr/hsr_slave.c:31 __netif_receive_skb_core+0xfbc/0x30b0 net/core/dev.c:5099 __netif_receive_skb_one_core+0xa8/0x1a0 net/core/dev.c:5196 __netif_receive_skb+0x2c/0x1d0 net/core/dev.c:5312 process_backlog+0x206/0x750 net/core/dev.c:6144 napi_poll net/core/dev.c:6582 [inline] net_rx_action+0x508/0x1120 net/core/dev.c:6650 __do_softirq+0x262/0x98c kernel/softirq.c:292 do_softirq_own_stack+0x2a/0x40 arch/x86/entry/entry_64.S:1082 </IRQ>
--- net/hsr/hsr_slave.c | 2 ++ 1 file changed, 2 insertions(+)
net/hsr/hsr_slave.c +2 -0
@@ -32,6 +32,8 @@ static rx_handler_result_t hsr_handle_frrcu_read_lock ();/* hsr->node_db, hsr->ports */ port =hsr_port_get_rcu (skb->dev); +if (!port) + goto finish_pass;if (hsr_addr_is_self (port->hsr,eth_hdr (skb)->h_source)) {/* Directly kill frames sent by ourselves */
Greg Kroah-Hartman
maintainerPATCH 15/195 net_sched: fix an OOB access in cls_tcindex
In reply to Greg Kroah-HartmanFrom: Cong Wang <[email protected]>
[ Upstream commit 599be01ee567b61f4471ee8078870847d0a11e8e ]
As Eric noticed, tcindex_alloc_perfect_hash() uses cp->hash to compute the size of memory allocation, but cp->hash is set again after the allocation, this caused an out-of-bound access.
So we have to move all cp->hash initialization and computation before the memory allocation. Move cp->mask and cp->shift together as cp->hash may need them for computation too.
--- net/sched/cls_tcindex.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-)
net/sched/cls_tcindex.c +20 -20
@@ -333,12 +333,31 @@ tcindex_set_parms(struct net *net, struc cp->fall_through = p->fall_through; cp->tp = tp; +if (tb[TCA_TCINDEX_HASH ]) + cp->hash =nla_get_u32 (tb[TCA_TCINDEX_HASH ]); + +if (tb[TCA_TCINDEX_MASK ]) + cp->mask =nla_get_u16 (tb[TCA_TCINDEX_MASK ]); + +if (tb[TCA_TCINDEX_SHIFT ]) + cp->shift =nla_get_u32 (tb[TCA_TCINDEX_SHIFT ]); + +if (!cp->hash) { +/* Hash not specified, use perfect hash if the upper limit +* of the hashing index is below the threshold. +*/ +if ((cp->mask >> cp->shift) <PERFECT_HASH_THRESHOLD ) + cp->hash = (cp->mask >> cp->shift) +1 ; +else + cp->hash =DEFAULT_HASH_SIZE ; + } +if (p->perfect) {int i;if (tcindex_alloc_perfect_hash (net, cp) <0 ) goto errout; -for (i =0 ; i < cp->hash; i++) +for (i =0 ; i <min (cp->hash, p->hash); i++) cp->perfect[i].res = p->perfect[i].res; balloc =1 ; }
@@ -350,15 +369,6 @@ tcindex_set_parms(struct net *net, strucif (old_r) cr = r->res; -if (tb[TCA_TCINDEX_HASH ]) - cp->hash =nla_get_u32 (tb[TCA_TCINDEX_HASH ]); - -if (tb[TCA_TCINDEX_MASK ]) - cp->mask =nla_get_u16 (tb[TCA_TCINDEX_MASK ]); - -if (tb[TCA_TCINDEX_SHIFT ]) - cp->shift =nla_get_u32 (tb[TCA_TCINDEX_SHIFT ]); - err = -EBUSY ;/* Hash already allocated, make sure that we still meet the
@@ -376,16 +386,6 @@ tcindex_set_parms(struct net *net, strucif (tb[TCA_TCINDEX_FALL_THROUGH ]) cp->fall_through =nla_get_u32 (tb[TCA_TCINDEX_FALL_THROUGH ]); -if (!cp->hash) { -/* Hash not specified, use perfect hash if the upper limit -* of the hashing index is below the threshold. -*/ -if ((cp->mask >> cp->shift) <PERFECT_HASH_THRESHOLD ) - cp->hash = (cp->mask >> cp->shift) +1 ; -else - cp->hash =DEFAULT_HASH_SIZE ; - } -if (!cp->perfect && !cp->h) cp->alloc_hash = cp->hash;
Greg Kroah-Hartman
maintainerPATCH 16/195 net: stmmac: Delete txtimer in suspend()
In reply to Greg Kroah-HartmanFrom: Nicolin Chen <[email protected]>
[ Upstream commit 14b41a2959fbaa50932699d32ceefd6643abacc6 ]
When running v5.5 with a rootfs on NFS, memory abort may happen in the system resume stage:
Unable to handle kernel paging request at virtual address dead00000000012a [dead00000000012a] address between user and kernel address ranges pc : run_timer_softirq+0x334/0x3d8 lr : run_timer_softirq+0x244/0x3d8 x1 : ffff800011cafe80 x0 : dead000000000122 Call trace: run_timer_softirq+0x334/0x3d8 efi_header_end+0x114/0x234 irq_exit+0xd0/0xd8 __handle_domain_irq+0x60/0xb0 gic_handle_irq+0x58/0xa8 el1_irq+0xb8/0x180 arch_cpu_idle+0x10/0x18 do_idle+0x1d8/0x2b0 cpu_startup_entry+0x24/0x40 secondary_start_kernel+0x1b4/0x208 Code: f9000693 a9400660 f9000020 b4000040 (f9000401) ---[ end trace bb83ceeb4c482071 ]--- Kernel panic - not syncing: Fatal exception in interrupt SMP: stopping secondary CPUs SMP: failed to stop secondary CPUs 2-3 Kernel Offset: disabled CPU features: 0x00002,2300aa30 Memory Limit: none ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
It's found that stmmac_xmit() and stmmac_resume() sometimes might run concurrently, possibly resulting in a race condition between mod_timer() and setup_timer(), being called by stmmac_xmit() and stmmac_resume() respectively.
Since the resume() runs setup_timer() every time, it'd be safer to have del_timer_sync() in the suspend() as the counterpart.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +4 -0
@@ -4513,6 +4513,7 @@ int stmmac_suspend(struct device *dev) {struct net_device *ndev =dev_get_drvdata (dev);struct stmmac_priv *priv =netdev_priv (ndev); +u32 chan;if (!ndev || !netif_running (ndev))return 0 ;
@@ -4527,6 +4528,9 @@ int stmmac_suspend(struct device *dev)stmmac_disable_all_queues (priv); +for (chan =0 ; chan < priv->plat->tx_queues_to_use; chan++) +del_timer_sync (&priv->tx_queue[chan].txtimer); +/* Stop TX/RX DMA */ stmmac_stop_all_dma (priv);
Greg Kroah-Hartman
maintainerPATCH 17/195 bnxt_en: Fix TC queue mapping.
In reply to Greg Kroah-HartmanFrom: Michael Chan <[email protected]>
[ Upstream commit 18e4960c18f484ac288f41b43d0e6c4c88e6ea78 ]
The driver currently only calls netdev_set_tc_queue when the number of TCs is greater than 1. Instead, the comparison should be greater than or equal to 1. Even with 1 TC, we need to set the queue mapping.
This bug can cause warnings when the number of TCs is changed back to 1.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +1 -1
@@ -5861,7 +5861,7 @@ static void bnxt_setup_msix(struct bnxtint tcs, i; tcs =netdev_get_num_tc (dev); -if (tcs >1 ) { +if (tcs) {int i, off, count;for (i =0 ; i < tcs; i++) {
Greg Kroah-Hartman
maintainerPATCH 18/195 tcp: clear tp->total_retrans in tcp_disconnect()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit c13c48c00a6bc1febc73902505bdec0967bd7095 ]
total_retrans needs to be cleared in tcp_disconnect().
tcp_disconnect() is rarely used, but it is worth fixing it.
--- net/ipv4/tcp.c | 1 + 1 file changed, 1 insertion(+)
net/ipv4/tcp.c +1 -0
@@ -2592,6 +2592,7 @@ int tcp_disconnect(struct sock *sk, inttcp_set_ca_state (sk, TCP_CA_Open); tp->is_sack_reneg =0 ;tcp_clear_retrans (tp); + tp->total_retrans =0 ;inet_csk_delack_init (sk);/* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 * issue in __tcp_select_window()
Greg Kroah-Hartman
maintainerPATCH 19/195 tcp: clear tp->delivered in tcp_disconnect()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 2fbdd56251b5c62f96589f39eded277260de7267 ]
tp->delivered needs to be cleared in tcp_disconnect().
tcp_disconnect() is rarely used, but it is worth fixing it.
--- net/ipv4/tcp.c | 1 + 1 file changed, 1 insertion(+)
net/ipv4/tcp.c +1 -0
@@ -2588,6 +2588,7 @@ int tcp_disconnect(struct sock *sk, int tp->snd_ssthresh =TCP_INFINITE_SSTHRESH ; tp->snd_cwnd_cnt =0 ; tp->window_clamp =0 ; + tp->delivered =0 ; tp->delivered_ce =0 ;tcp_set_ca_state (sk, TCP_CA_Open); tp->is_sack_reneg =0 ;
Greg Kroah-Hartman
maintainerPATCH 20/195 tcp: clear tp->data_segs{in|out} in tcp_disconnect()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit db7ffee6f3eb3683cdcaeddecc0a630a14546fe3 ]
tp->data_segs_in and tp->data_segs_out need to be cleared in tcp_disconnect().
tcp_disconnect() is rarely used, but it is worth fixing it.
--- net/ipv4/tcp.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv4/tcp.c +2 -0
@@ -2609,6 +2609,8 @@ int tcp_disconnect(struct sock *sk, int tp->bytes_acked =0 ; tp->bytes_received =0 ; tp->bytes_retrans =0 ; + tp->data_segs_in =0 ; + tp->data_segs_out =0 ; tp->dsack_dups =0 ; tp->reord_seen =0 ;
Greg Kroah-Hartman
maintainerPATCH 21/195 tcp: clear tp->segs_{in|out} in tcp_disconnect()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 784f8344de750a41344f4bbbebb8507a730fc99c ]
tp->segs_in and tp->segs_out need to be cleared in tcp_disconnect().
tcp_disconnect() is rarely used, but it is worth fixing it.
--- net/ipv4/tcp.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv4/tcp.c +2 -0
@@ -2605,6 +2605,8 @@ int tcp_disconnect(struct sock *sk, int sk->sk_rx_dst =NULL ;tcp_saved_syn_free (tp); tp->compressed_ack =0 ; + tp->segs_in =0 ; + tp->segs_out =0 ; tp->bytes_sent =0 ; tp->bytes_acked =0 ; tp->bytes_received =0 ;
Greg Kroah-Hartman
maintainerPATCH 22/195 rxrpc: Fix use-after-free in rxrpc_put_local()
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit fac20b9e738523fc884ee3ea5be360a321cd8bad ]
Fix rxrpc_put_local() to not access local->debug_id after calling atomic_dec_return() as, unless that returned n==0, we no longer have the right to access the object.
--- net/rxrpc/local_object.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/rxrpc/local_object.c +4 -1
@@ -368,11 +368,14 @@ void rxrpc_queue_local(struct rxrpc_locavoid rxrpc_put_local (struct rxrpc_local *local) {const void *here =__builtin_return_address (0 ); +unsigned int debug_id;int n;if (local) { + debug_id = local->debug_id; + n =atomic_dec_return (&local->usage); -trace_rxrpc_local (local->debug_id, rxrpc_local_put, n, here); +trace_rxrpc_local (debug_id, rxrpc_local_put, n, here);if (n ==0 )call_rcu (&local->rcu, rxrpc_local_rcu);
Greg Kroah-Hartman
maintainerPATCH 23/195 rxrpc: Fix insufficient receive notification generation
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit f71dbf2fb28489a79bde0dca1c8adfb9cdb20a6b ]
In rxrpc_input_data(), rxrpc_notify_socket() is called if the base sequence number of the packet is immediately following the hard-ack point at the end of the function. However, this isn't sufficient, since the recvmsg side may have been advancing the window and then overrun the position in which we're adding - at which point rx_hard_ack >= seq0 and no notification is generated.
Fix this by always generating a notification at the end of the input function.
Without this, a long call may stall, possibly indefinitely.
--- net/rxrpc/input.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/rxrpc/input.c +2 -4
@@ -612,10 +612,8 @@ ack: false, true, rxrpc_propose_ack_input_data); -if (sp->hdr.seq ==READ_ONCE (call->rx_hard_ack) +1 ) { -trace_rxrpc_notify_socket (call->debug_id, serial); -rxrpc_notify_socket (call); - } +trace_rxrpc_notify_socket (call->debug_id, serial); +rxrpc_notify_socket (call); unlock:spin_unlock (&call->input_lock);
Greg Kroah-Hartman
maintainerPATCH 24/195 rxrpc: Fix missing active use pinning of rxrpc_local object
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit 04d36d748fac349b068ef621611f454010054c58 ]
The introduction of a split between the reference count on rxrpc_local objects and the usage count didn't quite go far enough. A number of kernel work items need to make use of the socket to perform transmission. These also need to get an active count on the local object to prevent the socket from being closed.
Fix this by getting the active count in those places.
Also split out the raw active count get/put functions as these places tend to hold refs on the rxrpc_local object already, so getting and putting an extra object ref is just a waste of time.
The problem can lead to symptoms like:
BUG: kernel NULL pointer dereference, address: 0000000000000018
..
CPU: 2 PID: 818 Comm: kworker/u9:0 Not tainted 5.5.0-fscache+ #51
...
RIP: 0010:selinux_socket_sendmsg+0x5/0x13
...
Call Trace:
security_socket_sendmsg+0x2c/0x3e
sock_sendmsg+0x1a/0x46
rxrpc_send_keepalive+0x131/0x1ae
rxrpc_peer_keepalive_worker+0x219/0x34b
process_one_work+0x18e/0x271
worker_thread+0x1a3/0x247
kthread+0xe6/0xeb
ret_from_fork+0x1f/0x30--- net/rxrpc/af_rxrpc.c | 2 ++ net/rxrpc/ar-internal.h | 10 ++++++++++ net/rxrpc/conn_event.c | 31 +++++++++++++++++++++---------- net/rxrpc/local_object.c | 18 +++++++----------- net/rxrpc/peer_event.c | 40 ++++++++++++++++++++++------------------ 5 files changed, 62 insertions(+), 39 deletions(-)
net/rxrpc/af_rxrpc.c +2 -0
@@ -196,6 +196,7 @@ static int rxrpc_bind(struct socket *soc service_in_use:write_unlock (&local->services_lock);rxrpc_unuse_local (local); +rxrpc_put_local (local); ret = -EADDRINUSE ; error_unlock:release_sock (&rx->sk);
@@ -906,6 +907,7 @@ static int rxrpc_release_sock(struct socrxrpc_purge_queue (&sk->sk_receive_queue);rxrpc_unuse_local (rx->local); +rxrpc_put_local (rx->local); rx->local =NULL ;key_put (rx->key); rx->key =NULL ;
net/rxrpc/ar-internal.h +10 -0
@@ -1006,6 +1006,16 @@ void rxrpc_unuse_local(struct rxrpc_locavoid rxrpc_queue_local (struct rxrpc_local *);void rxrpc_destroy_all_locals (struct rxrpc_net *); +static inline bool __rxrpc_unuse_local (struct rxrpc_local *local) +{ +return atomic_dec_return (&local->active_users) ==0 ; +} + +static inline bool __rxrpc_use_local (struct rxrpc_local *local) +{ +return atomic_fetch_add_unless (&local->active_users,1 ,0 ) !=0 ; +} +/* * misc.c */
net/rxrpc/conn_event.c +21 -10
@@ -453,16 +453,12 @@ again:/* * connection-level event processor */ -void rxrpc_process_connection (struct work_struct *work) +static void rxrpc_do_process_connection (struct rxrpc_connection *conn) { -struct rxrpc_connection *conn = - container_of(work, struct rxrpc_connection, processor);struct sk_buff *skb;u32 abort_code =RX_PROTOCOL_ERROR ;int ret; -rxrpc_see_connection (conn); -if (test_and_clear_bit (RXRPC_CONN_EV_CHALLENGE , &conn->events))rxrpc_secure_connection (conn);
@@ -490,18 +486,33 @@ void rxrpc_process_connection(struct wor } } -out: -rxrpc_put_connection (conn); -_leave ("" );return ; requeue_and_leave:skb_queue_head (&conn->rx_queue, skb); - goto out; +return ; protocol_error:if (rxrpc_abort_connection (conn, ret, abort_code) <0 ) goto requeue_and_leave;rxrpc_free_skb (skb, rxrpc_skb_rx_freed); - goto out; +return ; +} + +void rxrpc_process_connection (struct work_struct *work) +{ +struct rxrpc_connection *conn = + container_of(work, struct rxrpc_connection, processor); + +rxrpc_see_connection (conn); + +if (__rxrpc_use_local (conn->params.local)) { +rxrpc_do_process_connection (conn); +rxrpc_unuse_local (conn->params.local); + } + +rxrpc_put_connection (conn); +_leave ("" ); +return ; } +
net/rxrpc/local_object.c +7 -11
@@ -387,14 +387,11 @@ void rxrpc_put_local(struct rxrpc_local*/ struct rxrpc_local *rxrpc_use_local (struct rxrpc_local *local) { -unsigned int au; - local =rxrpc_get_local_maybe (local);if (!local)return NULL ; - au =atomic_fetch_add_unless (&local->active_users,1 ,0 ); -if (au ==0 ) { +if (!__rxrpc_use_local (local)) {rxrpc_put_local (local);return NULL ; }
@@ -408,14 +405,11 @@ struct rxrpc_local *rxrpc_use_local(stru*/ void rxrpc_unuse_local (struct rxrpc_local *local) { -unsigned int au; -if (local) { - au =atomic_dec_return (&local->active_users); -if (au ==0 ) +if (__rxrpc_unuse_local (local)) { +rxrpc_get_local (local);rxrpc_queue_local (local); -else -rxrpc_put_local (local); + } } }
@@ -472,7 +466,7 @@ static void rxrpc_local_processor(struct do { again = false; - if (atomic_read(&local->active_users) == 0) { + if (!__rxrpc_use_local(local)) { rxrpc_local_destroyer(local); break; }
@@ -486,6 +480,8 @@ static void rxrpc_local_processor(structrxrpc_process_local_events (local); again = true; } + +__rxrpc_unuse_local (local); }while (again);rxrpc_put_local (local);
net/rxrpc/peer_event.c +22 -18
@@ -357,27 +357,31 @@ static void rxrpc_peer_keepalive_dispatcif (!rxrpc_get_peer_maybe (peer))continue ; -spin_unlock_bh (&rxnet->peer_hash_lock); +if (__rxrpc_use_local (peer->local)) { +spin_unlock_bh (&rxnet->peer_hash_lock); - keepalive_at = peer->last_tx_at +RXRPC_KEEPALIVE_TIME ; - slot = keepalive_at - base; -_debug ("%02x peer %u t=%d {%pISp}" , - cursor, peer->debug_id, slot, &peer->srx.transport); + keepalive_at = peer->last_tx_at +RXRPC_KEEPALIVE_TIME ; + slot = keepalive_at - base; +_debug ("%02x peer %u t=%d {%pISp}" , + cursor, peer->debug_id, slot, &peer->srx.transport); -if (keepalive_at <= base || - keepalive_at > base +RXRPC_KEEPALIVE_TIME ) { -rxrpc_send_keepalive (peer); - slot =RXRPC_KEEPALIVE_TIME ; - } +if (keepalive_at <= base || + keepalive_at > base +RXRPC_KEEPALIVE_TIME ) { +rxrpc_send_keepalive (peer); + slot =RXRPC_KEEPALIVE_TIME ; + } -/* A transmission to this peer occurred since last we examined -* it so put it into the appropriate future bucket. -*/ - slot += cursor; - slot &= mask; -spin_lock_bh (&rxnet->peer_hash_lock); -list_add_tail (&peer->keepalive_link, - &rxnet->peer_keepalive[slot & mask]); +/* A transmission to this peer occurred since last we +* examined it so put it into the appropriate future +* bucket. +*/ + slot += cursor; + slot &= mask; +spin_lock_bh (&rxnet->peer_hash_lock); +list_add_tail (&peer->keepalive_link, + &rxnet->peer_keepalive[slot & mask]); +rxrpc_unuse_local (peer->local); + }rxrpc_put_peer_locked (peer); }
Greg Kroah-Hartman
maintainerPATCH 25/195 rxrpc: Fix NULL pointer deref due to call->conn being cleared on disconnect
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit 5273a191dca65a675dc0bcf3909e59c6933e2831 ]
When a call is disconnected, the connection pointer from the call is cleared to make sure it isn't used again and to prevent further attempted transmission for the call. Unfortunately, there might be a daemon trying to use it at the same time to transmit a packet.
Fix this by keeping call->conn set, but setting a flag on the call to indicate disconnection instead.
Remove also the bits in the transmission functions where the conn pointer is checked and a ref taken under spinlock as this is now redundant.
--- net/rxrpc/ar-internal.h | 1 + net/rxrpc/call_object.c | 4 ++-- net/rxrpc/conn_client.c | 3 +-- net/rxrpc/conn_object.c | 4 ++-- net/rxrpc/output.c | 27 +++++++++------------------ 5 files changed, 15 insertions(+), 24 deletions(-)
net/rxrpc/ar-internal.h +1 -0
@@ -484,6 +484,7 @@ enum rxrpc_call_flag {RXRPC_CALL_BEGAN_RX_TIMER ,/* We began the expect_rx_by timer */ RXRPC_CALL_RX_HEARD ,/* The peer responded at least once to this call */ RXRPC_CALL_RX_UNDERRUN ,/* Got data underrun */ + RXRPC_CALL_DISCONNECTED, /* The call has been disconnected */ };/*
net/rxrpc/call_object.c +2 -2
@@ -520,7 +520,7 @@ void rxrpc_release_call(struct rxrpc_soc_debug ("RELEASE CALL %p (%d CONN %p)" , call, call->debug_id, conn); -if (conn) +if (conn && !test_bit (RXRPC_CALL_DISCONNECTED , &call->flags))rxrpc_disconnect_call (call);for (i =0 ; i <RXRPC_RXTX_BUFF_SIZE ; i++) {
@@ -654,6 +654,7 @@ static void rxrpc_rcu_destroy_call(struc struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu);struct rxrpc_net *rxnet = call->rxnet; +rxrpc_put_connection (call->conn);rxrpc_put_peer (call->peer);kfree (call->rxtx_buffer);kfree (call->rxtx_annotations);
@@ -677,7 +678,6 @@ void rxrpc_cleanup_call(struct rxrpc_cal ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);ASSERT (test_bit (RXRPC_CALL_RELEASED , &call->flags)); - ASSERTCMP(call->conn, ==, NULL);/* Clean up the Rx/Tx buffer */ for (i =0 ; i <RXRPC_RXTX_BUFF_SIZE ; i++)
net/rxrpc/conn_client.c +1 -2
@@ -786,6 +786,7 @@ void rxrpc_disconnect_client_call(structu32 cid;spin_lock (&conn->channel_lock); +set_bit (RXRPC_CALL_DISCONNECTED , &call->flags); cid = call->cid;if (cid) {
@@ -793,7 +794,6 @@ void rxrpc_disconnect_client_call(struct chan = &conn->channels[channel]; }trace_rxrpc_client (conn, channel, rxrpc_client_chan_disconnect); - call->conn =NULL ;/* Calls that have never actually been assigned a channel can simply be * discarded. If the conn didn't get used either, it will follow
@@ -909,7 +909,6 @@ out:spin_unlock (&rxnet->client_conn_cache_lock); out_2:spin_unlock (&conn->channel_lock); -rxrpc_put_connection (conn);_leave ("" );return ;
net/rxrpc/conn_object.c +2 -2
@@ -174,6 +174,8 @@ void __rxrpc_disconnect_call(struct rxrp_enter ("%d,%x" , conn->debug_id, call->cid); +set_bit (RXRPC_CALL_DISCONNECTED , &call->flags); +if (rcu_access_pointer (chan->call) == call) {/* Save the result of the call so that we can repeat it if necessary * through the channel, whilst disposing of the actual call record.
@@ -226,9 +228,7 @@ void rxrpc_disconnect_call(struct rxrpc___rxrpc_disconnect_call (conn, call);spin_unlock (&conn->channel_lock); - call->conn =NULL ; conn->idle_timestamp = jiffies; -rxrpc_put_connection (conn); }/*
net/rxrpc/output.c +9 -18
@@ -133,7 +133,7 @@ static size_t rxrpc_fill_out_ack(structint rxrpc_send_ack_packet (struct rxrpc_call *call,bool ping,rxrpc_serial_t *_serial) { -struct rxrpc_connection *conn =NULL ; +struct rxrpc_connection *conn;struct rxrpc_ack_buffer *pkt;struct msghdr msg;struct kvec iov[2 ];
@@ -143,18 +143,14 @@ int rxrpc_send_ack_packet(struct rxrpc_cint ret;u8 reason; -spin_lock_bh (&call->lock); -if (call->conn) - conn =rxrpc_get_connection_maybe (call->conn); -spin_unlock_bh (&call->lock); -if (!conn) +if (test_bit (RXRPC_CALL_DISCONNECTED , &call->flags))return -ECONNRESET ; pkt =kzalloc (sizeof (*pkt),GFP_KERNEL ); -if (!pkt) { -rxrpc_put_connection (conn); +if (!pkt)return -ENOMEM ; - } + + conn = call->conn; msg.msg_name = &call->peer->srx.transport; msg.msg_namelen = call->peer->srx.transport_len;
@@ -249,7 +245,6 @@ int rxrpc_send_ack_packet(struct rxrpc_c } out: -rxrpc_put_connection (conn);kfree (pkt);return ret; }
@@ -259,7 +254,7 @@ out:*/ int rxrpc_send_abort_packet (struct rxrpc_call *call) { -struct rxrpc_connection *conn =NULL ; +struct rxrpc_connection *conn;struct rxrpc_abort_buffer pkt;struct msghdr msg;struct kvec iov[1 ];
@@ -276,13 +271,11 @@ int rxrpc_send_abort_packet(struct rxrpc test_bit(RXRPC_CALL_TX_LAST, &call->flags))return 0 ; -spin_lock_bh (&call->lock); -if (call->conn) - conn =rxrpc_get_connection_maybe (call->conn); -spin_unlock_bh (&call->lock); -if (!conn) +if (test_bit (RXRPC_CALL_DISCONNECTED , &call->flags))return -ECONNRESET ; + conn = call->conn; + msg.msg_name = &call->peer->srx.transport; msg.msg_namelen = call->peer->srx.transport_len; msg.msg_control =NULL ;
@@ -317,8 +310,6 @@ int rxrpc_send_abort_packet(struct rxrpctrace_rxrpc_tx_packet (call->debug_id, &pkt.whdr, rxrpc_tx_point_call_abort);rxrpc_tx_backoff (call, ret); - -rxrpc_put_connection (conn);return ret; }
Greg Kroah-Hartman
maintainerPATCH 26/195 media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors
In reply to Greg Kroah-HartmanFrom: Will Deacon <[email protected]>
commit 68035c80e129c4cfec659aac4180354530b26527 upstream.
Way back in 2017, fuzzing the 4.14-rc2 USB stack with syzkaller kicked up the following WARNING from the UVC chain scanning code:
| list_add double add: new=ffff880069084010, prev=ffff880069084010, | next=ffff880067d22298. | ------------[ cut here ]------------ | WARNING: CPU: 1 PID: 1846 at lib/list_debug.c:31 __list_add_valid+0xbd/0xf0 | Modules linked in: | CPU: 1 PID: 1846 Comm: kworker/1:2 Not tainted | 4.14.0-rc2-42613-g1488251d1a98 #238 | Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 | Workqueue: usb_hub_wq hub_event | task: ffff88006b01ca40 task.stack: ffff880064358000 | RIP: 0010:__list_add_valid+0xbd/0xf0 lib/list_debug.c:29 | RSP: 0018:ffff88006435ddd0 EFLAGS: 00010286 | RAX: 0000000000000058 RBX: ffff880067d22298 RCX: 0000000000000000 | RDX: 0000000000000058 RSI: ffffffff85a58800 RDI: ffffed000c86bbac | RBP: ffff88006435dde8 R08: 1ffff1000c86ba52 R09: 0000000000000000 | R10: 0000000000000002 R11: 0000000000000000 R12: ffff880069084010 | R13: ffff880067d22298 R14: ffff880069084010 R15: ffff880067d222a0 | FS: 0000000000000000(0000) GS:ffff88006c900000(0000) knlGS:0000000000000000 | CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 | CR2: 0000000020004ff2 CR3: 000000006b447000 CR4: 00000000000006e0 | Call Trace: | __list_add ./include/linux/list.h:59 | list_add_tail+0x8c/0x1b0 ./include/linux/list.h:92 | uvc_scan_chain_forward.isra.8+0x373/0x416 | drivers/media/usb/uvc/uvc_driver.c:1471 | uvc_scan_chain drivers/media/usb/uvc/uvc_driver.c:1585 | uvc_scan_device drivers/media/usb/uvc/uvc_driver.c:1769 | uvc_probe+0x77f2/0x8f00 drivers/media/usb/uvc/uvc_driver.c:2104
Looking into the output from usbmon, the interesting part is the following data packet:
ffff880069c63e00 30710169 C Ci:1:002:0 0 143 = 09028f00 01030080 00090403 00000e01 00000924 03000103 7c003328 010204db
If we drop the lead configuration and interface descriptors, we're left with an output terminal descriptor describing a generic display:
/* Output terminal descriptor */
buf[0] 09
buf[1] 24
buf[2] 03 /* UVC_VC_OUTPUT_TERMINAL */
buf[3] 00 /* ID */
buf[4] 01 /* type == 0x0301 (UVC_OTT_DISPLAY) */
buf[5] 03
buf[6] 7c
buf[7] 00 /* source ID refers to self! */
buf[8] 33
The problem with this descriptor is that it is self-referential: the source ID of 0 matches itself! This causes the 'struct uvc_entity' representing the display to be added to its chain list twice during 'uvc_scan_chain()': once via 'uvc_scan_chain_entity()' when it is processed directly from the 'dev->entities' list and then again immediately afterwards when trying to follow the source ID in 'uvc_scan_chain_forward()'
Add a check before adding an entity to a chain list to ensure that the entity is not already part of a chain.
--- drivers/media/usb/uvc/uvc_driver.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/media/usb/uvc/uvc_driver.c +12 -0
@@ -1482,6 +1482,11 @@ static int uvc_scan_chain_forward(structbreak ;if (forward == prev)continue ; +if (forward->chain.next || forward->chain.prev) { +uvc_trace (UVC_TRACE_DESCR ,"Found reference to " +"entity %d already in chain.\n" , forward->id); +return -EINVAL ; + }switch (UVC_ENTITY_TYPE (forward)) {case UVC_VC_EXTENSION_UNIT :
@@ -1563,6 +1568,13 @@ static int uvc_scan_chain_backward(strucreturn -1 ; } +if (term->chain.next || term->chain.prev) { +uvc_trace (UVC_TRACE_DESCR ,"Found reference to " +"entity %d already in chain.\n" , + term->id); +return -EINVAL ; + } +if (uvc_trace_param &UVC_TRACE_PROBE )printk (KERN_CONT " %d" , term->id);
Greg Kroah-Hartman
maintainerPATCH 27/195 mfd: dln2: More sanity checking for endpoints
In reply to Greg Kroah-HartmanFrom: Oliver Neukum <[email protected]>
commit 2b8bd606b1e60ca28c765f69c1eedd7d2a2e9dca upstream.
It is not enough to check for the number of endpoints. The types must also be correct.
--- drivers/mfd/dln2.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/mfd/dln2.c +11 -2
@@ -725,6 +725,8 @@ static int dln2_probe(struct usb_interfa const struct usb_device_id *usb_id) {struct usb_host_interface *hostif = interface->cur_altsetting; +struct usb_endpoint_descriptor *epin; +struct usb_endpoint_descriptor *epout;struct device *dev = &interface->dev;struct dln2_dev *dln2;int ret;
@@ -734,12 +736,19 @@ static int dln2_probe(struct usb_interfa hostif->desc.bNumEndpoints < 2)return -ENODEV ; + epin = &hostif->endpoint[0 ].desc; + epout = &hostif->endpoint[1 ].desc; +if (!usb_endpoint_is_bulk_out (epout)) +return -ENODEV ; +if (!usb_endpoint_is_bulk_in (epin)) +return -ENODEV ; + dln2 =kzalloc (sizeof (*dln2),GFP_KERNEL );if (!dln2)return -ENOMEM ; - dln2->ep_out = hostif->endpoint[0 ].desc.bEndpointAddress; - dln2->ep_in = hostif->endpoint[1 ].desc.bEndpointAddress; + dln2->ep_out = epout->bEndpointAddress; + dln2->ep_in = epin->bEndpointAddress; dln2->usb_dev =usb_get_dev (interface_to_usbdev (interface)); dln2->interface = interface;usb_set_intfdata (interface, dln2);
Greg Kroah-Hartman
maintainerPATCH 28/195 ipc/msg.c: consolidate all xxxctl_down() functions
In reply to Greg Kroah-HartmanFrom: Lu Shuaibing <[email protected]>
commit 889b331724c82c11e15ba0a60979cf7bded0a26c upstream.
A use of uninitialized memory in msgctl_down() because msqid64 in ksys_msgctl hasn't been initialized. The local | msqid64 | is created in ksys_msgctl() and then passed into msgctl_down(). Along the way msqid64 is never initialized before msgctl_down() checks msqid64->msg_qbytes.
KUMSAN(KernelUninitializedMemorySantizer, a new error detection tool) reports:
==================================================================
BUG: KUMSAN: use of uninitialized memory in msgctl_down+0x94/0x300 Read of size 8 at addr ffff88806bb97eb8 by task syz-executor707/2022 CPU: 0 PID: 2022 Comm: syz-executor707 Not tainted 5.2.0-rc4+ #63 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 Call Trace: dump_stack+0x75/0xae __kumsan_report+0x17c/0x3e6 kumsan_report+0xe/0x20 msgctl_down+0x94/0x300 ksys_msgctl.constprop.14+0xef/0x260 do_syscall_64+0x7e/0x1f0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x4400e9 Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 fb 13 fc ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007ffd869e0598 EFLAGS: 00000246 ORIG_RAX: 0000000000000047 RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 00000000004400e9 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: 00000000006ca018 R08: 0000000000000000 R09: 0000000000000000 R10: 00000000ffffffff R11: 0000000000000246 R12: 0000000000401970 R13: 0000000000401a00 R14: 0000000000000000 R15: 0000000000000000 The buggy address belongs to the page: page:ffffea0001aee5c0 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 flags: 0x100000000000000() raw: 0100000000000000 0000000000000000 ffffffff01ae0101 0000000000000000 raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: kumsan: bad access detected ==================================================================
Syzkaller reproducer:
msgctl$IPC_RMID(0x0, 0x0)
C reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)
int main(void)
{
syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0); syscall(__NR_msgctl, 0, 0, 0);
return 0;
}
From: Andrew Morton <[email protected]>
Subject: [PATCH 4.19 028/195] ipc/msg.c: consolidate all xxxctl_down() functions
Each line here overflows 80 cols by exactly one character. Delete one tab per line to fix.
--- ipc/msg.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
ipc/msg.c +10 -9
@@ -377,7 +377,7 @@ copy_msqid_from_user(struct msqid64_ds ** NOTE: no locks must be held, the rwsem is taken inside this function. */ static int msgctl_down (struct ipc_namespace *ns,int msqid,int cmd, -struct msqid64_ds *msqid64) +struct ipc64_perm *perm,int msg_qbytes) {struct kern_ipc_perm *ipcp;struct msg_queue *msq;
@@ -387,7 +387,7 @@ static int msgctl_down(struct ipc_namesprcu_read_lock (); ipcp =ipcctl_obtain_check (ns, &msg_ids (ns), msqid, cmd, - &msqid64->msg_perm, msqid64->msg_qbytes); + perm, msg_qbytes);if (IS_ERR (ipcp)) { err =PTR_ERR (ipcp); goto out_unlock1;
@@ -409,18 +409,18 @@ static int msgctl_down(struct ipc_namesp {DEFINE_WAKE_Q (wake_q); -if (msqid64->msg_qbytes > ns->msg_ctlmnb && +if (msg_qbytes > ns->msg_ctlmnb && !capable (CAP_SYS_RESOURCE )) { err = -EPERM ; goto out_unlock1; }ipc_lock_object (&msq->q_perm); - err =ipc_update_perm (&msqid64->msg_perm, ipcp); + err =ipc_update_perm (perm, ipcp);if (err) goto out_unlock0; - msq->q_qbytes = msqid64->msg_qbytes; + msq->q_qbytes = msg_qbytes; msq->q_ctime =ktime_get_real_seconds ();/*
@@ -603,9 +603,10 @@ long ksys_msgctl(int msqid, int cmd, strcase IPC_SET :if (copy_msqid_from_user (&msqid64, buf, version))return -EFAULT ; -/* fallthru */ +return msgctl_down (ns, msqid, cmd, &msqid64.msg_perm, + msqid64.msg_qbytes);case IPC_RMID : -return msgctl_down (ns, msqid, cmd, &msqid64); +return msgctl_down (ns, msqid, cmd,NULL ,0 );default :return -EINVAL ; }
@@ -724,9 +725,9 @@ long compat_ksys_msgctl(int msqid, int ccase IPC_SET :if (copy_compat_msqid_from_user (&msqid64, uptr, version))return -EFAULT ; -/* fallthru */ +return msgctl_down (ns, msqid, cmd, &msqid64.msg_perm, msqid64.msg_qbytes);case IPC_RMID : -return msgctl_down (ns, msqid, cmd, &msqid64); +return msgctl_down (ns, msqid, cmd,NULL ,0 );default :return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 29/195 tracing: Fix sched switch start/stop refcount racy updates
In reply to Greg Kroah-HartmanFrom: Mathieu Desnoyers <[email protected]>
commit 64ae572bc7d0060429e40e1c8d803ce5eb31a0d6 upstream.
Reading the sched_cmdline_ref and sched_tgid_ref initial state within tracing_start_sched_switch without holding the sched_register_mutex is racy against concurrent updates, which can lead to tracepoint probes being registered more than once (and thus trigger warnings within tracepoint.c).
--- kernel/trace/trace_sched_switch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/trace/trace_sched_switch.c +3 -1
@@ -89,8 +89,10 @@ static void tracing_sched_unregister(voistatic void tracing_start_sched_switch (int ops) { -bool sched_register = (!sched_cmdline_ref && !sched_tgid_ref); +bool sched_register; +mutex_lock (&sched_register_mutex); + sched_register = (!sched_cmdline_ref && !sched_tgid_ref);switch (ops) {case RECORD_CMDLINE :
Greg Kroah-Hartman
maintainerPATCH 30/195 rcu: Avoid data-race in rcu_gp_fqs_check_wake()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit 6935c3983b246d5fbfebd3b891c825e65c118f2d upstream.
The rcu_gp_fqs_check_wake() function uses rcu_preempt_blocked_readers_cgp() to read ->gp_tasks while other cpus might overwrite this field.
We need READ_ONCE()/WRITE_ONCE() pairs to avoid compiler tricks and KCSAN splats like the following :
BUG: KCSAN: data-race in rcu_gp_fqs_check_wake / rcu_preempt_deferred_qs_irqrestore
write to 0xffffffff85a7f190 of 8 bytes by task 7317 on cpu 0:
rcu_preempt_deferred_qs_irqrestore+0x43d/0x580 kernel/rcu/tree_plugin.h:507 rcu_read_unlock_special+0xec/0x370 kernel/rcu/tree_plugin.h:659 __rcu_read_unlock+0xcf/0xe0 kernel/rcu/tree_plugin.h:394 rcu_read_unlock include/linux/rcupdate.h:645 [inline] __ip_queue_xmit+0x3b0/0xa40 net/ipv4/ip_output.c:533 ip_queue_xmit+0x45/0x60 include/net/ip.h:236 __tcp_transmit_skb+0xdeb/0x1cd0 net/ipv4/tcp_output.c:1158 __tcp_send_ack+0x246/0x300 net/ipv4/tcp_output.c:3685 tcp_send_ack+0x34/0x40 net/ipv4/tcp_output.c:3691 tcp_cleanup_rbuf+0x130/0x360 net/ipv4/tcp.c:1575 tcp_recvmsg+0x633/0x1a30 net/ipv4/tcp.c:2179 inet_recvmsg+0xbb/0x250 net/ipv4/af_inet.c:838 sock_recvmsg_nosec net/socket.c:871 [inline] sock_recvmsg net/socket.c:889 [inline] sock_recvmsg+0x92/0xb0 net/socket.c:885 sock_read_iter+0x15f/0x1e0 net/socket.c:967 call_read_iter include/linux/fs.h:1864 [inline] new_sync_read+0x389/0x4f0 fs/read_write.c:414
read to 0xffffffff85a7f190 of 8 bytes by task 10 on cpu 1:
rcu_gp_fqs_check_wake kernel/rcu/tree.c:1556 [inline] rcu_gp_fqs_check_wake+0x93/0xd0 kernel/rcu/tree.c:1546 rcu_gp_fqs_loop+0x36c/0x580 kernel/rcu/tree.c:1611 rcu_gp_kthread+0x143/0x220 kernel/rcu/tree.c:1768 kthread+0x1d4/0x200 drivers/block/aoe/aoecmd.c:1253 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:352
Reported by Kernel Concurrency Sanitizer on:
CPU: 1 PID: 10 Comm: rcu_preempt Not tainted 5.3.0+ #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
--- kernel/rcu/tree_plugin.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
kernel/rcu/tree_plugin.h +6 -5
@@ -267,7 +267,7 @@ static void rcu_preempt_ctxt_queue(struc* blocked tasks. */ if (!rnp->gp_tasks && (blkd_state &RCU_GP_BLKD )) { - rnp->gp_tasks = &t->rcu_node_entry; +WRITE_ONCE (rnp->gp_tasks, &t->rcu_node_entry);WARN_ON_ONCE (rnp->completedqs == rnp->gp_seq); }if (!rnp->exp_tasks && (blkd_state &RCU_EXP_BLKD ))
@@ -392,7 +392,7 @@ static void rcu_preempt_note_context_swi*/ static int rcu_preempt_blocked_readers_cgp (struct rcu_node *rnp) { -return rnp->gp_tasks !=NULL ; +return READ_ONCE (rnp->gp_tasks) !=NULL ; }/*
@@ -557,7 +557,7 @@ static void rcu_read_unlock_special(strutrace_rcu_unlock_preempted_task (TPS ("rcu_preempt" ), rnp->gp_seq, t->pid);if (&t->rcu_node_entry == rnp->gp_tasks) - rnp->gp_tasks = np; +WRITE_ONCE (rnp->gp_tasks, np);if (&t->rcu_node_entry == rnp->exp_tasks) rnp->exp_tasks = np;if (IS_ENABLED (CONFIG_RCU_BOOST )) {
@@ -716,7 +716,7 @@ rcu_preempt_check_blocked_tasks(struct rdump_blkd_tasks (rsp, rnp,10 );if (rcu_preempt_has_tasks (rnp) && (rnp->qsmaskinit || rnp->wait_blkd_tasks)) { - rnp->gp_tasks = rnp->blkd_tasks.next; +WRITE_ONCE (rnp->gp_tasks, rnp->blkd_tasks.next); t = container_of(rnp->gp_tasks, struct task_struct, rcu_node_entry); trace_rcu_unlock_preempted_task(TPS("rcu_preempt-GPS"),
@@ -883,7 +883,8 @@ dump_blkd_tasks(struct rcu_state *rsp, spr_info ("%s: %d:%d ->qsmask %#lx ->qsmaskinit %#lx ->qsmaskinitnext %#lx\n" , __func__, rnp1->grplo, rnp1->grphi, rnp1->qsmask, rnp1->qsmaskinit, rnp1->qsmaskinitnext);pr_info ("%s: ->gp_tasks %p ->boost_tasks %p ->exp_tasks %p\n" , - __func__, rnp->gp_tasks, rnp->boost_tasks, rnp->exp_tasks); + __func__,READ_ONCE (rnp->gp_tasks), rnp->boost_tasks, + rnp->exp_tasks);pr_info ("%s: ->blkd_tasks" , __func__); i =0 ;list_for_each (lhp, &rnp->blkd_tasks) {
Greg Kroah-Hartman
maintainerPATCH 31/195 brcmfmac: Fix memory leak in brcmf_usbdev_qinit
In reply to Greg Kroah-HartmanFrom: Navid Emamdoost <[email protected]>
commit 4282dc057d750c6a7dd92953564b15c26b54c22c upstream.
In the implementation of brcmf_usbdev_qinit() the allocated memory for reqs is leaking if usb_alloc_urb() fails. Release reqs in the error handling path.
--- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +1 -0
@@ -441,6 +441,7 @@ fail:usb_free_urb (req->urb);list_del (q->next); } +kfree (reqs);return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 32/195 usb: typec: tcpci: mask event interrupts when remove driver
In reply to Greg Kroah-HartmanFrom: Jun Li <[email protected]>
commit 3ba76256fc4e2a0d7fb26cc95459041ea0e88972 upstream.
This is to prevent any possible events generated while unregister tpcm port.
--- drivers/usb/typec/tcpci.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/typec/tcpci.c +6 -0
@@ -581,6 +581,12 @@ static int tcpci_probe(struct i2c_clientstatic int tcpci_remove (struct i2c_client *client) {struct tcpci_chip *chip =i2c_get_clientdata (client); +int err; + +/* Disable chip interrupts before unregistering port */ + err =tcpci_write16 (chip->tcpci,TCPC_ALERT_MASK ,0 ); +if (err <0 ) +return err;tcpci_unregister_port (chip->tcpci);
Greg Kroah-Hartman
maintainerPATCH 33/195 usb: gadget: legacy: set max_speed to super-speed
In reply to Greg Kroah-HartmanFrom: Roger Quadros <[email protected]>
commit 463f67aec2837f981b0a0ce8617721ff59685c00 upstream.
These interfaces do support super-speed so let's not limit maximum speed to high-speed.
--- drivers/usb/gadget/legacy/cdc2.c | 2 +- drivers/usb/gadget/legacy/g_ffs.c | 2 +- drivers/usb/gadget/legacy/multi.c | 2 +- drivers/usb/gadget/legacy/ncm.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
drivers/usb/gadget/legacy/cdc2.c +1 -1
@@ -225,7 +225,7 @@ static struct usb_composite_driver cdc_d .name = "g_cdc", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = cdc_bind, .unbind = cdc_unbind, };
drivers/usb/gadget/legacy/g_ffs.c +1 -1
@@ -149,7 +149,7 @@ static struct usb_composite_driver gfs_d .name = DRIVER_NAME, .dev = &gfs_dev_desc, .strings = gfs_dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = gfs_bind, .unbind = gfs_unbind, };
drivers/usb/gadget/legacy/multi.c +1 -1
@@ -482,7 +482,7 @@ static struct usb_composite_driver multi .name = "g_multi", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = multi_bind, .unbind = multi_unbind, .needs_serial = 1,
drivers/usb/gadget/legacy/ncm.c +1 -1
@@ -197,7 +197,7 @@ static struct usb_composite_driver ncm_d .name = "g_ncm", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = gncm_bind, .unbind = gncm_unbind, };
Greg Kroah-Hartman
maintainerPATCH 34/195 usb: gadget: f_ncm: Use atomic_t to track in-flight request
In reply to Greg Kroah-HartmanFrom: Bryan O'Donoghue <[email protected]>
commit 5b24c28cfe136597dc3913e1c00b119307a20c7e upstream.
Currently ncm->notify_req is used to flag when a request is in-flight. ncm->notify_req is set to NULL and when a request completes it is subsequently reset.
This is fundamentally buggy in that the unbind logic of the NCM driver will unconditionally free ncm->notify_req leading to a NULL pointer dereference.
--- drivers/usb/gadget/function/f_ncm.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/usb/gadget/function/f_ncm.c +13 -4
@@ -54,6 +54,7 @@ struct f_ncm {struct usb_ep *notify;struct usb_request *notify_req;u8 notify_state; +atomic_t notify_count;bool is_open;const struct ndp_parser_opts *parser_opts;
@@ -547,7 +548,7 @@ static void ncm_do_notify(struct f_ncm *int status;/* notification already in flight? */ -if (!req) +if (atomic_read (&ncm->notify_count))return ; event = req->buf;
@@ -587,7 +588,8 @@ static void ncm_do_notify(struct f_ncm * event->bmRequestType =0xA1 ; event->wIndex =cpu_to_le16 (ncm->ctrl_id); - ncm->notify_req =NULL ; +atomic_inc (&ncm->notify_count); +/* * In double buffering if there is a space in FIFO, * completion callback can be called right after the call,
@@ -597,7 +599,7 @@ static void ncm_do_notify(struct f_ncm * status =usb_ep_queue (ncm->notify, req,GFP_ATOMIC );spin_lock (&ncm->lock);if (status <0 ) { - ncm->notify_req = req; +atomic_dec (&ncm->notify_count);DBG (cdev,"notify --> %d\n" , status); } }
@@ -632,17 +634,19 @@ static void ncm_notify_complete(struct ucase 0 :VDBG (cdev,"Notification %02x sent\n" , event->bNotificationType); +atomic_dec (&ncm->notify_count);break ;case -ECONNRESET :case -ESHUTDOWN : +atomic_set (&ncm->notify_count,0 ); ncm->notify_state =NCM_NOTIFY_NONE ;break ;default :DBG (cdev,"event %02x --> %d\n" , event->bNotificationType, req->status); +atomic_dec (&ncm->notify_count);break ; } - ncm->notify_req = req;ncm_do_notify (ncm);spin_unlock (&ncm->lock); }
@@ -1612,6 +1616,11 @@ static void ncm_unbind(struct usb_config ncm_string_defs[0 ].id =0 ;usb_free_all_descriptors (f); +if (atomic_read (&ncm->notify_count)) { +usb_ep_dequeue (ncm->notify, ncm->notify_req); +atomic_set (&ncm->notify_count,0 ); + } +kfree (ncm->notify_req->buf);usb_ep_free_request (ncm->notify, ncm->notify_req); }
Greg Kroah-Hartman
maintainerPATCH 35/195 usb: gadget: f_ecm: Use atomic_t to track in-flight request
In reply to Greg Kroah-HartmanFrom: Bryan O'Donoghue <[email protected]>
commit d710562e01c48d59be3f60d58b7a85958b39aeda upstream.
Currently ecm->notify_req is used to flag when a request is in-flight. ecm->notify_req is set to NULL and when a request completes it is subsequently reset.
This is fundamentally buggy in that the unbind logic of the ECM driver will unconditionally free ecm->notify_req leading to a NULL pointer dereference.
--- drivers/usb/gadget/function/f_ecm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/usb/gadget/function/f_ecm.c +12 -4
@@ -52,6 +52,7 @@ struct f_ecm {struct usb_ep *notify;struct usb_request *notify_req;u8 notify_state; +atomic_t notify_count;bool is_open;/* FIXME is_open needs some irq-ish locking
@@ -380,7 +381,7 @@ static void ecm_do_notify(struct f_ecm *int status;/* notification already in flight? */ -if (!req) +if (atomic_read (&ecm->notify_count))return ; event = req->buf;
@@ -420,10 +421,10 @@ static void ecm_do_notify(struct f_ecm * event->bmRequestType =0xA1 ; event->wIndex =cpu_to_le16 (ecm->ctrl_id); - ecm->notify_req =NULL ; +atomic_inc (&ecm->notify_count); status =usb_ep_queue (ecm->notify, req,GFP_ATOMIC );if (status <0 ) { - ecm->notify_req = req; +atomic_dec (&ecm->notify_count);DBG (cdev,"notify --> %d\n" , status); } }
@@ -448,17 +449,19 @@ static void ecm_notify_complete(struct uswitch (req->status) {case 0 :/* no fault */ +atomic_dec (&ecm->notify_count);break ;case -ECONNRESET :case -ESHUTDOWN : +atomic_set (&ecm->notify_count,0 ); ecm->notify_state =ECM_NOTIFY_NONE ;break ;default :DBG (cdev,"event %02x --> %d\n" , event->bNotificationType, req->status); +atomic_dec (&ecm->notify_count);break ; } - ecm->notify_req = req;ecm_do_notify (ecm); }
@@ -907,6 +910,11 @@ static void ecm_unbind(struct usb_configusb_free_all_descriptors (f); +if (atomic_read (&ecm->notify_count)) { +usb_ep_dequeue (ecm->notify, ecm->notify_req); +atomic_set (&ecm->notify_count,0 ); + } +kfree (ecm->notify_req->buf);usb_ep_free_request (ecm->notify, ecm->notify_req); }
Greg Kroah-Hartman
maintainerPATCH 36/195 ALSA: usb-audio: Fix endianess in descriptor validation
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit f8e5f90b3a53bb75f05124ed19156388379a337d upstream.
I overlooked that some fields are words and need the converts from LE in the recently added USB descriptor validation code. This patch fixes those with the proper macro usages.
--- sound/usb/validate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
sound/usb/validate.c +3 -3
@@ -110,7 +110,7 @@ static bool validate_processing_unit(condefault :if (v->type ==UAC1_EXTENSION_UNIT )return true;/* OK */ -switch (d->wProcessType) { +switch (le16_to_cpu (d->wProcessType)) {case UAC_PROCESS_UP_DOWNMIX :case UAC_PROCESS_DOLBY_PROLOGIC :if (d->bLength < len +1 )/* bNrModes */
@@ -125,7 +125,7 @@ static bool validate_processing_unit(concase UAC_VERSION_2 :if (v->type ==UAC2_EXTENSION_UNIT_V2 )return true;/* OK */ -switch (d->wProcessType) { +switch (le16_to_cpu (d->wProcessType)) {case UAC2_PROCESS_UP_DOWNMIX :case UAC2_PROCESS_DOLBY_PROLOCIC :/* SiC! */ if (d->bLength < len +1 )/* bNrModes */
@@ -142,7 +142,7 @@ static bool validate_processing_unit(con len +=2 ;/* wClusterDescrID */ break ; } -switch (d->wProcessType) { +switch (le16_to_cpu (d->wProcessType)) {case UAC3_PROCESS_UP_DOWNMIX :if (d->bLength < len +1 )/* bNrModes */ return false;
Greg Kroah-Hartman
maintainerPATCH 37/195 ALSA: dummy: Fix PCM format loop in proc output
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 2acf25f13ebe8beb40e97a1bbe76f36277c64f1e upstream.
The loop termination for iterating over all formats should contain SNDRV_PCM_FORMAT_LAST, not less than it.
--- sound/drivers/dummy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/drivers/dummy.c +1 -1
@@ -929,7 +929,7 @@ static void print_formats(struct snd_dum {int i; -for (i =0 ; i <SNDRV_PCM_FORMAT_LAST ; i++) { +for (i =0 ; i <=SNDRV_PCM_FORMAT_LAST ; i++) {if (dummy->pcm_hw.formats & (1ULL << i))snd_iprintf (buffer," %s" ,snd_pcm_format_name (i)); }
Greg Kroah-Hartman
maintainerPATCH 38/195 mm/memory_hotplug: fix remove_memory() lockdep splat
In reply to Greg Kroah-HartmanFrom: Dan Williams <[email protected]>
commit f1037ec0cc8ac1a450974ad9754e991f72884f48 upstream.
The daxctl unit test for the dax_kmem driver currently triggers the (false positive) lockdep splat below. It results from the fact that remove_memory_block_devices() is invoked under the mem_hotplug_lock() causing lockdep entanglements with cpu_hotplug_lock() and sysfs (kernfs active state tracking). It is a false positive because the sysfs attribute path triggering the memory remove is not the same attribute path associated with memory-block device.
sysfs_break_active_protection() is not applicable since there is no real deadlock conflict, instead move memory-block device removal outside the lock. The mem_hotplug_lock() is not needed to synchronize the memory-block device removal vs the page online state, that is already handled by lock_device_hotplug(). Specifically, lock_device_hotplug() is sufficient to allow try_remove_memory() to check the offline state of the memblocks and be assured that any in progress online attempts are flushed / blocked by kernfs_drain() / attribute removal.
The add_memory() path safely creates memblock devices under the mem_hotplug_lock(). There is no kernfs active state synchronization in the memblock device_register() path, so nothing to fix there.
This change is only possible thanks to the recent change that refactored memory block device removal out of arch_remove_memory() (commit 4c4b7f9ba948 "mm/memory_hotplug: remove memory block devices before arch_remove_memory()"), and David's due diligence tracking down the guarantees afforded by kernfs_drain(). Not flagged for -stable since this only impacts ongoing development and lockdep validation, not a runtime issue.
======================================================
WARNING: possible circular locking dependency detected
5.5.0-rc3+ #230 Tainted: G OE
------------------------------------------------------
lt-daxctl/6459 is trying to acquire lock:
ffff99c7f0003510 (kn->count#241){++++}, at: kernfs_remove_by_name_ns+0x41/0x80
but task is already holding lock:
ffffffffa76a5450 (mem_hotplug_lock.rw_sem){++++}, at: percpu_down_write+0x20/0xe0
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (mem_hotplug_lock.rw_sem){++++}:
__lock_acquire+0x39c/0x790
lock_acquire+0xa2/0x1b0
get_online_mems+0x3e/0xb0
kmem_cache_create_usercopy+0x2e/0x260
kmem_cache_create+0x12/0x20
ptlock_cache_init+0x20/0x28
start_kernel+0x243/0x547
secondary_startup_64+0xb6/0xc0
-> #1 (cpu_hotplug_lock.rw_sem){++++}:
__lock_acquire+0x39c/0x790
lock_acquire+0xa2/0x1b0
cpus_read_lock+0x3e/0xb0
online_pages+0x37/0x300
memory_subsys_online+0x17d/0x1c0
device_online+0x60/0x80
state_store+0x65/0xd0
kernfs_fop_write+0xcf/0x1c0
vfs_write+0xdb/0x1d0
ksys_write+0x65/0xe0
do_syscall_64+0x5c/0xa0
entry_SYSCALL_64_after_hwframe+0x49/0xbe
-> #0 (kn->count#241){++++}:
check_prev_add+0x98/0xa40
validate_chain+0x576/0x860
__lock_acquire+0x39c/0x790
lock_acquire+0xa2/0x1b0
__kernfs_remove+0x25f/0x2e0
kernfs_remove_by_name_ns+0x41/0x80
remove_files.isra.0+0x30/0x70
sysfs_remove_group+0x3d/0x80
sysfs_remove_groups+0x29/0x40
device_remove_attrs+0x39/0x70
device_del+0x16a/0x3f0
device_unregister+0x16/0x60
remove_memory_block_devices+0x82/0xb0
try_remove_memory+0xb5/0x130
remove_memory+0x26/0x40
dev_dax_kmem_remove+0x44/0x6a [kmem]
device_release_driver_internal+0xe4/0x1c0
unbind_store+0xef/0x120
kernfs_fop_write+0xcf/0x1c0
vfs_write+0xdb/0x1d0
ksys_write+0x65/0xe0
do_syscall_64+0x5c/0xa0
entry_SYSCALL_64_after_hwframe+0x49/0xbe
other info that might help us debug this:
Chain exists of:
kn->count#241 --> cpu_hotplug_lock.rw_sem --> mem_hotplug_lock.rw_sem
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(mem_hotplug_lock.rw_sem);
lock(cpu_hotplug_lock.rw_sem);
lock(mem_hotplug_lock.rw_sem);
lock(kn->count#241);
*** DEADLOCK ***No fixes tag as this has been a long standing issue that predated the addition of kernfs lockdep annotations.
--- mm/memory_hotplug.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
mm/memory_hotplug.c +6 -3
@@ -1902,8 +1902,6 @@ void __ref __remove_memory(int nid, u64BUG_ON (check_hotplug_memory_range (start, size)); -mem_hotplug_begin (); -/* * All memory blocks must be offlined before removing memory. Check * whether all memory blocks in question are offline and trigger a BUG()
@@ -1919,9 +1917,14 @@ void __ref __remove_memory(int nid, u64memblock_free (start, size);memblock_remove (start, size); -/* remove memory block devices before removing memory */ +/* +* Memory block device removal under the device_hotplug_lock is +* a barrier against racing online attempts. +*/ remove_memory_block_devices (start, size); +mem_hotplug_begin (); +arch_remove_memory (nid, start, size,NULL );__release_memory_resource (start, size);
Greg Kroah-Hartman
maintainerPATCH 39/195 mm: move_pages: report the number of non-attempted pages
In reply to Greg Kroah-HartmanFrom: Yang Shi <[email protected]>
commit 5984fabb6e82d9ab4e6305cb99694c85d46de8ae upstream.
Since commit a49bd4d71637 ("mm, numa: rework do_pages_move"), the semantic of move_pages() has changed to return the number of non-migrated pages if they were result of a non-fatal reasons (usually a busy page).
This was an unintentional change that hasn't been noticed except for LTP tests which checked for the documented behavior.
There are two ways to go around this change. We can even get back to the original behavior and return -EAGAIN whenever migrate_pages is not able to migrate pages due to non-fatal reasons. Another option would be to simply continue with the changed semantic and extend move_pages documentation to clarify that -errno is returned on an invalid input or when migration simply cannot succeed (e.g. -ENOMEM, -EBUSY) or the number of pages that couldn't have been migrated due to ephemeral reasons (e.g. page is pinned or locked for other reasons).
This patch implements the second option because this behavior is in place for some time without anybody complaining and possibly new users depending on it. Also it allows to have a slightly easier error handling as the caller knows that it is worth to retry when err > 0.
But since the new semantic would be aborted immediately if migration is failed due to ephemeral reasons, need include the number of non-attempted pages in the return value too.
--- mm/migrate.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
mm/migrate.c +23 -2
@@ -1623,8 +1623,19 @@ static int do_pages_move(struct mm_struc start = i; }else if (node != current_node) { err =do_move_pages_to_node (mm, &pagelist, current_node); -if (err) +if (err) { +/* +* Positive err means the number of failed +* pages to migrate. Since we are going to +* abort and return the number of non-migrated +* pages, so need to incude the rest of the +* nr_pages that have not been attempted as +* well. +*/ +if (err >0 ) + err += nr_pages - i -1 ; goto out; + } err =store_status (status, start, current_node, i - start);if (err) goto out;
@@ -1655,8 +1666,11 @@ static int do_pages_move(struct mm_struc goto out_flush; err =do_move_pages_to_node (mm, &pagelist, current_node); -if (err) +if (err) { +if (err >0 ) + err += nr_pages - i -1 ; goto out; + }if (i > start) { err =store_status (status, start, current_node, i - start);if (err)
@@ -1670,6 +1684,13 @@ out_flush:/* Make sure we do not overwrite the existing error */ err1 =do_move_pages_to_node (mm, &pagelist, current_node); +/* +* Don't have to report non-attempted pages here since: +* - If the above loop is done gracefully all pages have been +* attempted. +* - If the above loop is aborted it means a fatal error +* happened, should return ret. +*/ if (!err1) err1 =store_status (status, start, current_node, i - start);if (err >=0 )
Greg Kroah-Hartman
maintainerPATCH 40/195 media/v4l2-core: set pages dirty upon releasing DMA buffers
In reply to Greg Kroah-HartmanFrom: John Hubbard <[email protected]>
commit 3c7470b6f68434acae459482ab920d1e3fabd1c7 upstream.
After DMA is complete, and the device and CPU caches are synchronized, it's still required to mark the CPU pages as dirty, if the data was coming from the device. However, this driver was just issuing a bare put_page() call, without any set_page_dirty*() call.
Fix the problem, by calling set_page_dirty_lock() if the CPU pages were potentially receiving data from the device.
--- drivers/media/v4l2-core/videobuf-dma-sg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/media/v4l2-core/videobuf-dma-sg.c +4 -1
@@ -352,8 +352,11 @@ int videobuf_dma_free(struct videobuf_dmBUG_ON (dma->sglen);if (dma->pages) { -for (i =0 ; i < dma->nr_pages; i++) +for (i =0 ; i < dma->nr_pages; i++) { +if (dma->direction ==DMA_FROM_DEVICE ) +set_page_dirty_lock (dma->pages[i]);put_page (dma->pages[i]); + }kfree (dma->pages); dma->pages =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 41/195 media: v4l2-core: compat: ignore native command codes
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
commit 4a873f3fa5d6ca52e446d306dd7194dd86a09422 upstream.
The do_video_ioctl() compat handler converts the compat command codes into the native ones before processing further, but this causes problems for 32-bit user applications that pass a command code that matches a 64-bit native number, which will then be handled the same way.
Specifically, this breaks VIDIOC_DQEVENT_TIME from user space applications with 64-bit time_t, as the structure layout is the same as the native 64-bit layout on many architectures (x86 being the notable exception).
Change the handler to use the converted command code only for passing into the native ioctl handler, not for deciding on the conversion, in order to make the compat behavior match the native behavior.
Actual support for the 64-bit time_t version of VIDIOC_DQEVENT_TIME and other commands still needs to be added in a separate patch.
--- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 148 +++++++++++++------------- 1 file changed, 75 insertions(+), 73 deletions(-)
drivers/media/v4l2-core/v4l2-compat-ioctl32.c +75 -73
@@ -1171,36 +1171,38 @@ static long do_video_ioctl(struct file *u32 aux_space;int compatible_arg =1 ;long err =0 ; +unsigned int ncmd;/* * 1. When struct size is different, converts the command. */ switch (cmd) { -case VIDIOC_G_FMT32 : cmd =VIDIOC_G_FMT ;break ; -case VIDIOC_S_FMT32 : cmd =VIDIOC_S_FMT ;break ; -case VIDIOC_QUERYBUF32 : cmd =VIDIOC_QUERYBUF ;break ; -case VIDIOC_G_FBUF32 : cmd =VIDIOC_G_FBUF ;break ; -case VIDIOC_S_FBUF32 : cmd =VIDIOC_S_FBUF ;break ; -case VIDIOC_QBUF32 : cmd =VIDIOC_QBUF ;break ; -case VIDIOC_DQBUF32 : cmd =VIDIOC_DQBUF ;break ; -case VIDIOC_ENUMSTD32 : cmd =VIDIOC_ENUMSTD ;break ; -case VIDIOC_ENUMINPUT32 : cmd =VIDIOC_ENUMINPUT ;break ; -case VIDIOC_TRY_FMT32 : cmd =VIDIOC_TRY_FMT ;break ; -case VIDIOC_G_EXT_CTRLS32 : cmd =VIDIOC_G_EXT_CTRLS ;break ; -case VIDIOC_S_EXT_CTRLS32 : cmd =VIDIOC_S_EXT_CTRLS ;break ; -case VIDIOC_TRY_EXT_CTRLS32 : cmd =VIDIOC_TRY_EXT_CTRLS ;break ; -case VIDIOC_DQEVENT32 : cmd =VIDIOC_DQEVENT ;break ; -case VIDIOC_OVERLAY32 : cmd =VIDIOC_OVERLAY ;break ; -case VIDIOC_STREAMON32 : cmd =VIDIOC_STREAMON ;break ; -case VIDIOC_STREAMOFF32 : cmd =VIDIOC_STREAMOFF ;break ; -case VIDIOC_G_INPUT32 : cmd =VIDIOC_G_INPUT ;break ; -case VIDIOC_S_INPUT32 : cmd =VIDIOC_S_INPUT ;break ; -case VIDIOC_G_OUTPUT32 : cmd =VIDIOC_G_OUTPUT ;break ; -case VIDIOC_S_OUTPUT32 : cmd =VIDIOC_S_OUTPUT ;break ; -case VIDIOC_CREATE_BUFS32 : cmd =VIDIOC_CREATE_BUFS ;break ; -case VIDIOC_PREPARE_BUF32 : cmd =VIDIOC_PREPARE_BUF ;break ; -case VIDIOC_G_EDID32 : cmd =VIDIOC_G_EDID ;break ; -case VIDIOC_S_EDID32 : cmd =VIDIOC_S_EDID ;break ; +case VIDIOC_G_FMT32 : ncmd =VIDIOC_G_FMT ;break ; +case VIDIOC_S_FMT32 : ncmd =VIDIOC_S_FMT ;break ; +case VIDIOC_QUERYBUF32 : ncmd =VIDIOC_QUERYBUF ;break ; +case VIDIOC_G_FBUF32 : ncmd =VIDIOC_G_FBUF ;break ; +case VIDIOC_S_FBUF32 : ncmd =VIDIOC_S_FBUF ;break ; +case VIDIOC_QBUF32 : ncmd =VIDIOC_QBUF ;break ; +case VIDIOC_DQBUF32 : ncmd =VIDIOC_DQBUF ;break ; +case VIDIOC_ENUMSTD32 : ncmd =VIDIOC_ENUMSTD ;break ; +case VIDIOC_ENUMINPUT32 : ncmd =VIDIOC_ENUMINPUT ;break ; +case VIDIOC_TRY_FMT32 : ncmd =VIDIOC_TRY_FMT ;break ; +case VIDIOC_G_EXT_CTRLS32 : ncmd =VIDIOC_G_EXT_CTRLS ;break ; +case VIDIOC_S_EXT_CTRLS32 : ncmd =VIDIOC_S_EXT_CTRLS ;break ; +case VIDIOC_TRY_EXT_CTRLS32 : ncmd =VIDIOC_TRY_EXT_CTRLS ;break ; +case VIDIOC_DQEVENT32 : ncmd =VIDIOC_DQEVENT ;break ; +case VIDIOC_OVERLAY32 : ncmd =VIDIOC_OVERLAY ;break ; +case VIDIOC_STREAMON32 : ncmd =VIDIOC_STREAMON ;break ; +case VIDIOC_STREAMOFF32 : ncmd =VIDIOC_STREAMOFF ;break ; +case VIDIOC_G_INPUT32 : ncmd =VIDIOC_G_INPUT ;break ; +case VIDIOC_S_INPUT32 : ncmd =VIDIOC_S_INPUT ;break ; +case VIDIOC_G_OUTPUT32 : ncmd =VIDIOC_G_OUTPUT ;break ; +case VIDIOC_S_OUTPUT32 : ncmd =VIDIOC_S_OUTPUT ;break ; +case VIDIOC_CREATE_BUFS32 : ncmd =VIDIOC_CREATE_BUFS ;break ; +case VIDIOC_PREPARE_BUF32 : ncmd =VIDIOC_PREPARE_BUF ;break ; +case VIDIOC_G_EDID32 : ncmd =VIDIOC_G_EDID ;break ; +case VIDIOC_S_EDID32 : ncmd =VIDIOC_S_EDID ;break ; +default : ncmd = cmd;break ; }/*
@@ -1209,11 +1211,11 @@ static long do_video_ioctl(struct file ** argument into it. */ switch (cmd) { -case VIDIOC_OVERLAY : -case VIDIOC_STREAMON : -case VIDIOC_STREAMOFF : -case VIDIOC_S_INPUT : -case VIDIOC_S_OUTPUT : +case VIDIOC_OVERLAY32 : +case VIDIOC_STREAMON32 : +case VIDIOC_STREAMOFF32 : +case VIDIOC_S_INPUT32 : +case VIDIOC_S_OUTPUT32 : err =alloc_userspace (sizeof (unsigned int ),0 , &new_p64);if (!err &&assign_in_user ((unsigned int __user *)new_p64, (compat_uint_t __user *)p32))
@@ -1221,23 +1223,23 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_G_INPUT : -case VIDIOC_G_OUTPUT : +case VIDIOC_G_INPUT32 : +case VIDIOC_G_OUTPUT32 : err =alloc_userspace (sizeof (unsigned int ),0 , &new_p64); compatible_arg =0 ;break ; -case VIDIOC_G_EDID : -case VIDIOC_S_EDID : +case VIDIOC_G_EDID32 : +case VIDIOC_S_EDID32 : err =alloc_userspace (sizeof (struct v4l2_edid ),0 , &new_p64);if (!err) err =get_v4l2_edid32 (new_p64, p32); compatible_arg =0 ;break ; -case VIDIOC_G_FMT : -case VIDIOC_S_FMT : -case VIDIOC_TRY_FMT : +case VIDIOC_G_FMT32 : +case VIDIOC_S_FMT32 : +case VIDIOC_TRY_FMT32 : err =bufsize_v4l2_format (p32, &aux_space);if (!err) err = alloc_userspace(sizeof(struct v4l2_format),
@@ -1250,7 +1252,7 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_CREATE_BUFS : +case VIDIOC_CREATE_BUFS32 : err =bufsize_v4l2_create (p32, &aux_space);if (!err) err = alloc_userspace(sizeof(struct v4l2_create_buffers),
@@ -1263,10 +1265,10 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_PREPARE_BUF : -case VIDIOC_QUERYBUF : -case VIDIOC_QBUF : -case VIDIOC_DQBUF : +case VIDIOC_PREPARE_BUF32 : +case VIDIOC_QUERYBUF32 : +case VIDIOC_QBUF32 : +case VIDIOC_DQBUF32 : err =bufsize_v4l2_buffer (p32, &aux_space);if (!err) err = alloc_userspace(sizeof(struct v4l2_buffer),
@@ -1279,7 +1281,7 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_S_FBUF : +case VIDIOC_S_FBUF32 : err =alloc_userspace (sizeof (struct v4l2_framebuffer ),0 , &new_p64);if (!err)
@@ -1287,13 +1289,13 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_G_FBUF : +case VIDIOC_G_FBUF32 : err =alloc_userspace (sizeof (struct v4l2_framebuffer ),0 , &new_p64); compatible_arg =0 ;break ; -case VIDIOC_ENUMSTD : +case VIDIOC_ENUMSTD32 : err =alloc_userspace (sizeof (struct v4l2_standard ),0 , &new_p64);if (!err)
@@ -1301,16 +1303,16 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_ENUMINPUT : +case VIDIOC_ENUMINPUT32 : err =alloc_userspace (sizeof (struct v4l2_input ),0 , &new_p64);if (!err) err =get_v4l2_input32 (new_p64, p32); compatible_arg =0 ;break ; -case VIDIOC_G_EXT_CTRLS : -case VIDIOC_S_EXT_CTRLS : -case VIDIOC_TRY_EXT_CTRLS : +case VIDIOC_G_EXT_CTRLS32 : +case VIDIOC_S_EXT_CTRLS32 : +case VIDIOC_TRY_EXT_CTRLS32 : err =bufsize_v4l2_ext_controls (p32, &aux_space);if (!err) err = alloc_userspace(sizeof(struct v4l2_ext_controls),
@@ -1322,7 +1324,7 @@ static long do_video_ioctl(struct file * } compatible_arg =0 ;break ; -case VIDIOC_DQEVENT : +case VIDIOC_DQEVENT32 : err =alloc_userspace (sizeof (struct v4l2_event ),0 , &new_p64); compatible_arg =0 ;break ;
@@ -1340,9 +1342,9 @@ static long do_video_ioctl(struct file ** Otherwise, it will pass the newly allocated @new_p64 argument. */ if (compatible_arg) - err =native_ioctl (file, cmd, (unsigned long )p32); + err =native_ioctl (file, ncmd, (unsigned long )p32);else - err =native_ioctl (file, cmd, (unsigned long )new_p64); + err =native_ioctl (file, ncmd, (unsigned long )new_p64);if (err == -ENOTTY )return err;
@@ -1358,13 +1360,13 @@ static long do_video_ioctl(struct file ** the blocks to maximum allowed value. */ switch (cmd) { -case VIDIOC_G_EXT_CTRLS : -case VIDIOC_S_EXT_CTRLS : -case VIDIOC_TRY_EXT_CTRLS : +case VIDIOC_G_EXT_CTRLS32 : +case VIDIOC_S_EXT_CTRLS32 : +case VIDIOC_TRY_EXT_CTRLS32 :if (put_v4l2_ext_controls32 (file, new_p64, p32)) err = -EFAULT ;break ; -case VIDIOC_S_EDID : +case VIDIOC_S_EDID32 :if (put_v4l2_edid32 (new_p64, p32)) err = -EFAULT ;break ;
@@ -1377,49 +1379,49 @@ static long do_video_ioctl(struct file ** the original 32 bits structure. */ switch (cmd) { -case VIDIOC_S_INPUT : -case VIDIOC_S_OUTPUT : -case VIDIOC_G_INPUT : -case VIDIOC_G_OUTPUT : +case VIDIOC_S_INPUT32 : +case VIDIOC_S_OUTPUT32 : +case VIDIOC_G_INPUT32 : +case VIDIOC_G_OUTPUT32 :if (assign_in_user ((compat_uint_t __user *)p32, ((unsigned int __user *)new_p64))) err = -EFAULT ;break ; -case VIDIOC_G_FBUF : +case VIDIOC_G_FBUF32 : err =put_v4l2_framebuffer32 (new_p64, p32);break ; -case VIDIOC_DQEVENT : +case VIDIOC_DQEVENT32 : err =put_v4l2_event32 (new_p64, p32);break ; -case VIDIOC_G_EDID : +case VIDIOC_G_EDID32 : err =put_v4l2_edid32 (new_p64, p32);break ; -case VIDIOC_G_FMT : -case VIDIOC_S_FMT : -case VIDIOC_TRY_FMT : +case VIDIOC_G_FMT32 : +case VIDIOC_S_FMT32 : +case VIDIOC_TRY_FMT32 : err =put_v4l2_format32 (new_p64, p32);break ; -case VIDIOC_CREATE_BUFS : +case VIDIOC_CREATE_BUFS32 : err =put_v4l2_create32 (new_p64, p32);break ; -case VIDIOC_PREPARE_BUF : -case VIDIOC_QUERYBUF : -case VIDIOC_QBUF : -case VIDIOC_DQBUF : +case VIDIOC_PREPARE_BUF32 : +case VIDIOC_QUERYBUF32 : +case VIDIOC_QBUF32 : +case VIDIOC_DQBUF32 : err =put_v4l2_buffer32 (new_p64, p32);break ; -case VIDIOC_ENUMSTD : +case VIDIOC_ENUMSTD32 : err =put_v4l2_standard32 (new_p64, p32);break ; -case VIDIOC_ENUMINPUT : +case VIDIOC_ENUMINPUT32 : err =put_v4l2_input32 (new_p64, p32);break ; }
Greg Kroah-Hartman
maintainerPATCH 42/195 media: v4l2-rect.h: fix v4l2_rect_map_inside() top/left adjustments
In reply to Greg Kroah-HartmanFrom: Helen Koike <[email protected]>
commit f51e50db4c20d46930b33be3f208851265694f3e upstream.
boundary->width and boundary->height are sizes relative to boundary->left and boundary->top coordinates, but they were not being taken into consideration to adjust r->left and r->top, leading to the following error:
Consider the follow as initial values for boundary and r:
struct v4l2_rect boundary = {
.left = 100,
.top = 100,
.width = 800,
.height = 600,
}struct v4l2_rect r = {
.left = 0,
.top = 0,
.width = 1920,
.height = 960,
}calling v4l2_rect_map_inside(&r, &boundary) was modifying r to:
r = {
.left = 0,
.top = 0,
.width = 800,
.height = 600,
}Which is wrongly outside the boundary rectangle, because:
v4l2_rect_set_max_size(r, boundary); // r->width = 800, r->height = 600 ... if (r->left + r->width > boundary->width) // true r->left = boundary->width - r->width; // r->left = 800 - 800 if (r->top + r->height > boundary->height) // true r->top = boundary->height - r->height; // r->height = 600 - 600
Fix this by considering top/left coordinates from boundary.
--- include/media/v4l2-rect.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
include/media/v4l2-rect.h +4 -4
@@ -63,10 +63,10 @@ static inline void v4l2_rect_map_inside( r->left = boundary->left;if (r->top < boundary->top) r->top = boundary->top; -if (r->left + r->width > boundary->width) - r->left = boundary->width - r->width; -if (r->top + r->height > boundary->height) - r->top = boundary->height - r->height; +if (r->left + r->width > boundary->left + boundary->width) + r->left = boundary->left + boundary->width - r->width; +if (r->top + r->height > boundary->top + boundary->height) + r->top = boundary->top + boundary->height - r->height; }/**
Greg Kroah-Hartman
maintainerPATCH 43/195 lib/test_kasan.c: fix memory leak in kmalloc_oob_krealloc_more()
In reply to Greg Kroah-HartmanFrom: Gustavo A. R. Silva <[email protected]>
commit 3e21d9a501bf99aee2e5835d7f34d8c823f115b5 upstream.
In case memory resources for _ptr2_ were allocated, release them before return.
Notice that in case _ptr1_ happens to be NULL, krealloc() behaves exactly like kmalloc().
Addresses-Coverity-ID: 1490594 ("Resource leak")
--- lib/test_kasan.c | 1 + 1 file changed, 1 insertion(+)
lib/test_kasan.c +1 -0
@@ -157,6 +157,7 @@ static noinline void __init kmalloc_oob_if (!ptr1 || !ptr2) {pr_err ("Allocation failed\n" );kfree (ptr1); +kfree (ptr2);return ; }
Greg Kroah-Hartman
maintainerPATCH 44/195 irqdomain: Fix a memory leak in irq_domain_push_irq()
In reply to Greg Kroah-HartmanFrom: Kevin Hao <[email protected]>
commit 0f394daef89b38d58c91118a2b08b8a1b316703b upstream.
Fix a memory leak reported by kmemleak:
unreferenced object 0xffff000bc6f50e80 (size 128):
comm "kworker/23:2", pid 201, jiffies 4294894947 (age 942.132s) hex dump (first 32 bytes):
00 00 00 00 41 00 00 00 86 c0 03 00 00 00 00 00 ....A...........
00 a0 b2 c6 0b 00 ff ff 40 51 fd 10 00 80 ff ff ........@Q......
backtrace:
[<00000000e62d2240>] kmem_cache_alloc_trace+0x1a4/0x320
[<00000000279143c9>] irq_domain_push_irq+0x7c/0x188
[<00000000d9f4c154>] thunderx_gpio_probe+0x3ac/0x438
[<00000000fd09ec22>] pci_device_probe+0xe4/0x198
[<00000000d43eca75>] really_probe+0xdc/0x320
[<00000000d3ebab09>] driver_probe_device+0x5c/0xf0
[<000000005b3ecaa0>] __device_attach_driver+0x88/0xc0
[<000000004e5915f5>] bus_for_each_drv+0x7c/0xc8
[<0000000079d4db41>] __device_attach+0xe4/0x140
[<00000000883bbda9>] device_initial_probe+0x18/0x20
[<000000003be59ef6>] bus_probe_device+0x98/0xa0
[<0000000039b03d3f>] deferred_probe_work_func+0x74/0xa8
[<00000000870934ce>] process_one_work+0x1c8/0x470
[<00000000e3cce570>] worker_thread+0x1f8/0x428
[<000000005d64975e>] kthread+0xfc/0x128
[<00000000f0eaa764>] ret_from_fork+0x10/0x18--- kernel/irq/irqdomain.c | 1 + 1 file changed, 1 insertion(+)
kernel/irq/irqdomain.c +1 -0
@@ -1421,6 +1421,7 @@ int irq_domain_push_irq(struct irq_domaiif (rv) {/* Restore the original irq_data. */ *root_irq_data = *child_irq_data; +kfree (child_irq_data); goto error; }
Greg Kroah-Hartman
maintainerPATCH 45/195 platform/x86: intel_scu_ipc: Fix interrupt support
In reply to Greg Kroah-HartmanFrom: Mika Westerberg <[email protected]>
commit e48b72a568bbd641c91dad354138d3c17d03ee6f upstream.
Currently the driver has disabled interrupt support for Tangier but actually interrupt works just fine if the command is not written twice in a row. Also we need to ack the interrupt in the handler.
--- drivers/platform/x86/intel_scu_ipc.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-)
drivers/platform/x86/intel_scu_ipc.c +8 -13
@@ -69,26 +69,22 @@struct intel_scu_ipc_pdata_t {u32 i2c_base;u32 i2c_len; -u8 irq_mode; };static const struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = { .i2c_base =0xff12b000 , .i2c_len =0x10 , - .irq_mode =0 , };/* Penwell and Cloverview */ static const struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = { .i2c_base =0xff12b000 , .i2c_len =0x10 , - .irq_mode =1 , };static const struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = { .i2c_base =0xff00d000 , .i2c_len =0x10 , - .irq_mode =0 , };struct intel_scu_ipc_dev {
@@ -101,6 +97,9 @@ struct intel_scu_ipc_dev {static struct intel_scu_ipc_dev ipcdev;/* Only one for now */ +#define IPC_STATUS 0x04 +#define IPC_STATUS_IRQ BIT(2) +/* * IPC Read Buffer (Read Only): * 16 byte buffer for receiving data from SCU, if IPC command
@@ -122,11 +121,8 @@ static DEFINE_MUTEX(ipclock); /* lock us*/ static inline void ipc_command (struct intel_scu_ipc_dev *scu,u32 cmd) { -if (scu->irq_mode) { -reinit_completion (&scu->cmd_complete); -writel (cmd |IPC_IOC , scu->ipc_base); - } -writel (cmd, scu->ipc_base); +reinit_completion (&scu->cmd_complete); +writel (cmd |IPC_IOC , scu->ipc_base); }/*
@@ -612,9 +608,10 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);static irqreturn_t ioc (int irq,void *dev_id) {struct intel_scu_ipc_dev *scu = dev_id; +int status =ipc_read_status (scu); -if (scu->irq_mode) -complete (&scu->cmd_complete); +writel (status |IPC_STATUS_IRQ , scu->ipc_base +IPC_STATUS ); +complete (&scu->cmd_complete);return IRQ_HANDLED ; }
@@ -640,8 +637,6 @@ static int ipc_probe(struct pci_dev *pdeif (!pdata)return -ENODEV ; - scu->irq_mode = pdata->irq_mode; - err =pcim_enable_device (pdev);if (err)return err;
Greg Kroah-Hartman
maintainerPATCH 46/195 ALSA: hda: Add Clevo W65_67SB the power_save blacklist
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit d8feb6080bb0c9f4d799a423d9453048fdd06990 upstream.
Using HDA power-saving on the Clevo W65_67SB causes the first 0.5 seconds of audio to be missing every time audio starts playing.
This commit adds the Clevo W65_67SB the power_save blacklist to avoid this issue.
--- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+)
sound/pci/hda/hda_intel.c +2 -0
@@ -2324,6 +2324,8 @@ static struct snd_pci_quirk power_save_b/* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */ SND_PCI_QUIRK (0x1558 ,0x3501 ,"Clevo W35xSS_370SS" ,0 ),/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ +SND_PCI_QUIRK (0x1558 ,0x6504 ,"Clevo W65_67SB" ,0 ), +/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0),/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
Greg Kroah-Hartman
maintainerPATCH 47/195 KVM: arm64: Correct PSTATE on exception entry
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit a425372e733177eb0779748956bc16c85167af48 upstream.
When KVM injects an exception into a guest, it generates the PSTATE value from scratch, configuring PSTATE.{M[4:0],DAIF}, and setting all other bits to zero.
This isn't correct, as the architecture specifies that some PSTATE bits are (conditionally) cleared or set upon an exception, and others are unchanged from the original context.
This patch adds logic to match the architectural behaviour. To make this simple to follow/audit/extend, documentation references are provided, and bits are configured in order of their layout in SPSR_EL2. This layout can be seen in the diagram on ARM DDI 0487E.a page C5-429.
--- arch/arm64/include/uapi/asm/ptrace.h | 1 arch/arm64/kvm/inject_fault.c | 70 ++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 5 deletions(-)
arch/arm64/include/uapi/asm/ptrace.h +1 -0
@@ -49,6 +49,7 @@#define PSR_SSBS_BIT 0x00001000#define PSR_PAN_BIT 0x00400000#define PSR_UAO_BIT 0x00800000 +#define PSR_DIT_BIT 0x01000000#define PSR_V_BIT 0x10000000#define PSR_C_BIT 0x20000000#define PSR_Z_BIT 0x40000000
arch/arm64/kvm/inject_fault.c +65 -5
94 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 48/195 KVM: arm/arm64: Correct CPSR on exception entry
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit 3c2483f15499b877ccb53250d88addb8c91da147 upstream.
When KVM injects an exception into a guest, it generates the CPSR value from scratch, configuring CPSR.{M,A,I,T,E}, and setting all other bits to zero.
This isn't correct, as the architecture specifies that some CPSR bits are (conditionally) cleared or set upon an exception, and others are unchanged from the original context.
This patch adds logic to match the architectural behaviour. To make this simple to follow/audit/extend, documentation references are provided, and bits are configured in order of their layout in SPSR_EL2. This layout can be seen in the diagram on ARM DDI 0487E.a page C5-426.
Note that this code is used by both arm and arm64, and is intended to fuction with the SPSR_EL2 and SPSR_HYP layouts.
--- arch/arm/include/asm/kvm_emulate.h | 12 ++++ arch/arm64/include/asm/ptrace.h | 1 virt/kvm/arm/aarch32.c | 111 +++++++++++++++++++++++++++++++++---- 3 files changed, 114 insertions(+), 10 deletions(-)
arch/arm/include/asm/kvm_emulate.h +12 -0
@@ -26,13 +26,25 @@#include <asm/cputype.h> /* arm64 compatibility macros */ +#define PSR_AA32_MODE_FIQ FIQ_MODE +#define PSR_AA32_MODE_SVC SVC_MODE#define PSR_AA32_MODE_ABT ABT_MODE#define PSR_AA32_MODE_UND UND_MODE#define PSR_AA32_T_BIT PSR_T_BIT +#define PSR_AA32_F_BIT PSR_F_BIT#define PSR_AA32_I_BIT PSR_I_BIT#define PSR_AA32_A_BIT PSR_A_BIT#define PSR_AA32_E_BIT PSR_E_BIT#define PSR_AA32_IT_MASK PSR_IT_MASK +#define PSR_AA32_GE_MASK 0x000f0000 +#define PSR_AA32_DIT_BIT 0x00200000 +#define PSR_AA32_PAN_BIT 0x00400000 +#define PSR_AA32_SSBS_BIT 0x00800000 +#define PSR_AA32_Q_BIT PSR_Q_BIT +#define PSR_AA32_V_BIT PSR_V_BIT +#define PSR_AA32_C_BIT PSR_C_BIT +#define PSR_AA32_Z_BIT PSR_Z_BIT +#define PSR_AA32_N_BIT PSR_N_BITunsigned long *vcpu_reg (struct kvm_vcpu *vcpu,u8 reg_num);
arch/arm64/include/asm/ptrace.h +1 -0
@@ -50,6 +50,7 @@#define PSR_AA32_I_BIT 0x00000080#define PSR_AA32_A_BIT 0x00000100#define PSR_AA32_E_BIT 0x00000200 +#define PSR_AA32_PAN_BIT 0x00400000#define PSR_AA32_SSBS_BIT 0x00800000#define PSR_AA32_DIT_BIT 0x01000000#define PSR_AA32_Q_BIT 0x08000000
virt/kvm/arm/aarch32.c +101 -10
136 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 49/195 KVM: arm/arm64: Correct AArch32 SPSR on exception entry
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit 1cfbb484de158e378e8971ac40f3082e53ecca55 upstream.
Confusingly, there are three SPSR layouts that a kernel may need to deal with:
(1) An AArch64 SPSR_ELx view of an AArch64 pstate
(2) An AArch64 SPSR_ELx view of an AArch32 pstate
(3) An AArch32 SPSR_* view of an AArch32 pstate
When the KVM AArch32 support code deals with SPSR_{EL2,HYP}, it's either dealing with #2 or #3 consistently. On arm64 the PSR_AA32_* definitions match the AArch64 SPSR_ELx view, and on arm the PSR_AA32_* definitions match the AArch32 SPSR_* view.
However, when we inject an exception into an AArch32 guest, we have to synthesize the AArch32 SPSR_* that the guest will see. Thus, an AArch64 host needs to synthesize layout #3 from layout #2.
This patch adds a new host_spsr_to_spsr32() helper for this, and makes use of it in the KVM AArch32 support code. For arm64 we need to shuffle the DIT bit around, and remove the SS bit, while for arm we can use the value as-is.
I've open-coded the bit manipulation for now to avoid having to rework the existing PSR_* definitions into PSR64_AA32_* and PSR32_AA32_* definitions. I hope to perform a more thorough refactoring in future so that we can handle pstate view manipulation more consistently across the kernel tree.
--- arch/arm/include/asm/kvm_emulate.h | 5 +++++ arch/arm64/include/asm/kvm_emulate.h | 32 ++++++++++++++++++++++++++++++++ virt/kvm/arm/aarch32.c | 6 +++--- 3 files changed, 40 insertions(+), 3 deletions(-)
arch/arm/include/asm/kvm_emulate.h +5 -0
@@ -65,6 +65,11 @@ static inline void vcpu_write_spsr(struc *__vcpu_spsr (vcpu) = v; } +static inline unsigned long host_spsr_to_spsr32 (unsigned long spsr) +{ +return spsr; +} +static inline unsigned long vcpu_get_reg (struct kvm_vcpu *vcpu,u8 reg_num) {
arch/arm64/include/asm/kvm_emulate.h +32 -0
@@ -202,6 +202,38 @@ static inline void vcpu_write_spsr(strucvcpu_gp_regs (vcpu)->spsr[KVM_SPSR_EL1 ] = v; } +/* +* The layout of SPSR for an AArch32 state is different when observed from an +* AArch64 SPSR_ELx or an AArch32 SPSR_*. This function generates the AArch32 +* view given an AArch64 view. +* +* In ARM DDI 0487E.a see: +* +* - The AArch64 view (SPSR_EL2) in section C5.2.18, page C5-426 +* - The AArch32 view (SPSR_abt) in section G8.2.126, page G8-6256 +* - The AArch32 view (SPSR_und) in section G8.2.132, page G8-6280 +* +* Which show the following differences: +* +* | Bit | AA64 | AA32 | Notes | +* +-----+------+------+-----------------------------| +* | 24 | DIT | J | J is RES0 in ARMv8 | +* | 21 | SS | DIT | SS doesn't exist in AArch32 | +* +* ... and all other bits are (currently) common. +*/ +static inline unsigned long host_spsr_to_spsr32 (unsigned long spsr) +{ +const unsigned long overlap =BIT (24 ) |BIT (21 ); +unsigned long dit = !!(spsr &PSR_AA32_DIT_BIT ); + + spsr &= ~overlap; + + spsr |= dit <<21 ; + +return spsr; +} +static inline bool vcpu_mode_priv (const struct kvm_vcpu *vcpu) {u32 mode;
virt/kvm/arm/aarch32.c +3 -3
@@ -140,15 +140,15 @@ static unsigned long get_except32_cpsr(sstatic void prepare_fault32 (struct kvm_vcpu *vcpu,u32 mode,u32 vect_offset) { -unsigned long new_spsr_value = *vcpu_cpsr (vcpu); -bool is_thumb = (new_spsr_value &PSR_AA32_T_BIT ); +unsigned long spsr = *vcpu_cpsr (vcpu); +bool is_thumb = (spsr &PSR_AA32_T_BIT );u32 return_offset = return_offsets[vect_offset >>2 ][is_thumb];u32 sctlr =vcpu_cp15 (vcpu, c1_SCTLR); *vcpu_cpsr (vcpu) =get_except32_cpsr (vcpu, mode);/* Note: These now point to the banked copies */ -vcpu_write_spsr (vcpu, new_spsr_value); +vcpu_write_spsr (vcpu,host_spsr_to_spsr32 (spsr)); *vcpu_reg32 (vcpu,14 ) = *vcpu_pc (vcpu) + return_offset;/* Branch to exception vector */
Greg Kroah-Hartman
maintainerPATCH 50/195 KVM: arm64: Only sign-extend MMIO up to register width
In reply to Greg Kroah-HartmanFrom: Christoffer Dall <[email protected]>
commit b6ae256afd32f96bec0117175b329d0dd617655e upstream.
On AArch64 you can do a sign-extended load to either a 32-bit or 64-bit register, and we should only sign extend the register up to the width of the register as specified in the operation (by using the 32-bit Wn or 64-bit Xn register specifier).
As it turns out, the architecture provides this decoding information in the SF ("Sixty-Four" -- how cute...) bit.
Let's take advantage of this with the usual 32-bit/64-bit header file dance and do the right thing on AArch64 hosts.
--- arch/arm/include/asm/kvm_emulate.h | 5 +++++ arch/arm/include/asm/kvm_mmio.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 5 +++++ arch/arm64/include/asm/kvm_mmio.h | 6 ++---- virt/kvm/arm/mmio.c | 6 ++++++ 5 files changed, 20 insertions(+), 4 deletions(-)
arch/arm/include/asm/kvm_emulate.h +5 -0
@@ -206,6 +206,11 @@ static inline bool kvm_vcpu_dabt_issext(return kvm_vcpu_get_hsr (vcpu) &HSR_SSE ; } +static inline bool kvm_vcpu_dabt_issf (const struct kvm_vcpu *vcpu) +{ +return false; +} +static inline int kvm_vcpu_dabt_get_rd (struct kvm_vcpu *vcpu) {return (kvm_vcpu_get_hsr (vcpu) &HSR_SRT_MASK ) >>HSR_SRT_SHIFT ;
arch/arm/include/asm/kvm_mmio.h +2 -0
@@ -26,6 +26,8 @@struct kvm_decode {unsigned long rt;bool sign_extend; +/* Not used on 32-bit arm */ +bool sixty_four; };void kvm_mmio_write_buf (void *buf,unsigned int len,unsigned long data);
arch/arm64/include/asm/kvm_emulate.h +5 -0
@@ -293,6 +293,11 @@ static inline bool kvm_vcpu_dabt_issext(return !!(kvm_vcpu_get_hsr (vcpu) & ESR_ELx_SSE); } +static inline bool kvm_vcpu_dabt_issf (const struct kvm_vcpu *vcpu) +{ +return !!(kvm_vcpu_get_hsr (vcpu) & ESR_ELx_SF); +} +static inline int kvm_vcpu_dabt_get_rd (const struct kvm_vcpu *vcpu) {return (kvm_vcpu_get_hsr (vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT;
arch/arm64/include/asm/kvm_mmio.h +2 -4
@@ -21,13 +21,11 @@#include <linux/kvm_host.h> #include <asm/kvm_arm.h> -/* -* This is annoying. The mmio code requires this, even if we don't -* need any decoding. To be fixed. -*/ struct kvm_decode {unsigned long rt;bool sign_extend; +/* Witdth of the register accessed by the faulting instruction is 64-bits */ +bool sixty_four; };void kvm_mmio_write_buf (void *buf,unsigned int len,unsigned long data);
virt/kvm/arm/mmio.c +6 -0
@@ -117,6 +117,9 @@ int kvm_handle_mmio_return(struct kvm_vc data = (data ^ mask) - mask; } +if (!vcpu->arch.mmio_decode.sixty_four) + data = data &0xffffffff ; +trace_kvm_mmio (KVM_TRACE_MMIO_READ , len, run->mmio.phys_addr, &data); data =vcpu_data_host_to_guest (vcpu, data, len);
@@ -137,6 +140,7 @@ static int decode_hsr(struct kvm_vcpu *vunsigned long rt;int access_size;bool sign_extend; +bool sixty_four;if (kvm_vcpu_dabt_iss1tw (vcpu)) {/* page table accesses IO mem: tell guest to fix its TTBR */
@@ -150,11 +154,13 @@ static int decode_hsr(struct kvm_vcpu *v *is_write =kvm_vcpu_dabt_iswrite (vcpu); sign_extend =kvm_vcpu_dabt_issext (vcpu); + sixty_four =kvm_vcpu_dabt_issf (vcpu); rt =kvm_vcpu_dabt_get_rd (vcpu); *len = access_size; vcpu->arch.mmio_decode.sign_extend = sign_extend; vcpu->arch.mmio_decode.rt = rt; + vcpu->arch.mmio_decode.sixty_four = sixty_four;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 51/195 MIPS: fix indentation of the RELOCS message
In reply to Greg Kroah-HartmanFrom: Alexander Lobakin <[email protected]>
commit a53998802e178451701d59d38e36f551422977ba upstream.
quiet_cmd_relocs lacks a whitespace which results in:
LD vmlinux SORTEX vmlinux SYSMAP System.map
RELOCS vmlinux
Building modules, stage 2.
MODPOST 64 modules
After this patch:
LD vmlinux SORTEX vmlinux SYSMAP System.map RELOCS vmlinux
Building modules, stage 2.
MODPOST 64 modules
Typo is present in kernel tree since the introduction of relocatable kernel support in commit e818fac595ab ("MIPS: Generate relocation table when CONFIG_RELOCATABLE"), but the relocation scripts were moved to Makefile.postlink later with commit 44079d3509ae ("MIPS: Use Makefile.postlink to insert relocations into vmlinux").
--- arch/mips/Makefile.postlink | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/Makefile.postlink +1 -1
@@ -12,7 +12,7 @@ __archpost: include scripts/Kbuild.include CMD_RELOCS = arch/mips/boot/tools/relocs -quiet_cmd_relocs = RELOCS $@ +quiet_cmd_relocs = RELOCS $@ cmd_relocs = $(CMD_RELOCS) $@ # `@true` prevents complaint when there is nothing to be done
Greg Kroah-Hartman
maintainerPATCH 52/195 MIPS: boot: fix typo in vmlinux.lzma.its target
In reply to Greg Kroah-HartmanFrom: Alexander Lobakin <[email protected]>
commit 16202c09577f3d0c533274c0410b7de05fb0d458 upstream.
Commit 92b34a976348 ("MIPS: boot: add missing targets for vmlinux.*.its") fixed constant rebuild of *.its files on every make invocation, but due to typo ("lzmo") it made no sense for vmlinux.lzma.its.
--- arch/mips/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/boot/Makefile +1 -1
@@ -123,7 +123,7 @@ $(obj)/vmlinux.its.S: $(addprefix $(srct targets += vmlinux.its targets += vmlinux.gz.its targets += vmlinux.bz2.its -targets += vmlinux.lzmo.its +targets += vmlinux.lzma.its targets += vmlinux.lzo.its quiet_cmd_cpp_its_S = ITS $@
Greg Kroah-Hartman
maintainerPATCH 53/195 s390/mm: fix dynamic pagetable upgrade for hugetlbfs
In reply to Greg Kroah-HartmanFrom: Gerald Schaefer <[email protected]>
commit 5f490a520bcb393389a4d44bec90afcb332eb112 upstream.
Commit ee71d16d22bb ("s390/mm: make TASK_SIZE independent from the number of page table levels") changed the logic of TASK_SIZE and also removed the arch_mmap_check() implementation for s390. This combination has a subtle effect on how get_unmapped_area() for hugetlbfs pages works. It is now possible that a user process establishes a hugetlbfs mapping at an address above 4 TB, without triggering a dynamic pagetable upgrade from 3 to 4 levels.
This is because hugetlbfs mappings will not use mm->get_unmapped_area, but rather file->f_op->get_unmapped_area, which currently is the generic implementation of hugetlb_get_unmapped_area() that does not know about s390 dynamic pagetable upgrades, but with the new definition of TASK_SIZE, it will now allow mappings above 4 TB.
Subsequent access to such a mapped address above 4 TB will result in a page fault loop, because the CPU cannot translate such a large address with 3 pagetable levels. The fault handler will try to map in a hugepage at the address, but due to the folded pagetable logic it will end up with creating entries in the 3 level pagetable, possibly overwriting existing mappings, and then it all repeats when the access is retried.
Apart from the page fault loop, this can have various nasty effects, e.g. kernel panic from one of the BUG_ON() checks in memory management code, or even data loss if an existing mapping gets overwritten.
Fix this by implementing HAVE_ARCH_HUGETLB_UNMAPPED_AREA support for s390, providing an s390 version for hugetlb_get_unmapped_area() with pagetable upgrade support similar to arch_get_unmapped_area(), which will then be used instead of the generic version.
--- arch/s390/include/asm/page.h | 2 arch/s390/mm/hugetlbpage.c | 100 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-)
arch/s390/include/asm/page.h +2 -0
@@ -33,6 +33,8 @@#define ARCH_HAS_PREPARE_HUGEPAGE #define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH +#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA +#include <asm/setup.h> #ifndef __ASSEMBLY__
arch/s390/mm/hugetlbpage.c +99 -1
115 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 54/195 powerpc/xmon: dont access ASDR in VMs
In reply to Greg Kroah-HartmanFrom: Sukadev Bhattiprolu <[email protected]>
commit c2a20711fc181e7f22ee5c16c28cb9578af84729 upstream.
ASDR is HV-privileged and must only be accessed in HV-mode. Fixes a Program Check (0x700) when xmon in a VM dumps SPRs.
--- arch/powerpc/xmon/xmon.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
arch/powerpc/xmon/xmon.c +4 -5
@@ -1878,15 +1878,14 @@ static void dump_300_sprs(void)printf ("pidr = %.16lx tidr = %.16lx\n" ,mfspr (SPRN_PID ),mfspr (SPRN_TIDR )); -printf ("asdr = %.16lx psscr = %.16lx\n" , -mfspr (SPRN_ASDR ), hv ?mfspr (SPRN_PSSCR ) - :mfspr (SPRN_PSSCR_PR )); +printf ("psscr = %.16lx\n" , + hv ?mfspr (SPRN_PSSCR ) :mfspr (SPRN_PSSCR_PR ));if (!hv)return ; -printf ("ptcr = %.16lx\n" , -mfspr (SPRN_PTCR )); +printf ("ptcr = %.16lx asdr = %.16lx\n" , +mfspr (SPRN_PTCR ),mfspr (SPRN_ASDR ));#endif }
Greg Kroah-Hartman
maintainerPATCH 55/195 powerpc/pseries: Advance pfn if section is not present in lmb_is_removable()
In reply to Greg Kroah-HartmanFrom: Pingfan Liu <[email protected]>
commit fbee6ba2dca30d302efe6bddb3a886f5e964a257 upstream.
In lmb_is_removable(), if a section is not present, it should continue to test the rest of the sections in the block. But the current code fails to do so.
--- arch/powerpc/platforms/pseries/hotplug-memory.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/platforms/pseries/hotplug-memory.c +3 -1
@@ -366,8 +366,10 @@ static bool lmb_is_removable(struct drmefor (i =0 ; i < scns_per_block; i++) { pfn =PFN_DOWN (phys_addr); -if (!pfn_present (pfn)) +if (!pfn_present (pfn)) { + phys_addr +=MIN_MEMORY_BLOCK_SIZE ;continue ; + } rc &=is_mem_section_removable (pfn,PAGES_PER_SECTION ); phys_addr +=MIN_MEMORY_BLOCK_SIZE ;
Greg Kroah-Hartman
maintainerPATCH 56/195 smb3: fix signing verification of large reads
In reply to Greg Kroah-HartmanFrom: Steve French <[email protected]>
[ Upstream commit 46f17d17687e8140f2e4e517d7dfa65e62fcc5f4 ]
Code cleanup in the 5.1 kernel changed the array passed into signing verification on large reads leading to warning messages being logged when copying files to local systems from remote.
SMB signature verification returned error = -5
This changeset fixes verification of SMB3 signatures of large reads.
--- fs/cifs/smb2pdu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/cifs/smb2pdu.c +2 -2
@@ -3130,8 +3130,8 @@ smb2_readv_callback(struct mid_q_entry *struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)rdata->iov[0 ].iov_base;unsigned int credits_received =0 ; -struct smb_rqst rqst = { .rq_iov = rdata->iov, - .rq_nvec =2 , +struct smb_rqst rqst = { .rq_iov = &rdata->iov[1 ], + .rq_nvec =1 , .rq_pages = rdata->pages, .rq_offset = rdata->page_offset, .rq_npages = rdata->nr_pages,
Greg Kroah-Hartman
maintainerPATCH 57/195 PCI: tegra: Fix return value check of pm_runtime_get_sync()
In reply to Greg Kroah-HartmanFrom: David Engraf <[email protected]>
commit 885199148442f56b880995d703d2ed03b6481a3c upstream.
pm_runtime_get_sync() returns the device's usage counter. This might be >0 if the device is already powered up or CONFIG_PM is disabled.
Abort probe function on real error only.
--- drivers/pci/controller/pci-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/controller/pci-tegra.c +1 -1
@@ -2398,7 +2398,7 @@ static int tegra_pcie_probe(struct platfpm_runtime_enable (pcie->dev); err =pm_runtime_get_sync (pcie->dev); -if (err) { +if (err <0 ) {dev_err (dev,"fail to enable pcie controller: %d\n" , err); goto teardown_msi; }
Greg Kroah-Hartman
maintainerPATCH 58/195 mmc: spi: Toggle SPI polarity, do not hardcode it
In reply to Greg Kroah-HartmanFrom: Linus Walleij <[email protected]>
commit af3ed119329cf9690598c5a562d95dfd128e91d6 upstream.
The code in mmc_spi_initsequence() tries to send a burst with high chipselect and for this reason hardcodes the device into SPI_CS_HIGH.
This is not good because the SPI_CS_HIGH flag indicates logical "asserted" CS not always the physical level. In some cases the signal is inverted in the GPIO library and in that case SPI_CS_HIGH is already set, and enforcing SPI_CS_HIGH again will actually drive it low.
Instead of hard-coding this, toggle the polarity so if the default is LOW it goes high to assert chipselect but if it is already high then toggle it low instead.
--- drivers/mmc/host/mmc_spi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/mmc/host/mmc_spi.c +8 -3
@@ -1154,17 +1154,22 @@ static void mmc_spi_initsequence(struct* SPI protocol. Another is that when chipselect is released while * the card returns BUSY status, the clock must issue several cycles * with chipselect high before the card will stop driving its output. +* +* SPI_CS_HIGH means "asserted" here. In some cases like when using +* GPIOs for chip select, SPI_CS_HIGH is set but this will be logically +* inverted by gpiolib, so if we want to ascertain to drive it high +* we should toggle the default with an XOR as we do here. */ - host->spi->mode |=SPI_CS_HIGH ; + host->spi->mode ^=SPI_CS_HIGH ;if (spi_setup (host->spi) !=0 ) {/* Just warn; most cards work without it. */ dev_warn (&host->spi->dev,"can't change chip-select polarity\n" ); - host->spi->mode &= ~SPI_CS_HIGH ; + host->spi->mode ^=SPI_CS_HIGH ; }else {mmc_spi_readbytes (host,18 ); - host->spi->mode &= ~SPI_CS_HIGH ; + host->spi->mode ^=SPI_CS_HIGH ;if (spi_setup (host->spi) !=0 ) {/* Wot, we can't get the same setup we had before? */ dev_err(&host->spi->dev,
Greg Kroah-Hartman
maintainerPATCH 59/195 ACPI: video: Do not export a non working backlight interface on MSI MS-7721 boards
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit d21a91629f4b8e794fc4c0e0c17c85cedf1d806c upstream.
Despite our heuristics to not wrongly export a non working ACPI backlight interface on desktop machines, we still end up exporting one on desktops using a motherboard from the MSI MS-7721 series.
I've looked at improving the heuristics, but in this case a quirk seems to be the only way to solve this.
While at it also add a comment to separate the video_detect_force_none entries in the video_detect_dmi_table from other type of entries, as we already do for the other entry types.
--- drivers/acpi/video_detect.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/acpi/video_detect.c +13 -0
@@ -328,6 +328,11 @@ static const struct dmi_system_id video_ DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"), }, }, + +/* +* Desktops which falsely report a backlight and which our heuristics +* for this do not catch. +*/ { .callback = video_detect_force_none, .ident = "Dell OptiPlex 9020M",
@@ -336,6 +341,14 @@ static const struct dmi_system_id video_ DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"), }, }, + { + .callback = video_detect_force_none, + .ident = "MSI MS-7721", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MSI"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-7721"), + }, + }, { }, };
Greg Kroah-Hartman
maintainerPATCH 60/195 ACPI / battery: Deal with design or full capacity being reported as -1
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit cc99f0ad52467028cb1251160f23ad4bb65baf20 upstream.
Commit b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity") added support for some (broken) devices which always report 0 for both design- and full_charge-capacity.
This assumes that if the capacity is not being reported it is 0. The ThunderSoft TS178 tablet's _BIX implementation falsifies this assumption. It reports ACPI_BATTERY_VALUE_UNKNOWN (-1) as full_charge_capacity, which we treat as a valid value which causes several problems.
This commit fixes this by adding a new ACPI_BATTERY_CAPACITY_VALID() helper which checks that the value is not 0 and not -1; and using this whenever we need to test if either design_capacity or full_charge_capacity is valid.
--- drivers/acpi/battery.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
drivers/acpi/battery.c +12 -7
@@ -51,6 +51,8 @@#define PREFIX "ACPI: "#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF +#define ACPI_BATTERY_CAPACITY_VALID (capacity) \ + ((capacity) != 0 && (capacity) != ACPI_BATTERY_VALUE_UNKNOWN)#define ACPI_BATTERY_DEVICE_NAME "Battery"
@@ -205,7 +207,8 @@ static int acpi_battery_is_charged(strucstatic bool acpi_battery_is_degraded (struct acpi_battery *battery) { -return battery->full_charge_capacity && battery->design_capacity && +return ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity) && +ACPI_BATTERY_CAPACITY_VALID (battery->design_capacity) && battery->full_charge_capacity < battery->design_capacity; }
@@ -276,14 +279,14 @@ static int acpi_battery_get_property(strbreak ;case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN :case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN : -if (battery->design_capacity ==ACPI_BATTERY_VALUE_UNKNOWN ) +if (!ACPI_BATTERY_CAPACITY_VALID (battery->design_capacity)) ret = -ENODEV ;else val->intval = battery->design_capacity *1000 ;break ;case POWER_SUPPLY_PROP_CHARGE_FULL :case POWER_SUPPLY_PROP_ENERGY_FULL : -if (battery->full_charge_capacity ==ACPI_BATTERY_VALUE_UNKNOWN ) +if (!ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity)) ret = -ENODEV ;else val->intval = battery->full_charge_capacity *1000 ;
@@ -296,11 +299,12 @@ static int acpi_battery_get_property(str val->intval = battery->capacity_now *1000 ;break ;case POWER_SUPPLY_PROP_CAPACITY : -if (battery->capacity_now && battery->full_charge_capacity) +if (battery->capacity_now ==ACPI_BATTERY_VALUE_UNKNOWN || + !ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity)) + ret = -ENODEV ; +else val->intval = battery->capacity_now *100 / battery->full_charge_capacity; -else - val->intval =0 ;break ;case POWER_SUPPLY_PROP_CAPACITY_LEVEL :if (battery->state &ACPI_BATTERY_STATE_CRITICAL )
@@ -812,7 +816,8 @@ static int sysfs_add_battery(struct acpi battery->bat_desc.properties = charge_battery_props; battery->bat_desc.num_properties =ARRAY_SIZE (charge_battery_props); - }else if (battery->full_charge_capacity ==0 ) { + }else if (!ACPI_BATTERY_CAPACITY_VALID ( + battery->full_charge_capacity)) { battery->bat_desc.properties = energy_battery_full_cap_broken_props; battery->bat_desc.num_properties =
Greg Kroah-Hartman
maintainerPATCH 61/195 ACPI / battery: Use design-cap for capacity calculations if full-cap is not available
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit 5b74d1d16e2f5753fcbdecd6771b2d8370dda414 upstream.
The ThunderSoft TS178 tablet's _BIX implementation reports design_capacity but not full_charge_capacity.
Before this commit this would cause us to return -ENODEV for the capacity attribute, which userspace does not like. Specifically upower does this:
if (sysfs_file_exists (native_path, "capacity")) {
percentage = sysfs_get_double (native_path, "capacity");Where the sysfs_get_double() helper returns 0 when we return -ENODEV, so the battery always reads 0% if we return -ENODEV.
This commit fixes this by using the design-capacity instead of the full-charge-capacity when the full-charge-capacity is not available.
--- drivers/acpi/battery.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/acpi/battery.c +8 -3
@@ -230,7 +230,7 @@ static int acpi_battery_get_property(strenum power_supply_property psp, union power_supply_propval *val) { - int ret = 0; + int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0;struct acpi_battery *battery =to_acpi_battery (psy);if (acpi_battery_present (battery)) {
@@ -299,12 +299,17 @@ static int acpi_battery_get_property(str val->intval = battery->capacity_now *1000 ;break ;case POWER_SUPPLY_PROP_CAPACITY : +if (ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity)) + full_capacity = battery->full_charge_capacity; +else if (ACPI_BATTERY_CAPACITY_VALID (battery->design_capacity)) + full_capacity = battery->design_capacity; +if (battery->capacity_now ==ACPI_BATTERY_VALUE_UNKNOWN || - !ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity)) + full_capacity ==ACPI_BATTERY_VALUE_UNKNOWN ) ret = -ENODEV ;else val->intval = battery->capacity_now *100 / - battery->full_charge_capacity; + full_capacity;break ;case POWER_SUPPLY_PROP_CAPACITY_LEVEL :if (battery->state &ACPI_BATTERY_STATE_CRITICAL )
Greg Kroah-Hartman
maintainerPATCH 62/195 ACPI / battery: Deal better with neither design nor full capacity not being reported
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit ff3154d1d89a2343fd5f82e65bc0cf1d4e6659b3 upstream.
Commit b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity") added support for some (broken) devices which always report 0 for both design_capacity and full_charge_capacity.
Since the device that commit was written as a fix for is not reporting any form of "full" capacity we cannot calculate the value for the POWER_SUPPLY_PROP_CAPACITY, this is worked around by using an alternative array of available properties which does not contain this property.
This is necessary because userspace (upower) treats us returning -ENODEV as 0 and then typically will trigger an emergency shutdown because of that. Userspace does not do this if the capacity sysfs attribute is not present at all.
There are two potential problems with that commit:
1) It assumes that both full_charge- and design-capacity are broken at the same time and only checks if full_charge- is broken.
2) It assumes that this only ever happens for devices which report energy units rather then charge units.
This commit fixes both issues by only using the alternative array of available properties if both full_charge- and design-capacity are broken and by also adding an alternative array of available properties for devices using mA units.
--- drivers/acpi/battery.c | 51 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-)
drivers/acpi/battery.c +39 -12
@@ -355,6 +355,20 @@ static enum power_supply_property charge POWER_SUPPLY_PROP_SERIAL_NUMBER, }; +static enum power_supply_property charge_battery_full_cap_broken_props[] = { +POWER_SUPPLY_PROP_STATUS , +POWER_SUPPLY_PROP_PRESENT , +POWER_SUPPLY_PROP_TECHNOLOGY , +POWER_SUPPLY_PROP_CYCLE_COUNT , +POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN , +POWER_SUPPLY_PROP_VOLTAGE_NOW , +POWER_SUPPLY_PROP_CURRENT_NOW , +POWER_SUPPLY_PROP_CHARGE_NOW , +POWER_SUPPLY_PROP_MODEL_NAME , +POWER_SUPPLY_PROP_MANUFACTURER , +POWER_SUPPLY_PROP_SERIAL_NUMBER , +}; +static enum power_supply_property energy_battery_props[] = {POWER_SUPPLY_PROP_STATUS ,POWER_SUPPLY_PROP_PRESENT ,
@@ -816,21 +830,34 @@ static void __exit battery_hook_exit(voistatic int sysfs_add_battery (struct acpi_battery *battery) {struct power_supply_config psy_cfg = { .drv_data = battery, }; +bool full_cap_broken = false; + +if (!ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity) && + !ACPI_BATTERY_CAPACITY_VALID (battery->design_capacity)) + full_cap_broken = true;if (battery->power_unit ==ACPI_BATTERY_POWER_UNIT_MA ) { - battery->bat_desc.properties = charge_battery_props; - battery->bat_desc.num_properties = -ARRAY_SIZE (charge_battery_props); - }else if (!ACPI_BATTERY_CAPACITY_VALID ( - battery->full_charge_capacity)) { - battery->bat_desc.properties = - energy_battery_full_cap_broken_props; - battery->bat_desc.num_properties = -ARRAY_SIZE (energy_battery_full_cap_broken_props); +if (full_cap_broken) { + battery->bat_desc.properties = + charge_battery_full_cap_broken_props; + battery->bat_desc.num_properties = +ARRAY_SIZE (charge_battery_full_cap_broken_props); + }else { + battery->bat_desc.properties = charge_battery_props; + battery->bat_desc.num_properties = +ARRAY_SIZE (charge_battery_props); + } }else { - battery->bat_desc.properties = energy_battery_props; - battery->bat_desc.num_properties = -ARRAY_SIZE (energy_battery_props); +if (full_cap_broken) { + battery->bat_desc.properties = + energy_battery_full_cap_broken_props; + battery->bat_desc.num_properties = +ARRAY_SIZE (energy_battery_full_cap_broken_props); + }else { + battery->bat_desc.properties = energy_battery_props; + battery->bat_desc.num_properties = +ARRAY_SIZE (energy_battery_props); + } } battery->bat_desc.name =acpi_device_bid (battery->device);
Greg Kroah-Hartman
maintainerPATCH 63/195 alarmtimer: Unregister wakeup source when module get fails
In reply to Greg Kroah-HartmanFrom: Stephen Boyd <[email protected]>
commit 6b6d188aae79a630957aefd88ff5c42af6553ee3 upstream.
The alarmtimer_rtc_add_device() function creates a wakeup source and then tries to grab a module reference. If that fails the function returns early with an error code, but fails to remove the wakeup source.
Cleanup this exit path so there is no dangling wakeup source, which is named 'alarmtime' left allocated which will conflict with another RTC device that may be registered later.
--- kernel/time/alarmtimer.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
kernel/time/alarmtimer.c +5 -3
@@ -91,6 +91,7 @@ static int alarmtimer_rtc_add_device(strunsigned long flags;struct rtc_device *rtc =to_rtc_device (dev);struct wakeup_source *__ws; +int ret =0 ;if (rtcdev)return -EBUSY ;
@@ -105,8 +106,8 @@ static int alarmtimer_rtc_add_device(strspin_lock_irqsave (&rtcdev_lock, flags);if (!rtcdev) {if (!try_module_get (rtc->owner)) { -spin_unlock_irqrestore (&rtcdev_lock, flags); -return -1 ; + ret =-1 ; + goto unlock; } rtcdev = rtc;
@@ -115,11 +116,12 @@ static int alarmtimer_rtc_add_device(str ws = __ws; __ws =NULL ; } +unlock:spin_unlock_irqrestore (&rtcdev_lock, flags);wakeup_source_unregister (__ws); -return 0 ; +return ret; }static inline void alarmtimer_rtc_timer_init (void )
Greg Kroah-Hartman
maintainerPATCH 64/195 ubifs: Reject unsupported ioctl flags explicitly
In reply to Greg Kroah-HartmanFrom: Hou Tao <[email protected]>
commit 2fe8b2d5578d7d142982e3bf62e4c0caf8b8fe02 upstream.
Reject unsupported ioctl flags explicitly, so the following command on a regular ubifs file will fail:
chattr +d ubifs_file
And xfstests generic/424 will pass.
--- fs/ubifs/ioctl.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/ubifs/ioctl.c +8 -0
@@ -28,6 +28,11 @@#include <linux/mount.h> #include "ubifs.h" +/* Need to be kept consistent with checked flags in ioctl2ubifs() */ +#define UBIFS_SUPPORTED_IOCTL_FLAGS \ + (FS_COMPR_FL | FS_SYNC_FL | FS_APPEND_FL | \ + FS_IMMUTABLE_FL | FS_DIRSYNC_FL) +/** * ubifs_set_inode_flags - set VFS inode flags. * @inode: VFS inode to set flags for
@@ -169,6 +174,9 @@ long ubifs_ioctl(struct file *file, unsiif (get_user (flags, (int __user *) arg))return -EFAULT ; +if (flags & ~UBIFS_SUPPORTED_IOCTL_FLAGS ) +return -EOPNOTSUPP ; +if (!S_ISDIR (inode->i_mode)) flags &= ~FS_DIRSYNC_FL ;
Greg Kroah-Hartman
maintainerPATCH 65/195 ubifs: dont trigger assertion on invalid no-key filename
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit f0d07a98a070bb5e443df19c3aa55693cbca9341 upstream.
If userspace provides an invalid fscrypt no-key filename which encodes a hash value with any of the UBIFS node type bits set (i.e. the high 3 bits), gracefully report ENOENT rather than triggering ubifs_assert().
Test case with kvm-xfstests shell:
. fs/ubifs/config
. ~/xfstests/common/encrypt dev=$(__blkdev_to_ubi_volume /dev/vdc) ubiupdatevol $dev -t
mount $dev /mnt -t ubifs
mkdir /mnt/edir
xfs_io -c set_encpolicy /mnt/edir
rm /mnt/edir/_,,,,,DAAAAAAAAAAAAAAAAAAAAAAAAAA
With the bug, the following assertion fails on the 'rm' command:
[ 19.066048] UBIFS error (ubi0:0 pid 379): ubifs_assert_failed: UBIFS assert failed: !(hash & ~UBIFS_S_KEY_HASH_MASK), in fs/ubifs/key.h:170
--- fs/ubifs/dir.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ubifs/dir.c +2 -0
@@ -242,6 +242,8 @@ static struct dentry *ubifs_lookup(strucif (nm.hash) {ubifs_assert (c,fname_len (&nm) ==0 );ubifs_assert (c,fname_name (&nm) ==NULL ); +if (nm.hash & ~UBIFS_S_KEY_HASH_MASK ) + goto done;/* ENOENT */ dent_key_init_hash (c, &key, dir->i_ino, nm.hash); err =ubifs_tnc_lookup_dh (c, &key, dent, nm.minor_hash); }else {
Greg Kroah-Hartman
maintainerPATCH 66/195 ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 2b57067a7778484c10892fa191997bfda29fea13 upstream.
UBIFS's implementation of FS_IOC_SETFLAGS fails to preserve existing inode flags that aren't settable by FS_IOC_SETFLAGS, namely the encrypt flag. This causes the encrypt flag to be unexpectedly cleared.
Fix it by preserving existing unsettable flags, like ext4 and f2fs do.
Test case with kvm-xfstests shell:
FSTYP=ubifs KEYCTL_PROG=keyctl
. fs/ubifs/config
. ~/xfstests/common/encrypt
dev=$(__blkdev_to_ubi_volume /dev/vdc)
ubiupdatevol -t $dev
mount $dev /mnt -t ubifs
k=$(_generate_session_encryption_key)
mkdir /mnt/edir
xfs_io -c "set_encpolicy $k" /mnt/edir
echo contents > /mnt/edir/file
chattr +i /mnt/edir/file
chattr -i /mnt/edir/file
With the bug, the following errors occur on the last command:
[ 18.081559] fscrypt (ubifs, inode 67): Inconsistent encryption context (parent directory: 65)
chattr: Operation not permitted while reading flags on /mnt/edir/file--- fs/ubifs/ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ubifs/ioctl.c +2 -1
@@ -132,7 +132,8 @@ static int setflags(struct inode *inode, } } - ui->flags =ioctl2ubifs (flags); + ui->flags &= ~ioctl2ubifs (UBIFS_SUPPORTED_IOCTL_FLAGS ); + ui->flags |=ioctl2ubifs (flags);ubifs_set_inode_flags (inode); inode->i_ctime =current_time (inode); release = ui->dirty;
Greg Kroah-Hartman
maintainerPATCH 67/195 ubifs: Fix deadlock in concurrent bulk-read and writepage
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
commit f5de5b83303e61b1f3fb09bd77ce3ac2d7a475f2 upstream.
In ubifs, concurrent execution of writepage and bulk read on the same file may cause ABBA deadlock, for example (Reproduce method see Link):
Process A(Bulk-read starts from page4) Process B(write page4 back)
vfs_read wb_workfn or fsync ... ... generic_file_buffered_read write_cache_pages
ubifs_readpage LOCK(page4)
ubifs_bulk_read ubifs_writepage
LOCK(ui->ui_mutex) ubifs_write_inode
ubifs_do_bulk_read LOCK(ui->ui_mutex)
find_or_create_page(alloc page4) ↑
LOCK(page4) <-- ABBA deadlock occurs!
In order to ensure the serialization execution of bulk read, we can't remove the big lock 'ui->ui_mutex' in ubifs_bulk_read(). Instead, we allow ubifs_do_bulk_read() to lock page failed by replacing find_or_create_page(FGP_LOCK) with pagecache_get_page(FGP_LOCK | FGP_NOWAIT).
--- fs/ubifs/file.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ubifs/file.c +3 -1
@@ -798,7 +798,9 @@ static int ubifs_do_bulk_read(struct ubiif (page_offset > end_index)break ; - page =find_or_create_page (mapping, page_offset, ra_gfp_mask); + page =pagecache_get_page (mapping, page_offset, +FGP_LOCK |FGP_ACCESSED |FGP_CREAT |FGP_NOWAIT , + ra_gfp_mask);if (!page)break ;if (!PageUptodate (page))
Greg Kroah-Hartman
maintainerPATCH 68/195 crypto: geode-aes - convert to skcipher API and make thread-safe
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 4549f7e5aa27ffc2cba63b5db8842a3b486f5688 upstream.
The geode AES driver is heavily broken because it stores per-request state in the transform context. So it will crash or produce the wrong result if used by any of the many places in the kernel that issue concurrent requests for the same transform object.
This driver is also implemented using the deprecated blkcipher API, which makes it difficult to fix, and puts it among the drivers preventing that API from being removed.
Convert this driver to use the skcipher API, and change it to not store per-request state in the transform context.
--- drivers/crypto/geode-aes.c | 450 +++++++++++++++------------------------------ drivers/crypto/geode-aes.h | 15 - 2 files changed, 153 insertions(+), 312 deletions(-)
drivers/crypto/geode-aes.c +151 -299
@@ -14,7 +14,7 @@#include <linux/spinlock.h> #include <crypto/algapi.h> #include <crypto/aes.h> -#include <crypto/skcipher.h> +#include <crypto/internal/skcipher.h> #include <linux/io.h> #include <linux/delay.h>
@@ -28,12 +28,12 @@ static spinlock_t lock;/* Write a 128 bit field (either a writable key or IV) */ static inline void -_writefield (u32 offset,void *value) +_writefield (u32 offset,const void *value) {int i;for (i =0 ; i <4 ; i++) -iowrite32 (((u32 *) value)[i], _iobase + offset + (i *4 )); +iowrite32 (((const u32 *) value)[i], _iobase + offset + (i *4 )); }/* Read a 128 bit field (either a writable key or IV) */
@@ -47,12 +47,12 @@ _readfield(u32 offset, void *value) }static int -do_crypt (void *src,void *dst,int len,u32 flags) +do_crypt (const void *src,void *dst,u32 len,u32 flags) {u32 status;u32 counter =AES_OP_TIMEOUT ; -iowrite32 (virt_to_phys (src), _iobase +AES_SOURCEA_REG ); +iowrite32 (virt_to_phys ((void *)src), _iobase +AES_SOURCEA_REG );iowrite32 (virt_to_phys (dst), _iobase +AES_DSTA_REG );iowrite32 (len, _iobase +AES_LENA_REG );
@@ -69,16 +69,14 @@ do_crypt(void *src, void *dst, int len,return counter ?0 :1 ; } -static unsigned int -geode_aes_crypt (struct geode_aes_op *op) +static void +geode_aes_crypt (const struct geode_aes_tfm_ctx *tctx,const void *src, +void *dst,u32 len,u8 *iv,int mode,int dir) {u32 flags =0 ;unsigned long iflags;int ret; -if (op->len ==0 ) -return 0 ; -/* If the source and destination is the same, then * we need to turn on the coherent flags, otherwise * we don't need to worry
@@ -86,32 +84,28 @@ geode_aes_crypt(struct geode_aes_op *op) flags |= (AES_CTRL_DCA |AES_CTRL_SCA ); -if (op->dir ==AES_DIR_ENCRYPT ) +if (dir ==AES_DIR_ENCRYPT ) flags |=AES_CTRL_ENCRYPT ;/* Start the critical section */ spin_lock_irqsave (&lock, iflags); -if (op->mode ==AES_MODE_CBC ) { +if (mode ==AES_MODE_CBC ) { flags |=AES_CTRL_CBC ; -_writefield (AES_WRITEIV0_REG , op->iv); +_writefield (AES_WRITEIV0_REG , iv); } -if (!(op->flags &AES_FLAGS_HIDDENKEY )) { - flags |=AES_CTRL_WRKEY ; -_writefield (AES_WRITEKEY0_REG , op->key); - } + flags |=AES_CTRL_WRKEY ; +_writefield (AES_WRITEKEY0_REG , tctx->key); - ret =do_crypt (op->src, op->dst, op->len, flags); + ret =do_crypt (src, dst, len, flags);BUG_ON (ret); -if (op->mode ==AES_MODE_CBC ) -_readfield (AES_WRITEIV0_REG , op->iv); +if (mode ==AES_MODE_CBC ) +_readfield (AES_WRITEIV0_REG , iv);spin_unlock_irqrestore (&lock, iflags); - -return op->len; }/* CRYPTO-API Functions */
@@ -119,13 +113,13 @@ geode_aes_crypt(struct geode_aes_op *op)static int geode_setkey_cip (struct crypto_tfm *tfm,const u8 *key,unsigned int len) { -struct geode_aes_op *op =crypto_tfm_ctx (tfm); +struct geode_aes_tfm_ctx *tctx =crypto_tfm_ctx (tfm);unsigned int ret; - op->keylen = len; + tctx->keylen = len;if (len ==AES_KEYSIZE_128 ) { -memcpy (op->key, key, len); +memcpy (tctx->key, key, len);return 0 ; }
@@ -138,132 +132,93 @@ static int geode_setkey_cip(struct crypt/* * The requested key size is not supported by HW, do a fallback */ - op->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK ; - op->fallback.cip->base.crt_flags |= (tfm->crt_flags &CRYPTO_TFM_REQ_MASK ); + tctx->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK ; + tctx->fallback.cip->base.crt_flags |= + (tfm->crt_flags &CRYPTO_TFM_REQ_MASK ); - ret =crypto_cipher_setkey (op->fallback.cip, key, len); + ret =crypto_cipher_setkey (tctx->fallback.cip, key, len);if (ret) { tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK ; - tfm->crt_flags |= (op->fallback.cip->base.crt_flags &CRYPTO_TFM_RES_MASK ); + tfm->crt_flags |= (tctx->fallback.cip->base.crt_flags & +CRYPTO_TFM_RES_MASK ); }return ret; } -static int geode_setkey_blk (struct crypto_tfm *tfm,const u8 *key, -unsigned int len) +static int geode_setkey_skcipher (struct crypto_skcipher *tfm,const u8 *key, +unsigned int len) { -struct geode_aes_op *op =crypto_tfm_ctx (tfm); +struct geode_aes_tfm_ctx *tctx =crypto_skcipher_ctx (tfm);unsigned int ret; - op->keylen = len; + tctx->keylen = len;if (len ==AES_KEYSIZE_128 ) { -memcpy (op->key, key, len); +memcpy (tctx->key, key, len);return 0 ; }if (len !=AES_KEYSIZE_192 && len !=AES_KEYSIZE_256 ) {/* not supported at all */ - tfm->crt_flags |=CRYPTO_TFM_RES_BAD_KEY_LEN ; +crypto_skcipher_set_flags (tfm,CRYPTO_TFM_RES_BAD_KEY_LEN );return -EINVAL ; }/* * The requested key size is not supported by HW, do a fallback */ -crypto_skcipher_clear_flags (op->fallback.blk,CRYPTO_TFM_REQ_MASK ); -crypto_skcipher_set_flags (op->fallback.blk, - tfm->crt_flags &CRYPTO_TFM_REQ_MASK ); - - ret =crypto_skcipher_setkey (op->fallback.blk, key, len); -if (ret) { - tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK ; - tfm->crt_flags |=crypto_skcipher_get_flags (op->fallback.blk) & -CRYPTO_TFM_RES_MASK ; - } +crypto_skcipher_clear_flags (tctx->fallback.skcipher, +CRYPTO_TFM_REQ_MASK ); +crypto_skcipher_set_flags (tctx->fallback.skcipher, +crypto_skcipher_get_flags (tfm) & +CRYPTO_TFM_REQ_MASK ); + ret =crypto_skcipher_setkey (tctx->fallback.skcipher, key, len); +crypto_skcipher_set_flags (tfm, +crypto_skcipher_get_flags (tctx->fallback.skcipher) & +CRYPTO_TFM_RES_MASK );return ret; } -static int fallback_blk_dec (struct blkcipher_desc *desc, -struct scatterlist *dst,struct scatterlist *src, -unsigned int nbytes) -{ -struct geode_aes_op *op =crypto_blkcipher_ctx (desc->tfm); -SKCIPHER_REQUEST_ON_STACK (req, op->fallback.blk); - -skcipher_request_set_tfm (req, op->fallback.blk); -skcipher_request_set_callback (req,0 ,NULL ,NULL ); -skcipher_request_set_crypt (req, src, dst, nbytes, desc->info); - -return crypto_skcipher_decrypt (req); -} - -static int fallback_blk_enc (struct blkcipher_desc *desc, -struct scatterlist *dst,struct scatterlist *src, -unsigned int nbytes) -{ -struct geode_aes_op *op =crypto_blkcipher_ctx (desc->tfm); -SKCIPHER_REQUEST_ON_STACK (req, op->fallback.blk); - -skcipher_request_set_tfm (req, op->fallback.blk); -skcipher_request_set_callback (req,0 ,NULL ,NULL ); -skcipher_request_set_crypt (req, src, dst, nbytes, desc->info); - -return crypto_skcipher_encrypt (req); -} -static void geode_encrypt (struct crypto_tfm *tfm,u8 *out,const u8 *in) { -struct geode_aes_op *op =crypto_tfm_ctx (tfm); +const struct geode_aes_tfm_ctx *tctx =crypto_tfm_ctx (tfm); -if (unlikely (op->keylen !=AES_KEYSIZE_128 )) { -crypto_cipher_encrypt_one (op->fallback.cip, out, in); +if (unlikely (tctx->keylen !=AES_KEYSIZE_128 )) { +crypto_cipher_encrypt_one (tctx->fallback.cip, out, in);return ; } - op->src = (void *) in; - op->dst = (void *) out; - op->mode =AES_MODE_ECB ; - op->flags =0 ; - op->len =AES_BLOCK_SIZE ; - op->dir =AES_DIR_ENCRYPT ; - -geode_aes_crypt (op); +geode_aes_crypt (tctx, in, out,AES_BLOCK_SIZE ,NULL , +AES_MODE_ECB ,AES_DIR_ENCRYPT ); }static void geode_decrypt (struct crypto_tfm *tfm,u8 *out,const u8 *in) { -struct geode_aes_op *op =crypto_tfm_ctx (tfm); +const struct geode_aes_tfm_ctx *tctx =crypto_tfm_ctx (tfm); -if (unlikely (op->keylen !=AES_KEYSIZE_128 )) { -crypto_cipher_decrypt_one (op->fallback.cip, out, in); +if (unlikely (tctx->keylen !=AES_KEYSIZE_128 )) { +crypto_cipher_decrypt_one (tctx->fallback.cip, out, in);return ; } - op->src = (void *) in; - op->dst = (void *) out; - op->mode =AES_MODE_ECB ; - op->flags =0 ; - op->len =AES_BLOCK_SIZE ; - op->dir =AES_DIR_DECRYPT ; - -geode_aes_crypt (op); +geode_aes_crypt (tctx, in, out,AES_BLOCK_SIZE ,NULL , +AES_MODE_ECB ,AES_DIR_DECRYPT ); }static int fallback_init_cip (struct crypto_tfm *tfm) {const char *name =crypto_tfm_alg_name (tfm); -struct geode_aes_op *op =crypto_tfm_ctx (tfm); +struct geode_aes_tfm_ctx *tctx =crypto_tfm_ctx (tfm); - op->fallback.cip =crypto_alloc_cipher (name,0 , -CRYPTO_ALG_ASYNC |CRYPTO_ALG_NEED_FALLBACK ); + tctx->fallback.cip =crypto_alloc_cipher (name,0 , +CRYPTO_ALG_NEED_FALLBACK ); -if (IS_ERR (op->fallback.cip)) { +if (IS_ERR (tctx->fallback.cip)) {printk (KERN_ERR "Error allocating fallback algo %s\n" , name); -return PTR_ERR (op->fallback.cip); +return PTR_ERR (tctx->fallback.cip); }return 0 ;
@@ -271,10 +226,9 @@ static int fallback_init_cip(struct crypstatic void fallback_exit_cip (struct crypto_tfm *tfm) { -struct geode_aes_op *op =crypto_tfm_ctx (tfm); +struct geode_aes_tfm_ctx *tctx =crypto_tfm_ctx (tfm); -crypto_free_cipher (op->fallback.cip); - op->fallback.cip =NULL ; +crypto_free_cipher (tctx->fallback.cip); }static struct crypto_alg geode_alg = {
@@ -287,7 +241,7 @@ static struct crypto_alg geode_alg = { .cra_init = fallback_init_cip, .cra_exit = fallback_exit_cip, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct geode_aes_op), + .cra_ctxsize = sizeof(struct geode_aes_tfm_ctx), .cra_module = THIS_MODULE, .cra_u = { .cipher = {
@@ -300,222 +254,126 @@ static struct crypto_alg geode_alg = { } }; -static int -geode_cbc_decrypt (struct blkcipher_desc *desc, -struct scatterlist *dst,struct scatterlist *src, -unsigned int nbytes) -{ -struct geode_aes_op *op =crypto_blkcipher_ctx (desc->tfm); -struct blkcipher_walk walk; -int err, ret; - -if (nbytes %AES_BLOCK_SIZE ) -return -EINVAL ; - -if (unlikely (op->keylen !=AES_KEYSIZE_128 )) -return fallback_blk_dec (desc, dst, src, nbytes); - -blkcipher_walk_init (&walk, dst, src, nbytes); - err =blkcipher_walk_virt (desc, &walk); - op->iv = walk.iv; - -while ((nbytes = walk.nbytes)) { - op->src = walk.src.virt.addr, - op->dst = walk.dst.virt.addr; - op->mode =AES_MODE_CBC ; - op->len = nbytes - (nbytes %AES_BLOCK_SIZE ); - op->dir =AES_DIR_DECRYPT ; - - ret =geode_aes_crypt (op); - - nbytes -= ret; - err =blkcipher_walk_done (desc, &walk, nbytes); - } - -return err; -} - -static int -geode_cbc_encrypt (struct blkcipher_desc *desc, -struct scatterlist *dst,struct scatterlist *src, -unsigned int nbytes) -{ -struct geode_aes_op *op =crypto_blkcipher_ctx (desc->tfm); -struct blkcipher_walk walk; -int err, ret; - -if (nbytes %AES_BLOCK_SIZE ) -return -EINVAL ; - -if (unlikely (op->keylen !=AES_KEYSIZE_128 )) -return fallback_blk_enc (desc, dst, src, nbytes); - -blkcipher_walk_init (&walk, dst, src, nbytes); - err =blkcipher_walk_virt (desc, &walk); - op->iv = walk.iv; - -while ((nbytes = walk.nbytes)) { - op->src = walk.src.virt.addr, - op->dst = walk.dst.virt.addr; - op->mode =AES_MODE_CBC ; - op->len = nbytes - (nbytes %AES_BLOCK_SIZE ); - op->dir =AES_DIR_ENCRYPT ; - - ret =geode_aes_crypt (op); - nbytes -= ret; - err =blkcipher_walk_done (desc, &walk, nbytes); - } - -return err; -} - -static int fallback_init_blk (struct crypto_tfm *tfm) +static int geode_init_skcipher (struct crypto_skcipher *tfm) { -const char *name =crypto_tfm_alg_name (tfm); -struct geode_aes_op *op =crypto_tfm_ctx (tfm); - - op->fallback.blk =crypto_alloc_skcipher (name,0 , -CRYPTO_ALG_ASYNC | -CRYPTO_ALG_NEED_FALLBACK ); +const char *name =crypto_tfm_alg_name (&tfm->base); +struct geode_aes_tfm_ctx *tctx =crypto_skcipher_ctx (tfm); -if (IS_ERR (op->fallback.blk)) { + tctx->fallback.skcipher = +crypto_alloc_skcipher (name,0 ,CRYPTO_ALG_NEED_FALLBACK | +CRYPTO_ALG_ASYNC ); +if (IS_ERR (tctx->fallback.skcipher)) {printk (KERN_ERR "Error allocating fallback algo %s\n" , name); -return PTR_ERR (op->fallback.blk); +return PTR_ERR (tctx->fallback.skcipher); } +crypto_skcipher_set_reqsize (tfm,sizeof (struct skcipher_request ) + +crypto_skcipher_reqsize (tctx->fallback.skcipher));return 0 ; } -static void fallback_exit_blk (struct crypto_tfm *tfm) +static void geode_exit_skcipher (struct crypto_skcipher *tfm) { -struct geode_aes_op *op =crypto_tfm_ctx (tfm); +struct geode_aes_tfm_ctx *tctx =crypto_skcipher_ctx (tfm); -crypto_free_skcipher (op->fallback.blk); - op->fallback.blk =NULL ; +crypto_free_skcipher (tctx->fallback.skcipher); } -static struct crypto_alg geode_cbc_alg = { - .cra_name ="cbc(aes)" , - .cra_driver_name ="cbc-aes-geode" , - .cra_priority =400 , - .cra_flags =CRYPTO_ALG_TYPE_BLKCIPHER | -CRYPTO_ALG_KERN_DRIVER_ONLY | -CRYPTO_ALG_NEED_FALLBACK , - .cra_init = fallback_init_blk, - .cra_exit = fallback_exit_blk, - .cra_blocksize =AES_BLOCK_SIZE , - .cra_ctxsize =sizeof (struct geode_aes_op ), - .cra_alignmask =15 , - .cra_type = &crypto_blkcipher_type, - .cra_module =THIS_MODULE , - .cra_u = { - .blkcipher = { - .min_keysize =AES_MIN_KEY_SIZE , - .max_keysize =AES_MAX_KEY_SIZE , - .setkey = geode_setkey_blk, - .encrypt = geode_cbc_encrypt, - .decrypt = geode_cbc_decrypt, - .ivsize =AES_BLOCK_SIZE , - } - } -}; - -static int -geode_ecb_decrypt (struct blkcipher_desc *desc, -struct scatterlist *dst,struct scatterlist *src, -unsigned int nbytes) -{ -struct geode_aes_op *op =crypto_blkcipher_ctx (desc->tfm); -struct blkcipher_walk walk; -int err, ret; +static int geode_skcipher_crypt (struct skcipher_request *req,int mode,int dir) +{ +struct crypto_skcipher *tfm =crypto_skcipher_reqtfm (req); +const struct geode_aes_tfm_ctx *tctx =crypto_skcipher_ctx (tfm); +struct skcipher_walk walk; +unsigned int nbytes; +int err; -if (nbytes %AES_BLOCK_SIZE ) -return -EINVAL ; +if (unlikely (tctx->keylen !=AES_KEYSIZE_128 )) { +struct skcipher_request *subreq =skcipher_request_ctx (req); -if (unlikely (op->keylen !=AES_KEYSIZE_128 )) -return fallback_blk_dec (desc, dst, src, nbytes); + *subreq = *req; +skcipher_request_set_tfm (subreq, tctx->fallback.skcipher); +if (dir ==AES_DIR_DECRYPT ) +return crypto_skcipher_decrypt (subreq); +else +return crypto_skcipher_encrypt (subreq); + } -blkcipher_walk_init (&walk, dst, src, nbytes); - err =blkcipher_walk_virt (desc, &walk); + err =skcipher_walk_virt (&walk, req, false); -while ((nbytes = walk.nbytes)) { - op->src = walk.src.virt.addr, - op->dst = walk.dst.virt.addr; - op->mode =AES_MODE_ECB ; - op->len = nbytes - (nbytes %AES_BLOCK_SIZE ); - op->dir =AES_DIR_DECRYPT ; - - ret =geode_aes_crypt (op); - nbytes -= ret; - err =blkcipher_walk_done (desc, &walk, nbytes); +while ((nbytes = walk.nbytes) !=0 ) { +geode_aes_crypt (tctx, walk.src.virt.addr, walk.dst.virt.addr, +round_down (nbytes,AES_BLOCK_SIZE ), + walk.iv, mode, dir); + err =skcipher_walk_done (&walk, nbytes %AES_BLOCK_SIZE ); }return err; } -static int -geode_ecb_encrypt (struct blkcipher_desc *desc, -struct scatterlist *dst,struct scatterlist *src, -unsigned int nbytes) -{ -struct geode_aes_op *op =crypto_blkcipher_ctx (desc->tfm); -struct blkcipher_walk walk; -int err, ret; - -if (nbytes %AES_BLOCK_SIZE ) -return -EINVAL ; - -if (unlikely (op->keylen !=AES_KEYSIZE_128 )) -return fallback_blk_enc (desc, dst, src, nbytes); - -blkcipher_walk_init (&walk, dst, src, nbytes); - err =blkcipher_walk_virt (desc, &walk); - -while ((nbytes = walk.nbytes)) { - op->src = walk.src.virt.addr, - op->dst = walk.dst.virt.addr; - op->mode =AES_MODE_ECB ; - op->len = nbytes - (nbytes %AES_BLOCK_SIZE ); - op->dir =AES_DIR_ENCRYPT ; - - ret =geode_aes_crypt (op); - nbytes -= ret; - ret =blkcipher_walk_done (desc, &walk, nbytes); - } +static int geode_cbc_encrypt (struct skcipher_request *req) +{ +return geode_skcipher_crypt (req,AES_MODE_CBC ,AES_DIR_ENCRYPT ); +} -return err; +static int geode_cbc_decrypt (struct skcipher_request *req) +{ +return geode_skcipher_crypt (req,AES_MODE_CBC ,AES_DIR_DECRYPT ); } -static struct crypto_alg geode_ecb_alg = { - .cra_name ="ecb(aes)" , - .cra_driver_name ="ecb-aes-geode" , - .cra_priority =400 , - .cra_flags =CRYPTO_ALG_TYPE_BLKCIPHER | -CRYPTO_ALG_KERN_DRIVER_ONLY | -CRYPTO_ALG_NEED_FALLBACK , - .cra_init = fallback_init_blk, - .cra_exit = fallback_exit_blk, - .cra_blocksize =AES_BLOCK_SIZE , - .cra_ctxsize =sizeof (struct geode_aes_op ), - .cra_alignmask =15 , - .cra_type = &crypto_blkcipher_type, - .cra_module =THIS_MODULE , - .cra_u = { - .blkcipher = { - .min_keysize =AES_MIN_KEY_SIZE , - .max_keysize =AES_MAX_KEY_SIZE , - .setkey = geode_setkey_blk, - .encrypt = geode_ecb_encrypt, - .decrypt = geode_ecb_decrypt, - } - } +static int geode_ecb_encrypt (struct skcipher_request *req) +{ +return geode_skcipher_crypt (req,AES_MODE_ECB ,AES_DIR_ENCRYPT ); +} + +static int geode_ecb_decrypt (struct skcipher_request *req) +{ +return geode_skcipher_crypt (req,AES_MODE_ECB ,AES_DIR_DECRYPT ); +} + +static struct skcipher_alg geode_skcipher_algs[] = { + { + .base.cra_name ="cbc(aes)" , + .base.cra_driver_name ="cbc-aes-geode" , + .base.cra_priority =400 , + .base.cra_flags =CRYPTO_ALG_KERN_DRIVER_ONLY | +CRYPTO_ALG_NEED_FALLBACK , + .base.cra_blocksize =AES_BLOCK_SIZE , + .base.cra_ctxsize =sizeof (struct geode_aes_tfm_ctx ), + .base.cra_alignmask =15 , + .base.cra_module =THIS_MODULE , + .init = geode_init_skcipher, + .exit = geode_exit_skcipher, + .setkey = geode_setkey_skcipher, + .encrypt = geode_cbc_encrypt, + .decrypt = geode_cbc_decrypt, + .min_keysize =AES_MIN_KEY_SIZE , + .max_keysize =AES_MAX_KEY_SIZE , + .ivsize =AES_BLOCK_SIZE , + }, { + .base.cra_name ="ecb(aes)" , + .base.cra_driver_name ="ecb-aes-geode" , + .base.cra_priority =400 , + .base.cra_flags =CRYPTO_ALG_KERN_DRIVER_ONLY | +CRYPTO_ALG_NEED_FALLBACK , + .base.cra_blocksize =AES_BLOCK_SIZE , + .base.cra_ctxsize =sizeof (struct geode_aes_tfm_ctx ), + .base.cra_alignmask =15 , + .base.cra_module =THIS_MODULE , + .init = geode_init_skcipher, + .exit = geode_exit_skcipher, + .setkey = geode_setkey_skcipher, + .encrypt = geode_ecb_encrypt, + .decrypt = geode_ecb_decrypt, + .min_keysize =AES_MIN_KEY_SIZE , + .max_keysize =AES_MAX_KEY_SIZE , + }, };static void geode_aes_remove (struct pci_dev *dev) {crypto_unregister_alg (&geode_alg); -crypto_unregister_alg (&geode_ecb_alg); -crypto_unregister_alg (&geode_cbc_alg); +crypto_unregister_skciphers (geode_skcipher_algs, +ARRAY_SIZE (geode_skcipher_algs));pci_iounmap (dev, _iobase); _iobase =NULL ;
@@ -553,20 +411,14 @@ static int geode_aes_probe(struct pci_deif (ret) goto eiomap; - ret =crypto_register_alg (&geode_ecb_alg); + ret =crypto_register_skciphers (geode_skcipher_algs, +ARRAY_SIZE (geode_skcipher_algs));if (ret) goto ealg; - ret =crypto_register_alg (&geode_cbc_alg); -if (ret) - goto eecb; -dev_notice (&dev->dev,"GEODE AES engine enabled.\n" );return 0 ; - eecb: -crypto_unregister_alg (&geode_ecb_alg); - ealg:crypto_unregister_alg (&geode_alg);
drivers/crypto/geode-aes.h +2 -13
@@ -50,21 +50,10 @@#define AES_OP_TIMEOUT 0x50000 -struct geode_aes_op { - -void *src; -void *dst; - -u32 mode; -u32 dir; -u32 flags; -int len; - +struct geode_aes_tfm_ctx {u8 key[AES_KEYSIZE_128 ]; -u8 *iv; -union { -struct crypto_skcipher *blk; +struct crypto_skcipher *skcipher;struct crypto_cipher *cip; } fallback;u32 keylen;
Greg Kroah-Hartman
maintainerPATCH 69/195 PCI: keystone: Fix link training retries initiation
In reply to Greg Kroah-HartmanFrom: Yurii Monakov <[email protected]>
[ Upstream commit 6df19872d881641e6394f93ef2938cffcbdae5bb ]
ks_pcie_stop_link() function does not clear LTSSM_EN_VAL bit so link training was not triggered more than once after startup. In configurations where link can be unstable during early boot, for example, under low temperature, it will never be established.
--- drivers/pci/controller/dwc/pci-keystone-dw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/controller/dwc/pci-keystone-dw.c +1 -1
@@ -425,7 +425,7 @@ void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)/* Disable Link training */ val =ks_dw_app_readl (ks_pcie,CMD_STATUS ); val &= ~LTSSM_EN_VAL ; -ks_dw_app_writel (ks_pcie,CMD_STATUS ,LTSSM_EN_VAL | val); +ks_dw_app_writel (ks_pcie,CMD_STATUS , val);/* Initiate Link Training */ val =ks_dw_app_readl (ks_pcie,CMD_STATUS );
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 70/195 mmc: sdhci-of-at91: fix memleak on clk_get failure
In reply to Greg Kroah-HartmanFrom: Michał Mirosław <[email protected]>
[ Upstream commit a04184ce777b46e92c2b3c93c6dcb2754cb005e1 ]
sdhci_alloc_host() does its work not using managed infrastructure, so needs explicit free on error path. Add it where needed.
--- drivers/mmc/host/sdhci-of-at91.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/mmc/host/sdhci-of-at91.c +6 -3
@@ -332,19 +332,22 @@ static int sdhci_at91_probe(struct platform_device *pdev) priv->mainck =devm_clk_get (&pdev->dev,"baseclk" );if (IS_ERR (priv->mainck)) {dev_err (&pdev->dev,"failed to get baseclk\n" ); -return PTR_ERR (priv->mainck); + ret =PTR_ERR (priv->mainck); + goto sdhci_pltfm_free; } priv->hclock =devm_clk_get (&pdev->dev,"hclock" );if (IS_ERR (priv->hclock)) {dev_err (&pdev->dev,"failed to get hclock\n" ); -return PTR_ERR (priv->hclock); + ret =PTR_ERR (priv->hclock); + goto sdhci_pltfm_free; } priv->gck =devm_clk_get (&pdev->dev,"multclk" );if (IS_ERR (priv->gck)) {dev_err (&pdev->dev,"failed to get multclk\n" ); -return PTR_ERR (priv->gck); + ret =PTR_ERR (priv->gck); + goto sdhci_pltfm_free; } ret =sdhci_at91_set_clks_presets (&pdev->dev);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 71/195 hv_balloon: Balloon up according to request page number
In reply to Greg Kroah-HartmanFrom: Tianyu Lan <[email protected]>
commit d33c240d47dab4fd15123d9e73fc8810cbc6ed6a upstream.
Current code has assumption that balloon request memory size aligns with 2MB. But actually Hyper-V doesn't guarantee such alignment. When balloon driver receives non-aligned balloon request, it produces warning and balloon up more memory than requested in order to keep 2MB alignment. Remove the warning and balloon up memory according to actual requested memory size.
--- drivers/hv/hv_balloon.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)
drivers/hv/hv_balloon.c +3 -10
@@ -1215,10 +1215,7 @@ static unsigned int alloc_balloon_pages(unsigned int i =0 ;struct page *pg; -if (num_pages < alloc_unit) -return 0 ; - -for (i =0 ; (i * alloc_unit) < num_pages; i++) { +for (i =0 ; i < num_pages / alloc_unit; i++) {if (bl_resp->hdr.size +sizeof (union dm_mem_page_range ) >PAGE_SIZE )return i * alloc_unit;
@@ -1252,7 +1249,7 @@ static unsigned int alloc_balloon_pages( } -return num_pages; +return i * alloc_unit; }static void balloon_up (struct work_struct *dummy)
@@ -1267,9 +1264,6 @@ static void balloon_up(struct work_struclong avail_pages;unsigned long floor; -/* The host balloons pages in 2M granularity. */ -WARN_ON_ONCE (num_pages %PAGES_IN_2M !=0 ); -/* * We will attempt 2M allocations. However, if we fail to * allocate 2M chunks, we will go back to 4k allocations.
@@ -1279,14 +1273,13 @@ static void balloon_up(struct work_struc avail_pages =si_mem_available (); floor =compute_balloon_floor (); -/* Refuse to balloon below the floor, keep the 2M granularity. */ +/* Refuse to balloon below the floor. */ if (avail_pages < num_pages || avail_pages - num_pages < floor) {pr_warn ("Balloon request will be partially fulfilled. %s\n" , avail_pages < num_pages ?"Not enough memory." :"Balloon floor reached." ); num_pages = avail_pages > floor ? (avail_pages - floor) :0 ; - num_pages -= num_pages %PAGES_IN_2M ; }while (!done) {
Greg Kroah-Hartman
maintainerPATCH 72/195 mfd: axp20x: Mark AXP20X_VBUS_IPSOUT_MGMT as volatile
In reply to Greg Kroah-HartmanFrom: Samuel Holland <[email protected]>
commit dc91c3b6fe66a13ac76f6cb3b2100c0779cd3350 upstream.
On AXP288 and newer PMICs, bit 7 of AXP20X_VBUS_IPSOUT_MGMT can be set to prevent using the VBUS input. However, when the VBUS unplugged and plugged back in, the bit automatically resets to zero.
We need to set the register as volatile to prevent regmap from caching that bit. Otherwise, regcache will think the bit is already set and not write the register.
--- drivers/mfd/axp20x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mfd/axp20x.c +1 -1
@@ -128,7 +128,7 @@ static const struct regmap_range axp288_static const struct regmap_range axp288_volatile_ranges[] = {regmap_reg_range (AXP20X_PWR_INPUT_STATUS ,AXP288_POWER_REASON ),regmap_reg_range (AXP288_BC_GLOBAL ,AXP288_BC_GLOBAL ), -regmap_reg_range (AXP288_BC_DET_STAT ,AXP288_BC_DET_STAT ), +regmap_reg_range (AXP288_BC_DET_STAT ,AXP20X_VBUS_IPSOUT_MGMT ),regmap_reg_range (AXP20X_CHRG_BAK_CTRL ,AXP20X_CHRG_BAK_CTRL ),regmap_reg_range (AXP20X_IRQ1_EN ,AXP20X_IPSOUT_V_HIGH_L ),regmap_reg_range (AXP20X_TIMER_CTRL ,AXP20X_TIMER_CTRL ),
Greg Kroah-Hartman
maintainerPATCH 73/195 crypto: api - Check spawn->alg under lock in crypto_drop_spawn
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit 7db3b61b6bba4310f454588c2ca6faf2958ad79f upstream.
We need to check whether spawn->alg is NULL under lock as otherwise the algorithm could be removed from under us after we have checked it and found it to be non-NULL. This could cause us to remove the spawn from a non-existent list.
--- crypto/algapi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
crypto/algapi.c +2 -4
@@ -649,11 +649,9 @@ EXPORT_SYMBOL_GPL(crypto_grab_spawn);void crypto_drop_spawn (struct crypto_spawn *spawn) { -if (!spawn->alg) -return ; -down_write (&crypto_alg_sem); -list_del (&spawn->list); +if (spawn->alg) +list_del (&spawn->list);up_write (&crypto_alg_sem); }EXPORT_SYMBOL_GPL (crypto_drop_spawn);
Greg Kroah-Hartman
maintainerPATCH 74/195 crypto: ccree - fix backlog memory leak
In reply to Greg Kroah-HartmanFrom: Gilad Ben-Yossef <[email protected]>
commit 4df2ef25b3b3618fd708ab484fe6239abd130fec upstream.
Fix brown paper bag bug of not releasing backlog list item buffer when backlog was consumed causing a memory leak when backlog is used.
--- drivers/crypto/ccree/cc_request_mgr.c | 1 + 1 file changed, 1 insertion(+)
drivers/crypto/ccree/cc_request_mgr.c +1 -0
@@ -403,6 +403,7 @@ static void cc_proc_backlog(struct cc_drspin_lock (&mgr->bl_lock);list_del (&bli->list); --mgr->bl_len; +kfree (bli); }spin_unlock (&mgr->bl_lock);
Greg Kroah-Hartman
maintainerPATCH 75/195 crypto: ccree - fix pm wrongful error reporting
In reply to Greg Kroah-HartmanFrom: Gilad Ben-Yossef <[email protected]>
commit cedca59fae5834af8445b403c66c9953754375d7 upstream.
pm_runtime_get_sync() can return 1 as a valid (none error) return code. Treat it as such.
--- drivers/crypto/ccree/cc_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/ccree/cc_pm.c +1 -1
@@ -82,7 +82,7 @@ int cc_pm_get(struct device *dev)else pm_runtime_get_noresume (dev); -return rc; +return (rc ==1 ?0 : rc); }int cc_pm_put_suspend (struct device *dev)
Greg Kroah-Hartman
maintainerPATCH 76/195 crypto: ccree - fix PM race condition
In reply to Greg Kroah-HartmanFrom: Gilad Ben-Yossef <[email protected]>
commit 15fd2566bf54ee4d4781d8f170acfc9472a1541f upstream.
The PM code was racy, possibly causing the driver to submit requests to a powered down device. Fix the race and while at it simplify the PM code.
--- drivers/crypto/ccree/cc_driver.h | 1 drivers/crypto/ccree/cc_pm.c | 28 ++++--------------- drivers/crypto/ccree/cc_request_mgr.c | 50 ---------------------------------- drivers/crypto/ccree/cc_request_mgr.h | 8 ----- 4 files changed, 7 insertions(+), 80 deletions(-)
drivers/crypto/ccree/cc_driver.h +1 -0
@@ -131,6 +131,7 @@ struct cc_drvdata {u32 axim_mon_offset;u32 sig_offset;u32 ver_offset; +bool pm_on; };struct cc_crypto_alg {
drivers/crypto/ccree/cc_pm.c +6 -22
@@ -23,14 +23,8 @@ const struct dev_pm_ops ccree_pm = {int cc_pm_suspend (struct device *dev) {struct cc_drvdata *drvdata =dev_get_drvdata (dev); -int rc;dev_dbg (dev,"set HOST_POWER_DOWN_EN\n" ); - rc =cc_suspend_req_queue (drvdata); -if (rc) { -dev_err (dev,"cc_suspend_req_queue (%x)\n" , rc); -return rc; - }fini_cc_regs (drvdata);cc_iowrite (drvdata,CC_REG (HOST_POWER_DOWN_EN ),POWER_DOWN_ENABLE );cc_clk_off (drvdata);
@@ -59,13 +53,6 @@ int cc_pm_resume(struct device *dev)/* check if tee fips error occurred during power down */ cc_tee_handle_fips_error (drvdata); - rc =cc_resume_req_queue (drvdata); -if (rc) { -dev_err (dev,"cc_resume_req_queue (%x)\n" , rc); -return rc; - } - -/* must be after the queue resuming as it uses the HW queue*/ cc_init_hash_sram (drvdata);cc_init_iv_sram (drvdata);
@@ -77,10 +64,8 @@ int cc_pm_get(struct device *dev)int rc =0 ;struct cc_drvdata *drvdata =dev_get_drvdata (dev); -if (cc_req_queue_suspended (drvdata)) +if (drvdata->pm_on) rc =pm_runtime_get_sync (dev); -else -pm_runtime_get_noresume (dev);return (rc ==1 ?0 : rc); }
@@ -90,14 +75,11 @@ int cc_pm_put_suspend(struct device *devint rc =0 ;struct cc_drvdata *drvdata =dev_get_drvdata (dev); -if (!cc_req_queue_suspended (drvdata)) { +if (drvdata->pm_on) {pm_runtime_mark_last_busy (dev); rc =pm_runtime_put_autosuspend (dev); - }else { -/* Something wrong happens*/ -dev_err (dev,"request to suspend already suspended queue" ); - rc = -EBUSY ; } +return rc; }
@@ -108,7 +90,7 @@ int cc_pm_init(struct cc_drvdata *drvdat/* must be before the enabling to avoid resdundent suspending */ pm_runtime_set_autosuspend_delay (dev,CC_SUSPEND_TIMEOUT );pm_runtime_use_autosuspend (dev); -/* activate the PM module */ +/* set us as active - note we won't do PM ops until cc_pm_go()! */ return pm_runtime_set_active (dev); }
@@ -116,9 +98,11 @@ int cc_pm_init(struct cc_drvdata *drvdatvoid cc_pm_go (struct cc_drvdata *drvdata) {pm_runtime_enable (drvdata_to_dev (drvdata)); + drvdata->pm_on = true; }void cc_pm_fini (struct cc_drvdata *drvdata) {pm_runtime_disable (drvdata_to_dev (drvdata)); + drvdata->pm_on = false; }
drivers/crypto/ccree/cc_request_mgr.c +0 -50
59 lines not on this page · raw message
drivers/crypto/ccree/cc_request_mgr.h +0 -8
@@ -40,12 +40,4 @@ void complete_request(struct cc_drvdatavoid cc_req_mgr_fini (struct cc_drvdata *drvdata); -#if defined(CONFIG_PM ) -int cc_resume_req_queue (struct cc_drvdata *drvdata); - -int cc_suspend_req_queue (struct cc_drvdata *drvdata); - -bool cc_req_queue_suspended (struct cc_drvdata *drvdata); -#endif -#endif /*__REQUEST_MGR_H__*/
Greg Kroah-Hartman
maintainerPATCH 77/195 scripts/find-unused-docs: Fix massive false positives
In reply to Greg Kroah-HartmanFrom: Geert Uytterhoeven <[email protected]>
commit 1630146db2111412e7524d05d812ff8f2c75977e upstream.
scripts/find-unused-docs.sh invokes scripts/kernel-doc to find out if a source file contains kerneldoc or not.
However, as it passes the no longer supported "-text" option to scripts/kernel-doc, the latter prints out its help text, causing all files to be considered containing kerneldoc.
Get rid of these false positives by removing the no longer supported "-text" option from the scripts/kernel-doc invocation.
--- scripts/find-unused-docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
scripts/find-unused-docs.sh +1 -1
@@ -54,7 +54,7 @@ for file in `find $1 -name '*.c'`; do if [[ ${FILES_INCLUDED[$file]+_} ]]; then continue; fi - str=$(scripts/kernel-doc -text -export "$file" 2>/dev/null) + str=$(scripts/kernel-doc -export "$file" 2>/dev/null) if [[ -n "$str" ]]; then echo "$file" fi
Greg Kroah-Hartman
maintainerPATCH 78/195 scsi: qla2xxx: Fix mtcp dump collection failure
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 641e0efddcbde52461e017136acd3ce7f2ef0c14 upstream.
MTCP dump failed due to MB Reg 10 was picking garbage data from stack memory.
--- drivers/scsi/qla2xxx/qla_mbx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/scsi/qla2xxx/qla_mbx.c +1 -2
@@ -5994,9 +5994,8 @@ qla2x00_dump_mctp_data(scsi_qla_host_t * mcp->mb[7 ] =LSW (MSD (req_dma)); mcp->mb[8 ] =MSW (addr);/* Setting RAM ID to valid */ - mcp->mb[10 ] |=BIT_7 ;/* For MCTP RAM ID is 0x40 */ - mcp->mb[10 ] |=0x40 ; + mcp->mb[10 ] =BIT_7 |0x40 ; mcp->out_mb |=MBX_10 |MBX_8 |MBX_7 |MBX_6 |MBX_5 |MBX_4 |MBX_3 |MBX_2 |MBX_1 |MBX_0 ;
Greg Kroah-Hartman
maintainerPATCH 79/195 power: supply: ltc2941-battery-gauge: fix use-after-free
In reply to Greg Kroah-HartmanFrom: Sven Van Asbroeck <[email protected]>
commit a60ec78d306c6548d4adbc7918b587a723c555cc upstream.
This driver's remove path calls cancel_delayed_work(). However, that function does not wait until the work function finishes. This could mean that the work function is still running after the driver's remove function has finished, which would result in a use-after-free.
Fix by calling cancel_delayed_work_sync(), which ensures that that the work is properly cancelled, no longer running, and unable to re-schedule itself.
This issue was detected with the help of Coccinelle.
--- drivers/power/supply/ltc2941-battery-gauge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/ltc2941-battery-gauge.c +1 -1
@@ -448,7 +448,7 @@ static int ltc294x_i2c_remove(struct i2c {struct ltc294x_info *info =i2c_get_clientdata (client); -cancel_delayed_work (&info->work); +cancel_delayed_work_sync (&info->work);power_supply_unregister (info->supply);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 80/195 ovl: fix wrong WARN_ON() in ovl_cache_update_ino()
In reply to Greg Kroah-HartmanFrom: Amir Goldstein <[email protected]>
commit 4c37e71b713ecffe81f8e6273c6835e54306d412 upstream.
The WARN_ON() that child entry is always on overlay st_dev became wrong when we allowed this function to update d_ino in non-samefs setup with xino enabled.
It is not true in case of xino bits overflow on a non-dir inode. Leave the WARN_ON() only for directories, where assertion is still true.
--- fs/overlayfs/readdir.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
fs/overlayfs/readdir.c +7 -1
@@ -507,7 +507,13 @@ get:if (err) goto fail; -WARN_ON_ONCE (dir->d_sb->s_dev != stat.dev); +/* +* Directory inode is always on overlay st_dev. +* Non-dir with ovl_same_dev() could be on pseudo st_dev in case +* of xino bits overflow. +*/ +WARN_ON_ONCE (S_ISDIR (stat.mode) && + dir->d_sb->s_dev != stat.dev); ino = stat.ino; }else if (xinobits && !OVL_TYPE_UPPER (type)) { ino = ovl_remap_lower_ino(ino, xinobits,
Greg Kroah-Hartman
maintainerPATCH 81/195 f2fs: choose hardlimit when softlimit is larger than hardlimit in f2fs_statfs_project()
In reply to Greg Kroah-HartmanFrom: Chengguang Xu <[email protected]>
commit 909110c060f22e65756659ec6fa957ae75777e00 upstream.
Setting softlimit larger than hardlimit seems meaningless for disk quota but currently it is allowed. In this case, there may be a bit of comfusion for users when they run df comamnd to directory which has project quota.
For example, we set 20M softlimit and 10M hardlimit of block usage limit for project quota of test_dir(project id 123).
[root@hades f2fs]# repquota -P -a
--- fs/f2fs/super.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
fs/f2fs/super.c +14 -6
@@ -1148,9 +1148,13 @@ static int f2fs_statfs_project(struct sureturn PTR_ERR (dquot);spin_lock (&dquot->dq_dqb_lock); - limit = (dquot->dq_dqb.dqb_bsoftlimit ? - dquot->dq_dqb.dqb_bsoftlimit : - dquot->dq_dqb.dqb_bhardlimit) >> sb->s_blocksize_bits; + limit =0 ; +if (dquot->dq_dqb.dqb_bsoftlimit) + limit = dquot->dq_dqb.dqb_bsoftlimit; +if (dquot->dq_dqb.dqb_bhardlimit && + (!limit || dquot->dq_dqb.dqb_bhardlimit < limit)) + limit = dquot->dq_dqb.dqb_bhardlimit; +if (limit && buf->f_blocks > limit) { curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits; buf->f_blocks = limit;
@@ -1159,9 +1163,13 @@ static int f2fs_statfs_project(struct su (buf->f_blocks - curblock) : 0; } - limit = dquot->dq_dqb.dqb_isoftlimit ? - dquot->dq_dqb.dqb_isoftlimit : - dquot->dq_dqb.dqb_ihardlimit; + limit =0 ; +if (dquot->dq_dqb.dqb_isoftlimit) + limit = dquot->dq_dqb.dqb_isoftlimit; +if (dquot->dq_dqb.dqb_ihardlimit && + (!limit || dquot->dq_dqb.dqb_ihardlimit < limit)) + limit = dquot->dq_dqb.dqb_ihardlimit; +if (limit && buf->f_files > limit) { buf->f_files = limit; buf->f_ffree =
Greg Kroah-Hartman
maintainerPATCH 82/195 f2fs: fix miscounted block limit in f2fs_statfs_project()
In reply to Greg Kroah-HartmanFrom: Chengguang Xu <[email protected]>
commit acdf2172172a511f97fa21ed0ee7609a6d3b3a07 upstream.
statfs calculates Total/Used/Avail disk space in block unit, so we should translate soft/hard prjquota limit to block unit as well.
Below testing result shows the block/inode numbers of Total/Used/Avail from df command are all correct afer applying this patch.
[root@localhost quota-tools]\# ./repquota -P /dev/sdb1
--- fs/f2fs/super.c | 2 ++ 1 file changed, 2 insertions(+)
fs/f2fs/super.c +2 -0
@@ -1154,6 +1154,8 @@ static int f2fs_statfs_project(struct suif (dquot->dq_dqb.dqb_bhardlimit && (!limit || dquot->dq_dqb.dqb_bhardlimit < limit)) limit = dquot->dq_dqb.dqb_bhardlimit; +if (limit) + limit >>= sb->s_blocksize_bits;if (limit && buf->f_blocks > limit) { curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits;
Greg Kroah-Hartman
maintainerPATCH 83/195 f2fs: code cleanup for f2fs_statfs_project()
In reply to Greg Kroah-HartmanFrom: Chengguang Xu <[email protected]>
commit bf2cbd3c57159c2b639ee8797b52ab5af180bf83 upstream.
Calling min_not_zero() to simplify complicated prjquota limit comparison in f2fs_statfs_project().
--- fs/f2fs/super.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-)
fs/f2fs/super.c +4 -12
@@ -1148,12 +1148,8 @@ static int f2fs_statfs_project(struct sureturn PTR_ERR (dquot);spin_lock (&dquot->dq_dqb_lock); - limit =0 ; -if (dquot->dq_dqb.dqb_bsoftlimit) - limit = dquot->dq_dqb.dqb_bsoftlimit; -if (dquot->dq_dqb.dqb_bhardlimit && - (!limit || dquot->dq_dqb.dqb_bhardlimit < limit)) - limit = dquot->dq_dqb.dqb_bhardlimit; + limit =min_not_zero (dquot->dq_dqb.dqb_bsoftlimit, + dquot->dq_dqb.dqb_bhardlimit);if (limit) limit >>= sb->s_blocksize_bits;
@@ -1165,12 +1161,8 @@ static int f2fs_statfs_project(struct su (buf->f_blocks - curblock) : 0; } - limit =0 ; -if (dquot->dq_dqb.dqb_isoftlimit) - limit = dquot->dq_dqb.dqb_isoftlimit; -if (dquot->dq_dqb.dqb_ihardlimit && - (!limit || dquot->dq_dqb.dqb_ihardlimit < limit)) - limit = dquot->dq_dqb.dqb_ihardlimit; + limit =min_not_zero (dquot->dq_dqb.dqb_isoftlimit, + dquot->dq_dqb.dqb_ihardlimit);if (limit && buf->f_files > limit) { buf->f_files = limit;
Greg Kroah-Hartman
maintainerPATCH 84/195 PM: core: Fix handling of devices deleted during system-wide resume
In reply to Greg Kroah-HartmanFrom: Rafael J. Wysocki <[email protected]>
commit 0552e05fdfea191a2cf3a0abd33574b5ef9ca818 upstream.
If a device is deleted by one of its system-wide resume callbacks (for example, because it does not appear to be present or accessible any more) along with its children, the resume of the children may continue leading to use-after-free errors and other issues (potentially).
Namely, if the device's children are resumed asynchronously, their resume may have been scheduled already before the device's callback runs and so the device may be deleted while dpm_wait_for_superior() is being executed for them. The memory taken up by the parent device object may be freed then while dpm_wait() is waiting for the parent's resume callback to complete, which leads to a use-after-free. Moreover, the resume of the children is really not expected to continue after they have been unregistered, so it must be terminated right away in that case.
To address this problem, modify dpm_wait_for_superior() to check if the target device is still there in the system-wide PM list of devices and if so, to increment its parent's reference counter, both under dpm_list_mtx which prevents device_del() running for the child from dropping the parent's reference counter prematurely.
If the device is not present in the system-wide PM list of devices any more, the resume of it cannot continue, so check that again after dpm_wait() returns, which means that the parent's callback has been completed, and pass the result of that check to the caller of dpm_wait_for_superior() to allow it to abort the device's resume if it is not there any more.
--- drivers/base/power/main.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-)
drivers/base/power/main.c +37 -5
@@ -265,10 +265,38 @@ static void dpm_wait_for_suppliers(strucdevice_links_read_unlock (idx); } -static void dpm_wait_for_superior (struct device *dev,bool async) +static bool dpm_wait_for_superior (struct device *dev,bool async) { -dpm_wait (dev->parent, async); +struct device *parent; + +/* +* If the device is resumed asynchronously and the parent's callback +* deletes both the device and the parent itself, the parent object may +* be freed while this function is running, so avoid that by reference +* counting the parent once more unless the device has been deleted +* already (in which case return right away). +*/ +mutex_lock (&dpm_list_mtx); + +if (!device_pm_initialized (dev)) { +mutex_unlock (&dpm_list_mtx); +return false; + } + + parent =get_device (dev->parent); + +mutex_unlock (&dpm_list_mtx); + +dpm_wait (parent, async); +put_device (parent); +dpm_wait_for_suppliers (dev, async); + +/* +* If the parent's callback has deleted the device, attempting to resume +* it would be invalid, so avoid doing that then. +*/ +return device_pm_initialized (dev); }static void dpm_wait_for_consumers (struct device *dev,bool async)
@@ -628,7 +656,8 @@ static int device_resume_noirq(struct deif (!dev->power.is_noirq_suspended) goto Out; -dpm_wait_for_superior (dev, async); +if (!dpm_wait_for_superior (dev, async)) + goto Out; skip_resume =dev_pm_may_skip_resume (dev);
@@ -829,7 +858,8 @@ static int device_resume_early(struct deif (!dev->power.is_late_suspended) goto Out; -dpm_wait_for_superior (dev, async); +if (!dpm_wait_for_superior (dev, async)) + goto Out; callback =dpm_subsys_resume_early_cb (dev, state, &info);
@@ -949,7 +979,9 @@ static int device_resume(struct device * goto Complete; } -dpm_wait_for_superior (dev, async); +if (!dpm_wait_for_superior (dev, async)) + goto Complete; +dpm_watchdog_set (&wd, dev);device_lock (dev);
Greg Kroah-Hartman
maintainerPATCH 85/195 of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit dabf6b36b83a18d57e3d4b9d50544ed040d86255 upstream.
There's an OF helper called of_dma_is_coherent(), which checks if a device has a "dma-coherent" property to see if the device is coherent for DMA.
But on some platforms devices are coherent by default, and on some platforms it's not possible to update existing device trees to add the "dma-coherent" property.
So add a Kconfig symbol to allow arch code to tell of_dma_is_coherent() that devices are coherent by default, regardless of the presence of the property.
Select that symbol on powerpc when NOT_COHERENT_CACHE is not set, ie. when the system has a coherent cache.
--- arch/powerpc/Kconfig | 1 + drivers/of/Kconfig | 4 ++++ drivers/of/address.c | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-)
arch/powerpc/Kconfig +1 -0
@@ -230,6 +230,7 @@ config PPC select NEED_SG_DMA_LENGTH select NO_BOOTMEM select OF + select OF_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE select OF_EARLY_FLATTREE select OF_RESERVED_MEM select OLD_SIGACTION if PPC32
drivers/of/Kconfig +4 -0
@@ -103,4 +103,8 @@ config OF_OVERLAY config OF_NUMA bool +config OF_DMA_DEFAULT_COHERENT + # arches should select this if DMA is coherent by default for OF devices + bool + endif # OF
drivers/of/address.c +5 -1
@@ -970,12 +970,16 @@ EXPORT_SYMBOL_GPL(of_dma_get_range);* @np: device node * * It returns true if "dma-coherent" property was found -* for this device in DT. +* for this device in the DT, or if DMA is coherent by +* default for OF devices on the current platform. */ bool of_dma_is_coherent (struct device_node *np) {struct device_node *node =of_node_get (np); +if (IS_ENABLED (CONFIG_OF_DMA_DEFAULT_COHERENT )) +return true; +while (node) {if (of_property_read_bool (node,"dma-coherent" )) {of_node_put (node);
Greg Kroah-Hartman
maintainerPATCH 86/195 dm zoned: support zone sizes smaller than 128MiB
In reply to Greg Kroah-HartmanFrom: Dmitry Fomichev <[email protected]>
commit b39962950339912978484cdac50069258545d753 upstream.
dm-zoned is observed to log failed kernel assertions and not work correctly when operating against a device with a zone size smaller than 128MiB (e.g. 32768 bits per 4K block). The reason is that the bitmap size per zone is calculated as zero with such a small zone size. Fix this problem and also make the code related to zone bitmap management be able to handle per zone bitmaps smaller than a single block.
A dm-zoned-tools patch is required to properly format dm-zoned devices with zone sizes smaller than 128MiB.
--- drivers/md/dm-zoned-metadata.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
drivers/md/dm-zoned-metadata.c +14 -9
@@ -132,6 +132,7 @@ struct dmz_metadata {sector_t zone_bitmap_size;unsigned int zone_nr_bitmap_blocks; +unsigned int zone_bits_per_mblk;unsigned int nr_bitmap_blocks;unsigned int nr_map_blocks;
@@ -1165,7 +1166,10 @@ static int dmz_init_zones(struct dmz_met/* Init */ zmd->zone_bitmap_size = dev->zone_nr_blocks >>3 ; - zmd->zone_nr_bitmap_blocks = zmd->zone_bitmap_size >>DMZ_BLOCK_SHIFT ; + zmd->zone_nr_bitmap_blocks = +max_t (sector_t,1 , zmd->zone_bitmap_size >>DMZ_BLOCK_SHIFT ); + zmd->zone_bits_per_mblk =min_t (sector_t, dev->zone_nr_blocks, +DMZ_BLOCK_SIZE_BITS );/* Allocate zone array */ zmd->zones =kcalloc (dev->nr_zones,sizeof (struct dm_zone ),GFP_KERNEL );
@@ -1982,7 +1986,7 @@ int dmz_copy_valid_blocks(struct dmz_metdmz_release_mblock (zmd, to_mblk);dmz_release_mblock (zmd, from_mblk); - chunk_block +=DMZ_BLOCK_SIZE_BITS ; + chunk_block += zmd->zone_bits_per_mblk; } to_zone->weight = from_zone->weight;
@@ -2043,7 +2047,7 @@ int dmz_validate_blocks(struct dmz_metad/* Set bits */ bit = chunk_block &DMZ_BLOCK_MASK_BITS ; - nr_bits =min (nr_blocks,DMZ_BLOCK_SIZE_BITS - bit); + nr_bits =min (nr_blocks, zmd->zone_bits_per_mblk - bit); count =dmz_set_bits ((unsigned long *)mblk->data, bit, nr_bits);if (count) {
@@ -2122,7 +2126,7 @@ int dmz_invalidate_blocks(struct dmz_met/* Clear bits */ bit = chunk_block &DMZ_BLOCK_MASK_BITS ; - nr_bits =min (nr_blocks,DMZ_BLOCK_SIZE_BITS - bit); + nr_bits =min (nr_blocks, zmd->zone_bits_per_mblk - bit); count =dmz_clear_bits ((unsigned long *)mblk->data, bit, nr_bits);
@@ -2182,6 +2186,7 @@ static int dmz_to_next_set_block(struct {struct dmz_mblock *mblk;unsigned int bit, set_bit, nr_bits; +unsigned int zone_bits = zmd->zone_bits_per_mblk;unsigned long *bitmap;int n =0 ;
@@ -2196,15 +2201,15 @@ static int dmz_to_next_set_block(struct/* Get offset */ bitmap = (unsigned long *) mblk->data; bit = chunk_block &DMZ_BLOCK_MASK_BITS ; - nr_bits =min (nr_blocks,DMZ_BLOCK_SIZE_BITS - bit); + nr_bits =min (nr_blocks, zone_bits - bit);if (set) - set_bit =find_next_bit (bitmap,DMZ_BLOCK_SIZE_BITS , bit); + set_bit =find_next_bit (bitmap, zone_bits, bit);else - set_bit =find_next_zero_bit (bitmap,DMZ_BLOCK_SIZE_BITS , bit); + set_bit =find_next_zero_bit (bitmap, zone_bits, bit);dmz_release_mblock (zmd, mblk); n += set_bit - bit; -if (set_bit <DMZ_BLOCK_SIZE_BITS ) +if (set_bit < zone_bits)break ; nr_blocks -= nr_bits;
@@ -2307,7 +2312,7 @@ static void dmz_get_zone_weight(struct d/* Count bits in this block */ bitmap = mblk->data; bit = chunk_block &DMZ_BLOCK_MASK_BITS ; - nr_bits =min (nr_blocks,DMZ_BLOCK_SIZE_BITS - bit); + nr_bits =min (nr_blocks, zmd->zone_bits_per_mblk - bit); n +=dmz_count_bits (bitmap, bit, nr_bits);dmz_release_mblock (zmd, mblk);
Greg Kroah-Hartman
maintainerPATCH 87/195 dm space map common: fix to ensure new block isnt already in use
In reply to Greg Kroah-HartmanFrom: Joe Thornber <[email protected]>
commit 4feaef830de7ffdd8352e1fe14ad3bf13c9688f8 upstream.
The space-maps track the reference counts for disk blocks allocated by both the thin-provisioning and cache targets. There are variants for tracking metadata blocks and data blocks.
Transactionality is implemented by never touching blocks from the previous transaction, so we can rollback in the event of a crash.
When allocating a new block we need to ensure the block is free (has reference count of 0) in both the current and previous transaction. Prior to this fix we were doing this by searching for a free block in the previous transaction, and relying on a 'begin' counter to track where the last allocation in the current transaction was. This 'begin' field was not being updated in all code paths (eg, increment of a data block reference count due to breaking sharing of a neighbour block in the same btree leaf).
This fix keeps the 'begin' field, but now it's just a hint to speed up the search. Instead the current transaction is searched for a free block, and then the old transaction is double checked to ensure it's free. Much simpler.
This fixes reports of sm_disk_new_block()'s BUG_ON() triggering when DM thin-provisioning's snapshots are heavily used.
--- drivers/md/persistent-data/dm-space-map-common.c | 27 +++++++++++++++++++++ drivers/md/persistent-data/dm-space-map-common.h | 2 + drivers/md/persistent-data/dm-space-map-disk.c | 6 +++- drivers/md/persistent-data/dm-space-map-metadata.c | 5 +++ 4 files changed, 37 insertions(+), 3 deletions(-)
drivers/md/persistent-data/dm-space-map-common.c +27 -0
@@ -382,6 +382,33 @@ int sm_ll_find_free_block(struct ll_diskreturn -ENOSPC ; } +int sm_ll_find_common_free_block (struct ll_disk *old_ll,struct ll_disk *new_ll, +dm_block_t begin,dm_block_t end,dm_block_t *b) +{ +int r; +uint32_t count; + +do { + r =sm_ll_find_free_block (new_ll, begin, new_ll->nr_blocks, b); +if (r) +break ; + +/* double check this block wasn't used in the old transaction */ +if (*b >= old_ll->nr_blocks) + count =0 ; +else { + r =sm_ll_lookup (old_ll, *b, &count); +if (r) +break ; + +if (count) + begin = *b +1 ; + } + }while (count); + +return r; +} +static int sm_ll_mutate (struct ll_disk *ll,dm_block_t b,int (*mutator)(void *context,uint32_t old,uint32_t *new),void *context,enum allocation_event *ev)
drivers/md/persistent-data/dm-space-map-common.h +2 -0
@@ -109,6 +109,8 @@ int sm_ll_lookup_bitmap(struct ll_disk *int sm_ll_lookup (struct ll_disk *ll,dm_block_t b,uint32_t *result);int sm_ll_find_free_block (struct ll_disk *ll,dm_block_t begin,dm_block_t end,dm_block_t *result); +int sm_ll_find_common_free_block (struct ll_disk *old_ll,struct ll_disk *new_ll, +dm_block_t begin,dm_block_t end,dm_block_t *result);int sm_ll_insert (struct ll_disk *ll,dm_block_t b,uint32_t ref_count,enum allocation_event *ev);int sm_ll_inc (struct ll_disk *ll,dm_block_t b,enum allocation_event *ev);int sm_ll_dec (struct ll_disk *ll,dm_block_t b,enum allocation_event *ev);
drivers/md/persistent-data/dm-space-map-disk.c +4 -2
@@ -167,8 +167,10 @@ static int sm_disk_new_block(struct dm_senum allocation_event ev; struct sm_disk *smd = container_of(sm, struct sm_disk, sm); -/* FIXME: we should loop round a couple of times */ - r =sm_ll_find_free_block (&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b); +/* +* Any block we allocate has to be free in both the old and current ll. +*/ + r =sm_ll_find_common_free_block (&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b);if (r)return r;
drivers/md/persistent-data/dm-space-map-metadata.c +4 -1
@@ -448,7 +448,10 @@ static int sm_metadata_new_block_(structenum allocation_event ev; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); - r =sm_ll_find_free_block (&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b); +/* +* Any block we allocate has to be free in both the old and current ll. +*/ + r =sm_ll_find_common_free_block (&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b);if (r)return r;
Greg Kroah-Hartman
maintainerPATCH 88/195 dm crypt: fix benbi IV constructor crash if used in authenticated mode
In reply to Greg Kroah-HartmanFrom: Milan Broz <[email protected]>
commit 4ea9471fbd1addb25a4d269991dc724e200ca5b5 upstream.
If benbi IV is used in AEAD construction, for example:
cryptsetup luksFormat <device> --cipher twofish-xts-benbi --key-size 512 --integrity=hmac-sha256
the constructor uses wrong skcipher function and crashes:
BUG: kernel NULL pointer dereference, address: 00000014 ... EIP: crypt_iv_benbi_ctr+0x15/0x70 [dm_crypt] Call Trace: ? crypt_subkey_size+0x20/0x20 [dm_crypt] crypt_ctr+0x567/0xfc0 [dm_crypt] dm_table_add_target+0x15f/0x340 [dm_mod]
Fix this by properly using crypt_aead_blocksize() in this case.
--- drivers/md/dm-crypt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/md/dm-crypt.c +8 -2
@@ -482,8 +482,14 @@ static int crypt_iv_essiv_gen(struct crystatic int crypt_iv_benbi_ctr (struct crypt_config *cc,struct dm_target *ti,const char *opts) { -unsigned bs =crypto_skcipher_blocksize (any_tfm (cc)); -int log =ilog2 (bs); +unsigned bs; +int log; + +if (test_bit (CRYPT_MODE_INTEGRITY_AEAD , &cc->cipher_flags)) + bs =crypto_aead_blocksize (any_tfm_aead (cc)); +else + bs =crypto_skcipher_blocksize (any_tfm (cc)); + log =ilog2 (bs);/* we need to calculate how far we must shift the sector count * to get the cipher block count, we use this shift in _gen */
Greg Kroah-Hartman
maintainerPATCH 89/195 dm: fix potential for q->make_request_fn NULL pointer
In reply to Greg Kroah-HartmanFrom: Mike Snitzer <[email protected]>
commit 47ace7e012b9f7ad71d43ac9063d335ea3d6820b upstream.
Move blk_queue_make_request() to dm.c:alloc_dev() so that q->make_request_fn is never NULL during the lifetime of a DM device (even one that is created without a DM table).
Otherwise generic_make_request() will crash simply by doing:
dmsetup create -n test
mount /dev/dm-N /mnt
While at it, move ->congested_data initialization out of dm.c:alloc_dev() and into the bio-based specific init method.
Depends-on: c12c9a3c3860c ("dm: various cleanups to md->queue initialization code")
--- drivers/md/dm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/md/dm.c +7 -2
@@ -1819,6 +1819,7 @@ static void dm_init_normal_md_queue(stru/* * Initialize aspects of queue that aren't relevant for blk-mq */ + md->queue->backing_dev_info->congested_data = md; md->queue->backing_dev_info->congested_fn = dm_any_congested; }
@@ -1913,7 +1914,12 @@ static struct mapped_device *alloc_dev(iif (!md->queue) goto bad; md->queue->queuedata = md; - md->queue->backing_dev_info->congested_data = md; +/* +* default to bio-based required ->make_request_fn until DM +* table is loaded and md->type established. If request-based +* table is loaded: blk-mq will override accordingly. +*/ +blk_queue_make_request (md->queue, dm_make_request); md->disk =alloc_disk_node (1 , md->numa_node_id);if (!md->disk)
@@ -2242,7 +2248,6 @@ int dm_setup_md_queue(struct mapped_devicase DM_TYPE_BIO_BASED :case DM_TYPE_DAX_BIO_BASED :dm_init_normal_md_queue (md); -blk_queue_make_request (md->queue, dm_make_request);break ;case DM_TYPE_NVME_BIO_BASED :dm_init_normal_md_queue (md);
Greg Kroah-Hartman
maintainerPATCH 90/195 dm writecache: fix incorrect flush sequence when doing SSD mode commit
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
commit aa9509209c5ac2f0b35d01a922bf9ae072d0c2fc upstream.
When committing state, the function writecache_flush does the following:
1. write metadata (writecache_commit_flushed)
2. flush disk cache (writecache_commit_flushed)
3. wait for data writes to complete (writecache_wait_for_ios)
4. increase superblock seq_count
5. write the superblock
6. flush disk cache
It may happen that at step 3, when we wait for some write to finish, the disk may report the write as finished, but the write only hit the disk cache and it is not yet stored in persistent storage. At step 5 we write the superblock - it may happen that the superblock is written before the write that we waited for in step 3. If the machine crashes, it may result in incorrect data being returned after reboot.
In order to fix the bug, we must swap steps 2 and 3 in the above sequence, so that we first wait for writes to complete and then flush the disk cache.
--- drivers/md/dm-writecache.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-)
drivers/md/dm-writecache.c +21 -20
@@ -447,7 +447,13 @@ static void writecache_notify_io(unsignecomplete (&endio->c); } -static void ssd_commit_flushed (struct dm_writecache *wc) +static void writecache_wait_for_ios (struct dm_writecache *wc,int direction) +{ +wait_event (wc->bio_in_progress_wait[direction], + !atomic_read (&wc->bio_in_progress[direction])); +} + +static void ssd_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {struct dm_io_region region;struct dm_io_request req;
@@ -493,17 +499,20 @@ static void ssd_commit_flushed(struct dmwritecache_notify_io (0 , &endio);wait_for_completion_io (&endio.c); +if (wait_for_ios) +writecache_wait_for_ios (wc,WRITE ); +writecache_disk_flush (wc, wc->ssd_dev);memset (wc->dirty_bitmap,0 , wc->dirty_bitmap_size); } -static void writecache_commit_flushed (struct dm_writecache *wc) +static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc))wmb ();else -ssd_commit_flushed (wc); +ssd_commit_flushed (wc, wait_for_ios); }static void writecache_disk_flush (struct dm_writecache *wc,struct dm_dev *dev)
@@ -527,12 +536,6 @@ static void writecache_disk_flush(structwritecache_error (wc, r,"error flushing metadata: %d" , r); } -static void writecache_wait_for_ios (struct dm_writecache *wc,int direction) -{ -wait_event (wc->bio_in_progress_wait[direction], - !atomic_read (&wc->bio_in_progress[direction])); -} -#define WFE_RETURN_FOLLOWING 1#define WFE_LOWEST_SEQ 2
@@ -730,14 +733,12 @@ static void writecache_flush(struct dm_w e = e2;cond_resched (); } -writecache_commit_flushed (wc); - -writecache_wait_for_ios (wc,WRITE ); +writecache_commit_flushed (wc, true); wc->seq_count++;pmem_assign (sb (wc)->seq_count,cpu_to_le64 (wc->seq_count));writecache_flush_region (wc, &sb (wc)->seq_count,sizeof sb (wc)->seq_count); -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false); wc->overwrote_committed = false;
@@ -761,7 +762,7 @@ static void writecache_flush(struct dm_w }if (need_flush_after_free) -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false); }static void writecache_flush_work (struct work_struct *work)
@@ -814,7 +815,7 @@ static void writecache_discard(struct dm }if (discarded_something) -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false); }static bool writecache_wait_for_writeback (struct dm_writecache *wc)
@@ -963,7 +964,7 @@ erase_this:if (need_flush) {writecache_flush_all_metadata (wc); -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false); }wc_unlock (wc);
@@ -1347,7 +1348,7 @@ static void __writecache_endio_pmem(stru wc->writeback_size--; n_walked++;if (unlikely (n_walked >=ENDIO_LATENCY )) { -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false);wc_unlock (wc);wc_lock (wc); n_walked =0 ;
@@ -1428,7 +1429,7 @@ pop_from_list:writecache_wait_for_ios (wc,READ ); } -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false);wc_unlock (wc); }
@@ -1759,10 +1760,10 @@ static int init_memory(struct dm_writecawrite_original_sector_seq_count (wc, &wc->entries[b],-1 ,-1 );writecache_flush_all_metadata (wc); -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false);pmem_assign (sb (wc)->magic,cpu_to_le32 (MEMORY_SUPERBLOCK_MAGIC ));writecache_flush_region (wc, &sb (wc)->magic,sizeof sb (wc)->magic); -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 91/195 padata: Remove broken queue flushing
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
[ Upstream commit 07928d9bfc81640bab36f5190e8725894d93b659 ]
The function padata_flush_queues is fundamentally broken because it cannot force padata users to complete the request that is underway. IOW padata has to passively wait for the completion of any outstanding work.
As it stands flushing is used in two places. Its use in padata_stop is simply unnecessary because nothing depends on the queues to be flushed afterwards.
The other use in padata_replace is more substantial as we depend on it to free the old pd structure. This patch instead uses the pd->refcnt to dynamically free the pd structure once all requests are complete.
--- kernel/padata.c | 46 ++++++++++++---------------------------------- 1 file changed, 12 insertions(+), 34 deletions(-)
kernel/padata.c +12 -34
@@ -35,6 +35,8 @@#define MAX_OBJ_NUM 1000 +static void padata_free_pd (struct parallel_data *pd); +static int padata_index_to_cpu (struct parallel_data *pd,int cpu_index) {int cpu, target_cpu;
@@ -334,6 +336,7 @@ static void padata_serial_worker(struct work_struct *serial_work)struct padata_serial_queue *squeue;struct parallel_data *pd;LIST_HEAD (local_list); +int cnt;local_bh_disable (); squeue = container_of(serial_work, struct padata_serial_queue, work);
@@ -343,6 +346,8 @@ static void padata_serial_worker(struct work_struct *serial_work)list_replace_init (&squeue->serial.list, &local_list);spin_unlock (&squeue->serial.lock); + cnt =0 ; +while (!list_empty (&local_list)) {struct padata_priv *padata;
@@ -352,9 +357,12 @@ static void padata_serial_worker(struct work_struct *serial_work)list_del_init (&padata->list); padata->serial (padata); -atomic_dec (&pd->refcnt); + cnt++; }local_bh_enable (); + +if (atomic_sub_and_test (cnt, &pd->refcnt)) +padata_free_pd (pd); }/**
@@ -501,8 +509,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst,timer_setup (&pd->timer, padata_reorder_timer,0 );atomic_set (&pd->seq_nr,-1 );atomic_set (&pd->reorder_objects,0 ); -atomic_set (&pd->refcnt,0 ); - pd->pinst = pinst; +atomic_set (&pd->refcnt,1 );spin_lock_init (&pd->lock);return pd;
@@ -526,31 +533,6 @@ static void padata_free_pd(struct parallel_data *pd)kfree (pd); } -/* Flush all objects out of the padata queues. */ -static void padata_flush_queues (struct parallel_data *pd) -{ -int cpu; -struct padata_parallel_queue *pqueue; -struct padata_serial_queue *squeue; - -for_each_cpu (cpu, pd->cpumask.pcpu) { - pqueue =per_cpu_ptr (pd->pqueue, cpu); -flush_work (&pqueue->work); - } - -del_timer_sync (&pd->timer); - -if (atomic_read (&pd->reorder_objects)) -padata_reorder (pd); - -for_each_cpu (cpu, pd->cpumask.cbcpu) { - squeue =per_cpu_ptr (pd->squeue, cpu); -flush_work (&squeue->work); - } - -BUG_ON (atomic_read (&pd->refcnt) !=0 ); -} -static void __padata_start (struct padata_instance *pinst) { pinst->flags |=PADATA_INIT ;
@@ -564,10 +546,6 @@ static void __padata_stop(struct padata_instance *pinst) pinst->flags &= ~PADATA_INIT ;synchronize_rcu (); - -get_online_cpus (); -padata_flush_queues (pinst->pd); -put_online_cpus (); }/* Replace the internal control structure with a new one. */
@@ -588,8 +566,8 @@ static void padata_replace(struct padata_instance *pinst,if (!cpumask_equal (pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu)) notification_mask |=PADATA_CPU_SERIAL ; -padata_flush_queues (pd_old); -padata_free_pd (pd_old); +if (atomic_dec_and_test (&pd_old->refcnt)) +padata_free_pd (pd_old);if (notification_mask) blocking_notifier_call_chain(&pinst->cpumask_change_notifier,
Signature · 1 line
2.20.1
Re: [PATCH 4.19 091/195] padata: Remove broken queue flushing
Hi,
Quoted 73 lines · Greg Kroah-Hartman
From: Herbert Xu <[email protected]>
[ Upstream commit
07928d9bfc81640bab36f5190e8725894d93b659]The function
padata_flush_queuesis fundamentally broken because it cannot force padata users to complete the request that is underway. IOW padata has to passively wait for the completion of any outstanding work.As it stands flushing is used in two places. Its use in
padata_stopis simply unnecessary because nothing depends on the queues to be flushed afterwards.The other use in
padata_replaceis more substantial as we depend on it to free the old pd structure. This patch instead uses thepd->refcntto dynamically free the pd structure once all requests are complete.Fixes 2b73b07ab8a4 ("padata: Flush the padata queues actively")Cc <[email protected]>Signed-off-by Herbert Xu <[email protected]>Reviewed-by Daniel Jordan <[email protected]>Signed-off-by Herbert Xu <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- kernel/padata.c | 46 ++++++++++++---------------------------------- 1 file changed, 12 insertions(+), 34 deletions(-)kernel/padata.c +9
-1@@ -35,6 +35,8 @@#define MAX_OBJ_NUM 1000 +static void padata_free_pd (struct parallel_data *pd); +static int padata_index_to_cpu (struct parallel_data *pd,int cpu_index) {int cpu, target_cpu;@@ -334,6 +336,7 @@ static void padata_serial_worker(struct work_struct *serial_work)struct padata_serial_queue *squeue;struct parallel_data *pd;LIST_HEAD (local_list); +int cnt;local_bh_disable (); squeue = container_of(serial_work, struct padata_serial_queue, work);@@ -343,6 +346,8 @@ static void padata_serial_worker(struct work_struct *serial_work)list_replace_init (&squeue->serial.list, &local_list);spin_unlock (&squeue->serial.lock); + cnt =0 ; +while (!list_empty (&local_list)) {struct padata_priv *padata;@@ -352,9 +357,12 @@ static void padata_serial_worker(struct work_struct *serial_work)list_del_init (&padata->list); padata->serial (padata); -atomic_dec (&pd->refcnt); + cnt++; }local_bh_enable (); + +if (atomic_sub_and_test (cnt, &pd->refcnt)) +padata_free_pd (pd); }/**
kernel/padata.c static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst, · line 505
Quoted 5 lines
kernel/padata.c +0
-2@@ -501,8 +509,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst,timer_setup (&pd->timer, padata_reorder_timer,0 );atomic_set (&pd->seq_nr,-1 );atomic_set (&pd->reorder_objects,0 ); -atomic_set (&pd->refcnt,0 ); - pd->pinst = pinst;
This patch remove this assignment, it's cause a null-ptr-deref when using pd->pinst in padata_reorder().
[39135.886908] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 [39135.886909] Mem abort info: [39135.886910] ESR = 0x96000004 [39135.886912] Exception class = DABT (current EL), IL = 32 bits [39135.886913] SET = 0, FnV = 0 [39135.886913] EA = 0, S1PTW = 0 [39135.886914] Data abort info: [39135.886915] ISV = 0, ISS = 0x00000004 [39135.886915] CM = 0, WnR = 0 [39135.886918] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000c66d7ef5 [39135.886919] [0000000000000010] pgd=0000000000000000 [39135.886922] Internal error: Oops: 96000004 [#1] SMP [39135.897190] Modules linked in: authenc pcrypt crypto_user cfg80211 rfkill ib_isert iscsi_target_mod ib_srpt target_core_mod dm_mirror dm_region_hash rpcrdma dm_log ib_srp scsi_transport_srp sunrpc dm_mod ib_ipoib rdma_ucm ib_uverbs ib_umad ib_iser rdma_cm ib_cm iw_cm aes_ce_blk crypto_simd cryptd aes_ce_cipher hns_roce_hw_v2 ghash_ce sha2_ce sha256_arm64 hns_roce ib_core sha1_ce sbsa_gwdt hi_sfc sg mtd ipmi_ssif sch_fq_codel ip_tables realtek hclge hinic hns3 ipmi_si hisi_sas_v3_hw hibmc_drm hnae3 hisi_sas_main ipmi_devintf ipmi_msghandler [39135.997870] Process kworker/0:2 (pid: 789, stack limit = 0x0000000047f55ba6) [39136.012707] CPU: 0 PID: 789 Comm: kworker/0:2 Kdump: loaded Not tainted 4.19.103+ #1 [39136.029010] Hardware name: Huawei TaiShan 2280 V2/BC82AMDD, BIOS 1.08 12/14/2019 [39136.044587] Workqueue: pencrypt padata_parallel_worker [39136.055396] pstate: 00c00009 (nzcv daif +PAN +UAO) [39136.065479] pc : padata_reorder+0x144/0x2e0 [39136.074274] lr : padata_reorder+0x124/0x2e0 [39136.083070] sp : ffff0000149cbc90 [39136.090036] x29: ffff0000149cbc90 x28: 0000000000000001 [39136.101215] x27: ffffa02fd14af080 x26: ffffa02fd5fe1600 [39136.112392] x25: ffff5df7bf4c0ac8 x24: ffffa02fd5fe1628 [39136.123569] x23: 0000000000000000 x22: ffff00000828a258 [39136.134747] x21: ffffa02fd5fe1618 x20: ffff000009a79788 [39136.145924] x19: ffff5df7bf4c0ac8 x18: 00000000bef9a3f7 [39136.157102] x17: 0000000066bb7710 x16: 000000009a34db62 [39136.168280] x15: 0000000000342311 x14: 0000000037c9c538 [39136.179458] x13: 00000000deb82818 x12: 000000007abb6477 [39136.190638] x11: 000000006e0b05e5 x10: 00000000ccde2d6a [39136.201817] x9 : 0000000000000000 x8 : a544a826aa446d6a [39136.212996] x7 : e5050b6ea3a6345c x6 : ffffa02fd74ef030 [39136.224174] x5 : 0000000000000010 x4 : ffff5df7bf4c0ac8 [39136.235354] x3 : ffff5df7bf4c0ad8 x2 : ffff5df7bf4c0ac8 [39136.246532] x1 : ffff5df7bf4c0ad8 x0 : 0000000000000000 [39136.257712] Call trace: [39136.262851] padata_reorder+0x144/0x2e0 [39136.270922] padata_do_serial+0xc8/0x128 [39136.279177] pcrypt_aead_enc+0x60/0x70 [pcrypt] [39136.288708] padata_parallel_worker+0xd8/0x138 [39136.298056] process_one_work+0x1bc/0x4b8 [39136.306489] worker_thread+0x164/0x580 [39136.314374] kthread+0x134/0x138 [39136.321163] ret_from_fork+0x10/0x18 [39136.328681] Code: f900033b 52800000 91004261 089ffc20 (f9400ae1) [39136.341508] ---[ end trace fc1b4f00385f0fee ]--- [39136.351221] Kernel panic - not syncing: Fatal exception in interrupt [39136.364591] SMP: stopping secondary CPUs [39136.372863] Kernel Offset: disabled [39138.438722] CPU features: 0x12,a2200a38 [39138.446797] Memory Limit: none [39138.463025] Starting crashdump kernel... [39138.471295] Bye!
Quoted 58 lines
kernel/padata.c +3
-31+atomic_set (&pd->refcnt,1 );spin_lock_init (&pd->lock);return pd;@@ -526,31 +533,6 @@ static void padata_free_pd(struct parallel_data *pd)kfree (pd); } -/* Flush all objects out of the padata queues. */ -static void padata_flush_queues (struct parallel_data *pd) -{ -int cpu; -struct padata_parallel_queue *pqueue; -struct padata_serial_queue *squeue; - -for_each_cpu (cpu, pd->cpumask.pcpu) { - pqueue =per_cpu_ptr (pd->pqueue, cpu); -flush_work (&pqueue->work); - } - -del_timer_sync (&pd->timer); - -if (atomic_read (&pd->reorder_objects)) -padata_reorder (pd); - -for_each_cpu (cpu, pd->cpumask.cbcpu) { - squeue =per_cpu_ptr (pd->squeue, cpu); -flush_work (&squeue->work); - } - -BUG_ON (atomic_read (&pd->refcnt) !=0 ); -} -static void __padata_start (struct padata_instance *pinst) { pinst->flags |=PADATA_INIT ;@@ -564,10 +546,6 @@ static void __padata_stop(struct padata_instance *pinst) pinst->flags &= ~PADATA_INIT ;synchronize_rcu (); - -get_online_cpus (); -padata_flush_queues (pinst->pd); -put_online_cpus (); }/* Replace the internal control structure with a new one. */ @@ -588,8 +566,8 @@ static void padata_replace(struct padata_instance *pinst,if (!cpumask_equal (pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu)) notification_mask |=PADATA_CPU_SERIAL ; -padata_flush_queues (pd_old); -padata_free_pd (pd_old); +if (atomic_dec_and_test (&pd_old->refcnt)) +padata_free_pd (pd_old);if (notification_mask) blocking_notifier_call_chain(&pinst->cpumask_change_notifier,
Re: [PATCH 4.19 091/195] padata: Remove broken queue flushing
Hello Yang,
Quoted 9 lines · Yang Yingliang
kernel/padata.c static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst, · line 505
Quoted 6 lines · Greg Kroah-Hartman
kernel/padata.c +0
-2@@ -501,8 +509,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst,timer_setup (&pd->timer, padata_reorder_timer,0 );atomic_set (&pd->seq_nr,-1 );atomic_set (&pd->reorder_objects,0 ); -atomic_set (&pd->refcnt,0 ); - pd->pinst = pinst;This patch remove this assignment, it's cause a null-ptr-deref when using
pd->pinstinpadata_reorder().
Thanks for reporting. This change is based on an enhancement in mainline that moved this assignment but isn't in 4.19:
bfde23ce200e ("padata: unbind parallel jobs from specific CPUs")
A version of _this_ patch (i.e. remove broken queue flushing) has been posted for 4.14, 4.9, and 4.4, all of which would likely result in the same issue, so let's hold off on merging those until I can post fixed versions.
I'll start working on the 4.19 fix now.
Greg Kroah-Hartman
maintainerRe: [PATCH 4.19 091/195] padata: Remove broken queue flushing
In reply to Yang YingliangQuoted 134 lines · Yang Yingliang
Hi,
Quoted 66 lines · Greg Kroah-Hartman
From: Herbert Xu <[email protected]>
[ Upstream commit
07928d9bfc81640bab36f5190e8725894d93b659]The function
padata_flush_queuesis fundamentally broken because it cannot force padata users to complete the request that is underway. IOW padata has to passively wait for the completion of any outstanding work.As it stands flushing is used in two places. Its use in
padata_stopis simply unnecessary because nothing depends on the queues to be flushed afterwards.The other use in
padata_replaceis more substantial as we depend on it to free the old pd structure. This patch instead uses thepd->refcntto dynamically free the pd structure once all requests are complete.Fixes 2b73b07ab8a4 ("padata: Flush the padata queues actively")Cc <[email protected]>Signed-off-by Herbert Xu <[email protected]>Reviewed-by Daniel Jordan <[email protected]>Signed-off-by Herbert Xu <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- kernel/padata.c | 46 ++++++++++++---------------------------------- 1 file changed, 12 insertions(+), 34 deletions(-)kernel/padata.c +9
-1@@ -35,6 +35,8 @@#define MAX_OBJ_NUM 1000 +static void padata_free_pd (struct parallel_data *pd); +static int padata_index_to_cpu (struct parallel_data *pd,int cpu_index) {int cpu, target_cpu;@@ -334,6 +336,7 @@ static void padata_serial_worker(struct work_struct *serial_work)struct padata_serial_queue *squeue;struct parallel_data *pd;LIST_HEAD (local_list); +int cnt;local_bh_disable (); squeue = container_of(serial_work, struct padata_serial_queue, work);@@ -343,6 +346,8 @@ static void padata_serial_worker(struct work_struct *serial_work)list_replace_init (&squeue->serial.list, &local_list);spin_unlock (&squeue->serial.lock); + cnt =0 ; +while (!list_empty (&local_list)) {struct padata_priv *padata;@@ -352,9 +357,12 @@ static void padata_serial_worker(struct work_struct *serial_work)list_del_init (&padata->list); padata->serial (padata); -atomic_dec (&pd->refcnt); + cnt++; }local_bh_enable (); + +if (atomic_sub_and_test (cnt, &pd->refcnt)) +padata_free_pd (pd); }/** kernel/padata.c static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst, · line 505
Quoted 5 lines
kernel/padata.c +0
-2@@ -501,8 +509,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst,timer_setup (&pd->timer, padata_reorder_timer,0 );atomic_set (&pd->seq_nr,-1 );atomic_set (&pd->reorder_objects,0 ); -atomic_set (&pd->refcnt,0 ); - pd->pinst = pinst;This patch remove this assignment, it's cause a null-ptr-deref when using
pd->pinstinpadata_reorder().[39135.886908] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 [39135.886909] Mem abort info: [39135.886910] ESR = 0x96000004 [39135.886912] Exception class = DABT (current EL), IL = 32 bits [39135.886913] SET = 0, FnV = 0 [39135.886913] EA = 0, S1PTW = 0 [39135.886914] Data abort info: [39135.886915] ISV = 0, ISS = 0x00000004 [39135.886915] CM = 0, WnR = 0 [39135.886918] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000c66d7ef5 [39135.886919] [0000000000000010] pgd=0000000000000000 [39135.886922] Internal error: Oops: 96000004 [#1] SMP [39135.897190] Modules linked in: authenc pcrypt crypto_user cfg80211 rfkill
ib_isertiscsi_target_modib_srpttarget_core_moddm_mirrordm_region_hashrpcrdmadm_logib_srpscsi_transport_srpsunrpcdm_modib_ipoibrdma_ucmib_uverbsib_umadib_iserrdma_cmib_cmiw_cmaes_ce_blkcrypto_simdcryptdaes_ce_cipherhns_roce_hw_v2ghash_cesha2_cesha256_arm64hns_roceib_coresha1_cesbsa_gwdthi_sfcsg mtdipmi_ssifsch_fq_codelip_tablesrealtek hclge hinic hns3ipmi_sihisi_sas_v3_hwhibmc_drmhnae3hisi_sas_mainipmi_devintfipmi_msghandler[39135.997870] Process kworker/0:2 (pid: 789, stack limit = 0x0000000047f55ba6) [39136.012707] CPU: 0 PID: 789 Comm: kworker/0:2 Kdump: loaded Not tainted 4.19.103+ #1 [39136.029010] Hardware name: Huawei TaiShan 2280 V2/BC82AMDD, BIOS 1.08 12/14/2019 [39136.044587] Workqueue: pencrypt padata_parallel_worker [39136.055396] pstate: 00c00009 (nzcv daif +PAN +UAO) [39136.065479] pc : padata_reorder+0x144/0x2e0 [39136.074274] lr : padata_reorder+0x124/0x2e0 [39136.083070] sp : ffff0000149cbc90 [39136.090036] x29: ffff0000149cbc90 x28: 0000000000000001 [39136.101215] x27: ffffa02fd14af080 x26: ffffa02fd5fe1600 [39136.112392] x25: ffff5df7bf4c0ac8 x24: ffffa02fd5fe1628 [39136.123569] x23: 0000000000000000 x22: ffff00000828a258 [39136.134747] x21: ffffa02fd5fe1618 x20: ffff000009a79788 [39136.145924] x19: ffff5df7bf4c0ac8 x18: 00000000bef9a3f7 [39136.157102] x17: 0000000066bb7710 x16: 000000009a34db62 [39136.168280] x15: 0000000000342311 x14: 0000000037c9c538 [39136.179458] x13: 00000000deb82818 x12: 000000007abb6477 [39136.190638] x11: 000000006e0b05e5 x10: 00000000ccde2d6a [39136.201817] x9 : 0000000000000000 x8 : a544a826aa446d6a [39136.212996] x7 : e5050b6ea3a6345c x6 : ffffa02fd74ef030 [39136.224174] x5 : 0000000000000010 x4 : ffff5df7bf4c0ac8 [39136.235354] x3 : ffff5df7bf4c0ad8 x2 : ffff5df7bf4c0ac8 [39136.246532] x1 : ffff5df7bf4c0ad8 x0 : 0000000000000000 [39136.257712] Call trace: [39136.262851] padata_reorder+0x144/0x2e0 [39136.270922] padata_do_serial+0xc8/0x128 [39136.279177] pcrypt_aead_enc+0x60/0x70 [pcrypt] [39136.288708] padata_parallel_worker+0xd8/0x138 [39136.298056] process_one_work+0x1bc/0x4b8 [39136.306489] worker_thread+0x164/0x580 [39136.314374] kthread+0x134/0x138 [39136.321163] ret_from_fork+0x10/0x18 [39136.328681] Code: f900033b 52800000 91004261 089ffc20 (f9400ae1)
Quoted 8 lines
[39136.341508] ---[ end trace fc1b4f00385f0fee ]--- [39136.351221] Kernel panic - not syncing: Fatal exception in interrupt [39136.364591] SMP: stopping secondary CPUs [39136.372863] Kernel Offset: disabled [39138.438722] CPU features: 0x12,a2200a38 [39138.446797] Memory Limit: none [39138.463025] Starting crashdump kernel... [39138.471295] Bye!
So this causes a problem in the 4.19-rc tree but not in Linus's tree? Or am I confused? Should it be dropped from stable or is there some other fix-of-a-fix that I need to apply here?
thanks,
greg k-h
Re: [PATCH 4.19 091/195] padata: Remove broken queue flushing
Quoted 3 lines · Greg Kroah-Hartman
So this causes a problem in the 4.19-rc tree but not in Linus's tree? Or am I confused? Should it be dropped from stable or is there some other fix-of-a-fix that I need to apply here?
This causes a problem in 4.19.103 and 4.19-rc but not Linus's tree.
The fix-of-a-fix is posted recently here:
https://lore.kernel.org/lkml/[email protected]/
For 4.14, 4.9, and 4.4, I'm posting a revised version of "Remove broken queue flushing" in each review thread. 4.14 is already up. Is this what I should be doing?
thanks,
Daniel
Greg Kroah-Hartman
maintainerRe: [PATCH 4.19 091/195] padata: Remove broken queue flushing
Quoted 7 lines · Daniel Jordan
Quoted 3 lines · Greg Kroah-Hartman
So this causes a problem in the 4.19-rc tree but not in Linus's tree? Or am I confused? Should it be dropped from stable or is there some other fix-of-a-fix that I need to apply here?
This causes a problem in 4.19.103 and 4.19-rc but not Linus's tree.
Quoted 7 lines
The fix-of-a-fix is posted recently here:
https://lore.kernel.org/lkml/[email protected]/For 4.14, 4.9, and 4.4, I'm posting a revised version of "Remove broken queue flushing" in each review thread. 4.14 is already up. Is this what I should be doing?
That is exactly correct, thanks for doing this, I'll drop what is currently in these trees and then queue your new fix up for the next round of releases, thanks!
greg k-h
Greg Kroah-Hartman
maintainerPATCH 92/195 tracing: Annotate ftrace_graph_hash pointer with __rcu
In reply to Greg Kroah-HartmanFrom: Amol Grover <[email protected]>
[ Upstream commit 24a9729f831462b1d9d61dc85ecc91c59037243f ]
Fix following instances of sparse error kernel/trace/ftrace.c:5664:29: error: incompatible types in comparison kernel/trace/ftrace.c:5785:21: error: incompatible types in comparison kernel/trace/ftrace.c:5864:36: error: incompatible types in comparison kernel/trace/ftrace.c:5866:25: error: incompatible types in comparison
Use rcu_dereference_protected to access the __rcu annotated pointer.
--- kernel/trace/ftrace.c | 2 +- kernel/trace/trace.h | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-)
kernel/trace/ftrace.c +1 -1
@@ -5072,7 +5072,7 @@ static const struct file_operations ftrace_notrace_fops = {static DEFINE_MUTEX (graph_lock); -struct ftrace_hash *ftrace_graph_hash =EMPTY_HASH ; +struct ftrace_hash __rcu *ftrace_graph_hash =EMPTY_HASH ;struct ftrace_hash *ftrace_graph_notrace_hash =EMPTY_HASH ;enum graph_filter_type {
kernel/trace/trace.h +6 -3
@@ -872,22 +872,25 @@ extern void __trace_graph_return(struct trace_array *tr, unsigned long flags, int pc);#ifdef CONFIG_DYNAMIC_FTRACE -extern struct ftrace_hash *ftrace_graph_hash; +extern struct ftrace_hash __rcu *ftrace_graph_hash;extern struct ftrace_hash *ftrace_graph_notrace_hash;static inline int ftrace_graph_addr (struct ftrace_graph_ent *trace) {unsigned long addr = trace->func;int ret =0 ; +struct ftrace_hash *hash;preempt_disable_notrace (); -if (ftrace_hash_empty (ftrace_graph_hash)) { + hash =rcu_dereference_protected (ftrace_graph_hash, !preemptible ()); + +if (ftrace_hash_empty (hash)) { ret =1 ; goto out; } -if (ftrace_lookup_ip (ftrace_graph_hash, addr)) { +if (ftrace_lookup_ip (hash, addr)) {/* * This needs to be cleared on the return functions
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 93/195 tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu
In reply to Greg Kroah-HartmanFrom: Amol Grover <[email protected]>
[ Upstream commit fd0e6852c407dd9aefc594f54ddcc21d84803d3b ]
Fix following instances of sparse error kernel/trace/ftrace.c:5667:29: error: incompatible types in comparison kernel/trace/ftrace.c:5813:21: error: incompatible types in comparison kernel/trace/ftrace.c:5868:36: error: incompatible types in comparison kernel/trace/ftrace.c:5870:25: error: incompatible types in comparison
Use rcu_dereference_protected to dereference the newly annotated pointer.
--- kernel/trace/ftrace.c | 2 +- kernel/trace/trace.h | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-)
kernel/trace/ftrace.c +1 -1
@@ -5073,7 +5073,7 @@ static const struct file_operations ftrace_notrace_fops = {static DEFINE_MUTEX (graph_lock);struct ftrace_hash __rcu *ftrace_graph_hash =EMPTY_HASH ; -struct ftrace_hash *ftrace_graph_notrace_hash =EMPTY_HASH ; +struct ftrace_hash __rcu *ftrace_graph_notrace_hash =EMPTY_HASH ;enum graph_filter_type {GRAPH_FILTER_NOTRACE =0 ,
kernel/trace/trace.h +6 -2
@@ -873,7 +873,7 @@ extern void __trace_graph_return(struct trace_array *tr,#ifdef CONFIG_DYNAMIC_FTRACE extern struct ftrace_hash __rcu *ftrace_graph_hash; -extern struct ftrace_hash *ftrace_graph_notrace_hash; +extern struct ftrace_hash __rcu *ftrace_graph_notrace_hash;static inline int ftrace_graph_addr (struct ftrace_graph_ent *trace) {
@@ -926,10 +926,14 @@ static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace)static inline int ftrace_graph_notrace_addr (unsigned long addr) {int ret =0 ; +struct ftrace_hash *notrace_hash;preempt_disable_notrace (); -if (ftrace_lookup_ip (ftrace_graph_notrace_hash, addr)) + notrace_hash =rcu_dereference_protected (ftrace_graph_notrace_hash, + !preemptible ()); + +if (ftrace_lookup_ip (notrace_hash, addr)) ret =1 ;preempt_enable_notrace ();
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 94/195 ftrace: Add comment to why rcu_dereference_sched() is open coded
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit 16052dd5bdfa16dbe18d8c1d4cde2ddab9d23177 ]
Because the function graph tracer can execute in sections where RCU is not "watching", the rcu_dereference_sched() for the has needs to be open coded. This is fine because the RCU "flavor" of the ftrace hash is protected by its own RCU handling (it does its own little synchronization on every CPU and does not rely on RCU sched).
--- kernel/trace/trace.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
kernel/trace/trace.h +10 -0
@@ -883,6 +883,11 @@ static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)preempt_disable_notrace (); +/* +* Have to open code "rcu_dereference_sched()" because the +* function graph tracer can be called when RCU is not +* "watching". +*/ hash =rcu_dereference_protected (ftrace_graph_hash, !preemptible ());if (ftrace_hash_empty (hash)) {
@@ -930,6 +935,11 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)preempt_disable_notrace (); +/* +* Have to open code "rcu_dereference_sched()" because the +* function graph tracer can be called when RCU is not +* "watching". +*/ notrace_hash =rcu_dereference_protected (ftrace_graph_notrace_hash, !preemptible ());
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 95/195 ftrace: Protect ftrace_graph_hash with ftrace_sync
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit 54a16ff6f2e50775145b210bcd94d62c3c2af117 ]
As function_graph tracer can run when RCU is not "watching", it can not be protected by synchronize_rcu() it requires running a task on each CPU before it can be freed. Calling schedule_on_each_cpu(ftrace_sync) needs to be used.
--- kernel/trace/ftrace.c | 11 +++++++++-- kernel/trace/trace.h | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-)
kernel/trace/ftrace.c +9 -2
@@ -5344,8 +5344,15 @@ ftrace_graph_release(struct inode *inode, struct file *file)mutex_unlock (&graph_lock); -/* Wait till all users are no longer using the old hash */ -synchronize_sched (); +/* +* We need to do a hard force of sched synchronization. +* This is because we use preempt_disable() to do RCU, but +* the function tracers can be called where RCU is not watching +* (like before user_exit()). We can not rely on the RCU +* infrastructure to do the synchronization, thus we must do it +* ourselves. +*/ +schedule_on_each_cpu (ftrace_sync);free_ftrace_hash (old_hash); }
kernel/trace/trace.h +2 -0
@@ -887,6 +887,7 @@ static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)* Have to open code "rcu_dereference_sched()" because the * function graph tracer can be called when RCU is not * "watching". +* Protected with schedule_on_each_cpu(ftrace_sync) */ hash =rcu_dereference_protected (ftrace_graph_hash, !preemptible ());
@@ -939,6 +940,7 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)* Have to open code "rcu_dereference_sched()" because the * function graph tracer can be called when RCU is not * "watching". +* Protected with schedule_on_each_cpu(ftrace_sync) */ notrace_hash =rcu_dereference_protected (ftrace_graph_notrace_hash, !preemptible ());
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 96/195 samples/bpf: Dont try to remove users homedir on clean
In reply to Greg Kroah-HartmanFrom: Toke Høiland-Jørgensen <[email protected]>
commit b2e5e93ae8af6a34bca536cdc4b453ab1e707b8b upstream.
The 'clean' rule in the samples/bpf Makefile tries to remove backup files (ending in ~). However, if no such files exist, it will instead try to remove the user's home directory. While the attempt is mostly harmless, it does lead to a somewhat scary warning like this:
rm: cannot remove '~': Is a directory
Fix this by using find instead of shell expansion to locate any actual backup files that need to be removed.
--- samples/bpf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
samples/bpf/Makefile +1 -1
@@ -221,7 +221,7 @@ all: clean: $(MAKE) -C ../../ M=$(CURDIR) clean - @rm -f *~ + @find $(CURDIR) -type f -name '*~' -delete $(LIBBPF): FORCE # Fix up variables inherited from Kbuild that tools/ build system won't like
Greg Kroah-Hartman
maintainerPATCH 97/195 crypto: ccp - set max RSA modulus size for v3 platform devices as well
In reply to Greg Kroah-HartmanFrom: Ard Biesheuvel <[email protected]>
commit 11548f5a5747813ff84bed6f2ea01100053b0d8d upstream.
AMD Seattle incorporates a non-PCI version of the v3 CCP crypto accelerator, and this version was left behind when the maximum RSA modulus size was parameterized in order to support v5 hardware which supports larger moduli than v3 hardware does. Due to this oversight, RSA acceleration no longer works at all on these systems.
Fix this by setting the .rsamax property to the appropriate value for v3 platform hardware.
--- drivers/crypto/ccp/ccp-dev-v3.c | 1 + 1 file changed, 1 insertion(+)
drivers/crypto/ccp/ccp-dev-v3.c +1 -0
@@ -590,6 +590,7 @@ const struct ccp_vdata ccpv3_platform = .setup = NULL, .perform = &ccp3_actions, .offset = 0, + .rsamax = CCP_RSA_MAX_WIDTH, };const struct ccp_vdata ccpv3 = {
Greg Kroah-Hartman
maintainerPATCH 98/195 crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit e8d998264bffade3cfe0536559f712ab9058d654 upstream.
We should not be modifying the original request's MAY_SLEEP flag upon completion. It makes no sense to do so anyway.
--- crypto/pcrypt.c | 1 - 1 file changed, 1 deletion(-)
crypto/pcrypt.c +0 -1
@@ -130,7 +130,6 @@ static void pcrypt_aead_done(struct crypstruct padata_priv *padata =pcrypt_request_padata (preq); padata->info = err; - req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP ;padata_do_serial (padata); }
Greg Kroah-Hartman
maintainerPATCH 99/195 crypto: atmel-aes - Fix counter overflow in CTR mode
In reply to Greg Kroah-HartmanFrom: Tudor Ambarus <[email protected]>
commit 781a08d9740afa73357f1a60d45d7c93d7cca2dd upstream.
32 bit counter is not supported by neither of our AES IPs, all implement a 16 bit block counter. Drop the 32 bit block counter logic.
--- drivers/crypto/atmel-aes.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-)
drivers/crypto/atmel-aes.c +12 -25
@@ -91,7 +91,6 @@struct atmel_aes_caps {bool has_dualbuff;bool has_cfb64; -bool has_ctr32;bool has_gcm;bool has_xts;bool has_authenc;
@@ -1016,8 +1015,9 @@ static int atmel_aes_ctr_transfer(structstruct atmel_aes_ctr_ctx *ctx =atmel_aes_ctr_ctx_cast (dd->ctx);struct ablkcipher_request *req =ablkcipher_request_cast (dd->areq);struct scatterlist *src, *dst; -u32 ctr, blocks;size_t datalen; +u32 ctr; +u16 blocks, start, end;bool use_dma, fragmented = false;/* Check for transfer completion. */
@@ -1029,27 +1029,17 @@ static int atmel_aes_ctr_transfer(struct datalen = req->nbytes - ctx->offset; blocks =DIV_ROUND_UP (datalen,AES_BLOCK_SIZE ); ctr =be32_to_cpu (ctx->iv[3 ]); -if (dd->caps.has_ctr32) { -/* Check 32bit counter overflow. */ -u32 start = ctr; -u32 end = start + blocks -1 ; - -if (end < start) { - ctr |=0xffffffff ; - datalen =AES_BLOCK_SIZE * -start; - fragmented = true; - } - }else { -/* Check 16bit counter overflow. */ -u16 start = ctr &0xffff ; -u16 end = start + (u16 )blocks -1 ; - -if (blocks >>16 || end < start) { - ctr |=0xffff ; - datalen =AES_BLOCK_SIZE * (0x10000 -start); - fragmented = true; - } + +/* Check 16bit counter overflow. */ + start = ctr &0xffff ; + end = start + blocks -1 ; + +if (blocks >>16 || end < start) { + ctr |=0xffff ; + datalen =AES_BLOCK_SIZE * (0x10000 - start); + fragmented = true; } + use_dma = (datalen >=ATMEL_AES_DMA_THRESHOLD );/* Jump to offset. */
@@ -2553,7 +2543,6 @@ static void atmel_aes_get_cap(struct atm { dd->caps.has_dualbuff =0 ; dd->caps.has_cfb64 =0 ; - dd->caps.has_ctr32 =0 ; dd->caps.has_gcm =0 ; dd->caps.has_xts =0 ; dd->caps.has_authenc =0 ;
@@ -2564,7 +2553,6 @@ static void atmel_aes_get_cap(struct atmcase 0x500 : dd->caps.has_dualbuff =1 ; dd->caps.has_cfb64 =1 ; - dd->caps.has_ctr32 =1 ; dd->caps.has_gcm =1 ; dd->caps.has_xts =1 ; dd->caps.has_authenc =1 ;
@@ -2573,7 +2561,6 @@ static void atmel_aes_get_cap(struct atmcase 0x200 : dd->caps.has_dualbuff =1 ; dd->caps.has_cfb64 =1 ; - dd->caps.has_ctr32 =1 ; dd->caps.has_gcm =1 ; dd->caps.max_burst_size =4 ;break ;
Greg Kroah-Hartman
maintainerPATCH 100/195 crypto: api - Fix race condition in crypto_spawn_alg
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit 73669cc556462f4e50376538d77ee312142e8a8a upstream.
The function crypto_spawn_alg is racy because it drops the lock before shooting the dying algorithm. The algorithm could disappear altogether before we shoot it.
This patch fixes it by moving the shooting into the locked section.
--- crypto/algapi.c | 16 +++++----------- crypto/api.c | 3 +-- crypto/internal.h | 1 - 3 files changed, 6 insertions(+), 14 deletions(-)
crypto/algapi.c +5 -11
@@ -659,22 +659,16 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn);static struct crypto_alg *crypto_spawn_alg (struct crypto_spawn *spawn) {struct crypto_alg *alg; -struct crypto_alg *alg2;down_read (&crypto_alg_sem); alg = spawn->alg; - alg2 = alg; -if (alg2) - alg2 =crypto_mod_get (alg2); -up_read (&crypto_alg_sem); - -if (!alg2) { -if (alg) -crypto_shoot_alg (alg); -return ERR_PTR (-EAGAIN ); +if (alg && !crypto_mod_get (alg)) { + alg->cra_flags |=CRYPTO_ALG_DYING ; + alg =NULL ; } +up_read (&crypto_alg_sem); -return alg; +return alg ?:ERR_PTR (-EAGAIN ); } struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
crypto/api.c +1 -2
@@ -349,13 +349,12 @@ static unsigned int crypto_ctxsize(strucreturn len; } -void crypto_shoot_alg (struct crypto_alg *alg) +static void crypto_shoot_alg (struct crypto_alg *alg) {down_write (&crypto_alg_sem); alg->cra_flags |=CRYPTO_ALG_DYING ;up_write (&crypto_alg_sem); } -EXPORT_SYMBOL_GPL (crypto_shoot_alg);struct crypto_tfm *__crypto_alloc_tfm (struct crypto_alg *alg,u32 type,u32 mask)
crypto/internal.h +0 -1
@@ -79,7 +79,6 @@ void crypto_alg_tested(const char *name,void crypto_remove_spawns (struct crypto_alg *alg,struct list_head *list,struct crypto_alg *nalg);void crypto_remove_final (struct list_head *list); -void crypto_shoot_alg (struct crypto_alg *alg);struct crypto_tfm *__crypto_alloc_tfm (struct crypto_alg *alg,u32 type,u32 mask); void *crypto_create_tfm(struct crypto_alg *alg,
Greg Kroah-Hartman
maintainerPATCH 101/195 crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill
In reply to Greg Kroah-HartmanFrom: Chuhong Yuan <[email protected]>
commit 7f8c36fe9be46862c4f3c5302f769378028a34fa upstream.
Since tasklet is needed to be initialized before registering IRQ handler, adjust the position of tasklet_init to fix the wrong order.
Besides, to fix the missed tasklet_kill, this patch adds a helper function and uses devm_add_action to kill the tasklet automatically.
--- drivers/crypto/picoxcell_crypto.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/crypto/picoxcell_crypto.c +13 -2
@@ -1616,6 +1616,11 @@ static const struct of_device_id spacc_oMODULE_DEVICE_TABLE (of, spacc_of_id_table);#endif /* CONFIG_OF */ +static void spacc_tasklet_kill (void *data) +{ +tasklet_kill (data); +} +static int spacc_probe (struct platform_device *pdev) {int i, err, ret;
@@ -1659,6 +1664,14 @@ static int spacc_probe(struct platform_dreturn -ENXIO ; } +tasklet_init (&engine->complete, spacc_spacc_complete, + (unsigned long )engine); + + ret =devm_add_action (&pdev->dev, spacc_tasklet_kill, + &engine->complete); +if (ret) +return ret; +if (devm_request_irq (&pdev->dev, irq->start, spacc_spacc_irq,0 , engine->name, engine)) {dev_err (engine->dev,"failed to request IRQ\n" );
@@ -1716,8 +1729,6 @@ static int spacc_probe(struct platform_dINIT_LIST_HEAD (&engine->completed);INIT_LIST_HEAD (&engine->in_progress); engine->in_flight =0 ; -tasklet_init (&engine->complete, spacc_spacc_complete, - (unsigned long )engine);platform_set_drvdata (pdev, engine);
Greg Kroah-Hartman
maintainerPATCH 102/195 scsi: qla2xxx: Fix unbound NVME response length
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 00fe717ee1ea3c2979db4f94b1533c57aed8dea9 upstream.
On certain cases when response length is less than 32, NVME response data is supplied inline in IOCB. This is indicated by some combination of state flags. There was an instance when a high, and incorrect, response length was indicated causing driver to overrun buffers. Fix this by checking and limiting the response payload length.
--- drivers/scsi/qla2xxx/qla_dbg.c | 6 ------ drivers/scsi/qla2xxx/qla_dbg.h | 6 ++++++ drivers/scsi/qla2xxx/qla_isr.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-)
drivers/scsi/qla2xxx/qla_dbg.c +0 -6
@@ -2520,12 +2520,6 @@ qla83xx_fw_dump_failed:/* Driver Debug Functions. */ /****************************************************************************/ -static inline int -ql_mask_match (uint32_t level) -{ -return (level & ql2xextended_error_logging) == level; -} -/* * This function is for formatting and logging debug information. * It is to be used when vha is available. It formats the message
drivers/scsi/qla2xxx/qla_dbg.h +6 -0
@@ -374,3 +374,9 @@ extern int qla24xx_dump_ram(struct qla_hextern void qla24xx_pause_risc (struct device_reg_24xx __iomem *,struct qla_hw_data *);extern int qla24xx_soft_reset (struct qla_hw_data *); + +static inline int +ql_mask_match (uint level) +{ +return (level & ql2xextended_error_logging) == level; +}
drivers/scsi/qla2xxx/qla_isr.c +12 -0
@@ -1876,6 +1876,18 @@ static void qla24xx_nvme_iocb_entry(scsi inbuf = (uint32_t *)&sts->nvme_ersp_data; outbuf = (uint32_t *)fd->rspaddr; iocb->u.nvme.rsp_pyld_len =le16_to_cpu (sts->nvme_rsp_pyld_len); +if (unlikely (iocb->u.nvme.rsp_pyld_len > +sizeof (struct nvme_fc_ersp_iu ))) { +if (ql_mask_match (ql_dbg_io)) { +WARN_ONCE (1 ,"Unexpected response payload length %u.\n" , + iocb->u.nvme.rsp_pyld_len); +ql_log (ql_log_warn, fcport->vha,0x5100 , +"Unexpected response payload length %u.\n" , + iocb->u.nvme.rsp_pyld_len); + } + iocb->u.nvme.rsp_pyld_len = +sizeof (struct nvme_fc_ersp_iu ); + } iter = iocb->u.nvme.rsp_pyld_len >>2 ;for (; iter; iter--) *outbuf++ =swab32 (*inbuf++);
Greg Kroah-Hartman
maintainerPATCH 103/195 NFS: Fix memory leaks and corruption in readdir
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
commit 4b310319c6a8ce708f1033d57145e2aa027a883c upstream.
nfs_readdir_xdr_to_array() must not exit without having initialised the array, so that the page cache deletion routines can safely call nfs_readdir_clear_array().
Furthermore, we should ensure that if we exit nfs_readdir_filler() with an error, we free up any page contents to prevent a leak if we try to fill the page again.
--- fs/nfs/dir.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
fs/nfs/dir.c +15 -2
@@ -162,6 +162,17 @@ typedef struct {bool eof; } nfs_readdir_descriptor_t; +static +void nfs_readdir_init_array (struct page *page) +{ +struct nfs_cache_array *array; + + array =kmap_atomic (page); +memset (array,0 ,sizeof (struct nfs_cache_array )); + array->eof_index =-1 ; +kunmap_atomic (array); +} +/* * we are freeing strings created by nfs_add_to_readdir_array() */
@@ -174,6 +185,7 @@ void nfs_readdir_clear_array(struct page array =kmap_atomic (page);for (i =0 ; i < array->size; i++)kfree (array->array[i].string.name); + array->size =0 ;kunmap_atomic (array); }
@@ -610,6 +622,8 @@ int nfs_readdir_xdr_to_array(nfs_readdirint status = -ENOMEM ;unsigned int array_size =ARRAY_SIZE (pages); +nfs_readdir_init_array (page); + entry.prev_cookie =0 ; entry.cookie = desc->last_cookie; entry.eof =0 ;
@@ -626,8 +640,6 @@ int nfs_readdir_xdr_to_array(nfs_readdir } array =kmap (page); -memset (array,0 ,sizeof (struct nfs_cache_array )); - array->eof_index =-1 ; status =nfs_readdir_alloc_pages (pages, array_size);if (status <0 )
@@ -681,6 +693,7 @@ int nfs_readdir_filler(nfs_readdir_descrunlock_page (page);return 0 ; error: +nfs_readdir_clear_array (page);unlock_page (page);return ret; }
Greg Kroah-Hartman
maintainerPATCH 104/195 NFS: Directory page cache pages need to be locked when read
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
commit 114de38225d9b300f027e2aec9afbb6e0def154b upstream.
When a NFS directory page cache page is removed from the page cache, its contents are freed through a call to nfs_readdir_clear_array(). To prevent the removal of the page cache entry until after we've finished reading it, we must take the page lock.
--- fs/nfs/dir.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
fs/nfs/dir.c +19 -11
@@ -701,8 +701,6 @@ int nfs_readdir_filler(nfs_readdir_descrstatic void cache_page_release (nfs_readdir_descriptor_t *desc) { -if (!desc->page->mapping) -nfs_readdir_clear_array (desc->page);put_page (desc->page); desc->page =NULL ; }
@@ -716,19 +714,28 @@ struct page *get_cache_page(nfs_readdir_/* * Returns 0 if desc->dir_cookie was found on page desc->page_index +* and locks the page to prevent removal from the page cache. */ static -int find_cache_page (nfs_readdir_descriptor_t *desc) +int find_and_lock_cache_page (nfs_readdir_descriptor_t *desc) {int res; desc->page =get_cache_page (desc);if (IS_ERR (desc->page))return PTR_ERR (desc->page); - - res =nfs_readdir_search_array (desc); + res =lock_page_killable (desc->page);if (res !=0 ) -cache_page_release (desc); + goto error; + res = -EAGAIN ; +if (desc->page->mapping !=NULL ) { + res =nfs_readdir_search_array (desc); +if (res ==0 ) +return 0 ; + } +unlock_page (desc->page); +error: +cache_page_release (desc);return res; }
@@ -743,7 +750,7 @@ int readdir_search_pagecache(nfs_readdir desc->last_cookie =0 ; }do { - res =find_cache_page (desc); + res =find_and_lock_cache_page (desc); }while (res == -EAGAIN );return res; }
@@ -782,7 +789,6 @@ int nfs_do_filldir(nfs_readdir_descripto desc->eof = true;kunmap (desc->page); -cache_page_release (desc);dfprintk (DIRCACHE ,"NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n" , (unsigned long long )*desc->dir_cookie, res);return res;
@@ -828,13 +834,13 @@ int uncached_readdir(nfs_readdir_descrip status =nfs_do_filldir (desc); + out_release: +nfs_readdir_clear_array (desc->page); +cache_page_release (desc); out:dfprintk (DIRCACHE ,"NFS: %s: returns %d\n" , __func__, status);return status; - out_release: -cache_page_release (desc); - goto out; }/* The file offset position represents the dirent entry number. A
@@ -899,6 +905,8 @@ static int nfs_readdir(struct file *filebreak ; res =nfs_do_filldir (desc); +unlock_page (desc->page); +cache_page_release (desc);if (res <0 )break ; }while (!desc->eof);
Greg Kroah-Hartman
maintainerPATCH 105/195 jbd2_seq_info_next should increase position index
In reply to Greg Kroah-HartmanFrom: Vasily Averin <[email protected]>
commit 1a8e9cf40c9a6a2e40b1e924b13ed303aeea4418 upstream.
if seq_file .next fuction does not change position index, read after some lseek can generate unexpected output.
Script below generates endless output
$ q=;while read -r r;do echo "$((++q)) $r";done </proc/fs/jbd2/DEV/info
https://bugzilla.kernel.org/show_bug.cgi?id=206283
--- fs/jbd2/journal.c | 1 + 1 file changed, 1 insertion(+)
fs/jbd2/journal.c +1 -0
@@ -1002,6 +1002,7 @@ static void *jbd2_seq_info_start(structstatic void *jbd2_seq_info_next (struct seq_file *seq,void *v,loff_t *pos) { + (*pos)++;return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 106/195 Btrfs: fix missing hole after hole punching and fsync when using NO_HOLES
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 0e56315ca147b3e60c7bf240233a301d3c7fb508 upstream.
When using the NO_HOLES feature, if we punch a hole into a file and then fsync it, there are cases where a subsequent fsync will miss the fact that a hole was punched, resulting in the holes not existing after replaying the log tree.
Essentially these cases all imply that, tree-log.c:copy_items(), is not invoked for the leafs that delimit holes, because nothing changed those leafs in the current transaction. And it's precisely copy_items() where we currenly detect and log holes, which works as long as the holes are between file extent items in the input leaf or between the beginning of input leaf and the previous leaf or between the last item in the leaf and the next leaf.
First example where we miss a hole:
*) The extent items of the inode span multiple leafs;
*) The punched hole covers a range that affects only the extent items of
the first leaf;
*) The fsync operation is done in full mode (BTRFS_INODE_NEEDS_FULL_SYNC
is set in the inode's runtime flags).
That results in the hole not existing after replaying the log tree.
For example, if the fs/subvolume tree has the following layout for a particular inode:
Leaf N, generation 10:
[ ... INODE_ITEM INODE_REF EXTENT_ITEM (0 64K) EXTENT_ITEM (64K 128K) ]
Leaf N + 1, generation 10:
[ EXTENT_ITEM (128K 64K) ... ]
If at transaction 11 we punch a hole coverting the range [0, 128K[, we end up dropping the two extent items from leaf N, but we don't touch the other leaf, so we end up in the following state:
Leaf N, generation 11:
[ ... INODE_ITEM INODE_REF ]
Leaf N + 1, generation 10:
[ EXTENT_ITEM (128K 64K) ... ]
A full fsync after punching the hole will only process leaf N because it was modified in the current transaction, but not leaf N + 1, since it was not modified in the current transaction (generation 10 and not 11). As a result the fsync will not log any holes, because it didn't process any leaf with extent items.
Second example where we will miss a hole:
*) An inode as its items spanning 5 (or more) leafs;
*) A hole is punched and it covers only the extents items of the 3rd
leaf. This resulsts in deleting the entire leaf and not touching any of the other leafs.
So the only leaf that is modified in the current transaction, when punching the hole, is the first leaf, which contains the inode item. During the full fsync, the only leaf that is passed to copy_items() is that first leaf, and that's not enough for the hole detection code in copy_items() to determine there's a hole between the last file extent item in the 2nd leaf and the first file extent item in the 3rd leaf (which was the 4th leaf before punching the hole).
Fix this by scanning all leafs and punch holes as necessary when doing a full fsync (less common than a non-full fsync) when the NO_HOLES feature is enabled. The lack of explicit file extent items to mark holes makes it necessary to scan existing extents to determine if holes exist.
A test case for fstests follows soon.
--- fs/btrfs/tree-log.c | 388 +++++++++++++--------------------------------------- 1 file changed, 100 insertions(+), 288 deletions(-)
fs/btrfs/tree-log.c +100 -288
@@ -3892,7 +3892,7 @@ static int log_csums(struct btrfs_trans_ static noinline int copy_items(struct btrfs_trans_handle *trans,struct btrfs_inode *inode,struct btrfs_path *dst_path, -struct btrfs_path *src_path,u64 *last_extent, +struct btrfs_path *src_path,int start_slot,int nr,int inode_only,u64 logged_isize) {
@@ -3903,7 +3903,6 @@ static noinline int copy_items(struct btstruct btrfs_file_extent_item *extent;struct btrfs_inode_item *inode_item;struct extent_buffer *src = src_path->nodes[0 ]; -struct btrfs_key first_key, last_key, key;int ret;struct btrfs_key *ins_keys;u32 *ins_sizes;
@@ -3911,9 +3910,6 @@ static noinline int copy_items(struct btint i;struct list_head ordered_sums;int skip_csum = inode->flags &BTRFS_INODE_NODATASUM ; -bool has_extents = false; -bool need_find_last_extent = true; -bool done = false;INIT_LIST_HEAD (&ordered_sums);
@@ -3922,8 +3918,6 @@ static noinline int copy_items(struct btif (!ins_data)return -ENOMEM ; - first_key.objectid = (u64)-1 ; - ins_sizes = (u32 *)ins_data; ins_keys = (struct btrfs_key *)(ins_data + nr *sizeof (u32));
@@ -3944,9 +3938,6 @@ static noinline int copy_items(struct bt src_offset =btrfs_item_ptr_offset (src, start_slot + i); -if (i == nr -1 ) - last_key = ins_keys[i]; -if (ins_keys[i].type ==BTRFS_INODE_ITEM_KEY ) { inode_item = btrfs_item_ptr(dst_path->nodes[0], dst_path->slots[0],
@@ -3960,20 +3951,6 @@ static noinline int copy_items(struct bt src_offset, ins_sizes[i]); } -/* -* We set need_find_last_extent here in case we know we were -* processing other items and then walk into the first extent in -* the inode. If we don't hit an extent then nothing changes, -* we'll do the last search the next time around. -*/ -if (ins_keys[i].type ==BTRFS_EXTENT_DATA_KEY ) { - has_extents = true; -if (first_key.objectid == (u64)-1 ) - first_key = ins_keys[i]; - }else { - need_find_last_extent = false; - } -/* take a reference on file data extents so that truncates * or deletes of this inode don't have to relog the inode * again
@@ -4039,167 +4016,6 @@ static noinline int copy_items(struct btkfree (sums); } -if (!has_extents) -return ret; - -if (need_find_last_extent && *last_extent == first_key.offset) { -/* -* We don't have any leafs between our current one and the one -* we processed before that can have file extent items for our -* inode (and have a generation number smaller than our current -* transaction id). -*/ - need_find_last_extent = false; - } - -/* -* Because we use btrfs_search_forward we could skip leaves that were -* not modified and then assume *last_extent is valid when it really -* isn't. So back up to the previous leaf and read the end of the last -* extent before we go and fill in holes. -*/ -if (need_find_last_extent) { -u64 len; - - ret =btrfs_prev_leaf (inode->root, src_path); -if (ret <0 ) -return ret; -if (ret) - goto fill_holes; -if (src_path->slots[0 ]) - src_path->slots[0 ]--; - src = src_path->nodes[0 ]; -btrfs_item_key_to_cpu (src, &key, src_path->slots[0 ]); -if (key.objectid !=btrfs_ino (inode) || - key.type !=BTRFS_EXTENT_DATA_KEY ) - goto fill_holes; - extent =btrfs_item_ptr (src, src_path->slots[0 ], - struct btrfs_file_extent_item); -if (btrfs_file_extent_type (src, extent) == -BTRFS_FILE_EXTENT_INLINE ) { - len =btrfs_file_extent_ram_bytes (src, extent); - *last_extent =ALIGN (key.offset + len, - fs_info->sectorsize); - }else { - len =btrfs_file_extent_num_bytes (src, extent); - *last_extent = key.offset + len; - } - } -fill_holes: -/* So we did prev_leaf, now we need to move to the next leaf, but a few -* things could have happened -* -* 1) A merge could have happened, so we could currently be on a leaf -* that holds what we were copying in the first place. -* 2) A split could have happened, and now not all of the items we want -* are on the same leaf. -* -* So we need to adjust how we search for holes, we need to drop the -* path and re-search for the first extent key we found, and then walk -* forward until we hit the last one we copied. -*/ -if (need_find_last_extent) { -/* btrfs_prev_leaf could return 1 without releasing the path */ -btrfs_release_path (src_path); - ret =btrfs_search_slot (NULL , inode->root, &first_key, - src_path,0 ,0 ); -if (ret <0 ) -return ret; -ASSERT (ret ==0 ); - src = src_path->nodes[0 ]; - i = src_path->slots[0 ]; - }else { - i = start_slot; - } - -/* -* Ok so here we need to go through and fill in any holes we may have -* to make sure that holes are punched for those areas in case they had -* extents previously. -*/ -while (!done) { -u64 offset, len; -u64 extent_end; - -if (i >=btrfs_header_nritems (src_path->nodes[0 ])) { - ret =btrfs_next_leaf (inode->root, src_path); -if (ret <0 ) -return ret; -ASSERT (ret ==0 ); - src = src_path->nodes[0 ]; - i =0 ; - need_find_last_extent = true; - } - -btrfs_item_key_to_cpu (src, &key, i); -if (!btrfs_comp_cpu_keys (&key, &last_key)) - done = true; -if (key.objectid !=btrfs_ino (inode) || - key.type !=BTRFS_EXTENT_DATA_KEY ) { - i++; -continue ; - } - extent = btrfs_item_ptr(src, i, struct btrfs_file_extent_item); -if (btrfs_file_extent_type (src, extent) == -BTRFS_FILE_EXTENT_INLINE ) { - len =btrfs_file_extent_ram_bytes (src, extent); - extent_end =ALIGN (key.offset + len, - fs_info->sectorsize); - }else { - len =btrfs_file_extent_num_bytes (src, extent); - extent_end = key.offset + len; - } - i++; - -if (*last_extent == key.offset) { - *last_extent = extent_end; -continue ; - } - offset = *last_extent; - len = key.offset - *last_extent; - ret =btrfs_insert_file_extent (trans, log,btrfs_ino (inode), - offset,0 ,0 , len,0 , len,0 ,0 ,0 ); -if (ret) -break ; - *last_extent = extent_end; - } - -/* -* Check if there is a hole between the last extent found in our leaf -* and the first extent in the next leaf. If there is one, we need to -* log an explicit hole so that at replay time we can punch the hole. -*/ -if (ret ==0 && - key.objectid ==btrfs_ino (inode) && - key.type ==BTRFS_EXTENT_DATA_KEY && - i ==btrfs_header_nritems (src_path->nodes[0 ])) { - ret =btrfs_next_leaf (inode->root, src_path); - need_find_last_extent = true; -if (ret >0 ) { - ret =0 ; - }else if (ret ==0 ) { -btrfs_item_key_to_cpu (src_path->nodes[0 ], &key, - src_path->slots[0 ]); -if (key.objectid ==btrfs_ino (inode) && - key.type ==BTRFS_EXTENT_DATA_KEY && - *last_extent < key.offset) { -const u64 len = key.offset - *last_extent; - - ret =btrfs_insert_file_extent (trans, log, -btrfs_ino (inode), - *last_extent,0 , -0 , len,0 , len, -0 ,0 ,0 ); - *last_extent += len; - } - } - } -/* -* Need to let the callers know we dropped the path so they should -* re-search. -*/ -if (!ret && need_find_last_extent) - ret =1 ;return ret; }
@@ -4365,7 +4181,7 @@ static int btrfs_log_prealloc_extents(stconst u64 i_size =i_size_read (&inode->vfs_inode);const u64 ino =btrfs_ino (inode);struct btrfs_path *dst_path =NULL ; -u64 last_extent = (u64)-1 ; +bool dropped_extents = false;int ins_nr =0 ;int start_slot;int ret;
@@ -4387,8 +4203,7 @@ static int btrfs_log_prealloc_extents(stif (slot >=btrfs_header_nritems (leaf)) {if (ins_nr >0 ) { ret =copy_items (trans, inode, dst_path, path, - &last_extent, start_slot, - ins_nr,1 ,0 ); + start_slot, ins_nr,1 ,0 );if (ret <0 ) goto out; ins_nr =0 ;
@@ -4412,8 +4227,7 @@ static int btrfs_log_prealloc_extents(st path->slots[0 ]++;continue ; } -if (last_extent == (u64)-1 ) { - last_extent = key.offset; +if (!dropped_extents) {/* * Avoid logging extent items logged in past fsync calls * and leading to duplicate keys in the log tree.
@@ -4427,6 +4241,7 @@ static int btrfs_log_prealloc_extents(st }while (ret == -EAGAIN );if (ret) goto out; + dropped_extents = true; }if (ins_nr ==0 ) start_slot = slot;
@@ -4441,7 +4256,7 @@ static int btrfs_log_prealloc_extents(st } }if (ins_nr >0 ) { - ret =copy_items (trans, inode, dst_path, path, &last_extent, + ret =copy_items (trans, inode, dst_path, path, start_slot, ins_nr,1 ,0 );if (ret >0 ) ret =0 ;
@@ -4636,13 +4451,8 @@ static int btrfs_log_all_xattrs(struct bif (slot >= nritems) {if (ins_nr >0 ) { -u64 last_extent =0 ; - ret =copy_items (trans, inode, dst_path, path, - &last_extent, start_slot, - ins_nr,1 ,0 ); -/* can't be 1, extent items aren't processed */ -ASSERT (ret <=0 ); + start_slot, ins_nr,1 ,0 );if (ret <0 )return ret; ins_nr =0 ;
@@ -4666,13 +4476,8 @@ static int btrfs_log_all_xattrs(struct bcond_resched (); }if (ins_nr >0 ) { -u64 last_extent =0 ; - ret =copy_items (trans, inode, dst_path, path, - &last_extent, start_slot, - ins_nr,1 ,0 ); -/* can't be 1, extent items aren't processed */ -ASSERT (ret <=0 ); + start_slot, ins_nr,1 ,0 );if (ret <0 )return ret; }
@@ -4681,100 +4486,119 @@ static int btrfs_log_all_xattrs(struct b }/* -* If the no holes feature is enabled we need to make sure any hole between the -* last extent and the i_size of our inode is explicitly marked in the log. This -* is to make sure that doing something like: -* -* 1) create file with 128Kb of data -* 2) truncate file to 64Kb -* 3) truncate file to 256Kb -* 4) fsync file -* 5) <crash/power failure> -* 6) mount fs and trigger log replay -* -* Will give us a file with a size of 256Kb, the first 64Kb of data match what -* the file had in its first 64Kb of data at step 1 and the last 192Kb of the -* file correspond to a hole. The presence of explicit holes in a log tree is -* what guarantees that log replay will remove/adjust file extent items in the -* fs/subvol tree. -* -* Here we do not need to care about holes between extents, that is already done -* by copy_items(). We also only need to do this in the full sync path, where we -* lookup for extents from the fs/subvol tree only. In the fast path case, we -* lookup the list of modified extent maps and if any represents a hole, we -* insert a corresponding extent representing a hole in the log tree. +* When using the NO_HOLES feature if we punched a hole that causes the +* deletion of entire leafs or all the extent items of the first leaf (the one +* that contains the inode item and references) we may end up not processing +* any extents, because there are no leafs with a generation matching the +* current transaction that have extent items for our inode. So we need to find +* if any holes exist and then log them. We also need to log holes after any +* truncate operation that changes the inode's size. */ -static int btrfs_log_trailing_hole (struct btrfs_trans_handle *trans, -struct btrfs_root *root, -struct btrfs_inode *inode, -struct btrfs_path *path) +static int btrfs_log_holes (struct btrfs_trans_handle *trans, +struct btrfs_root *root, +struct btrfs_inode *inode, +struct btrfs_path *path) {struct btrfs_fs_info *fs_info = root->fs_info; -int ret;struct btrfs_key key; -u64 hole_start; -u64 hole_size; -struct extent_buffer *leaf; -struct btrfs_root *log = root->log_root;const u64 ino =btrfs_ino (inode);const u64 i_size =i_size_read (&inode->vfs_inode); +u64 prev_extent_end =0 ; +int ret; -if (!btrfs_fs_incompat (fs_info,NO_HOLES )) +if (!btrfs_fs_incompat (fs_info,NO_HOLES ) || i_size ==0 )return 0 ; key.objectid = ino; key.type =BTRFS_EXTENT_DATA_KEY ; - key.offset = (u64)-1 ; + key.offset =0 ; ret =btrfs_search_slot (NULL , root, &key, path,0 ,0 ); -ASSERT (ret !=0 );if (ret <0 )return ret; -ASSERT (path->slots[0 ] >0 ); - path->slots[0 ]--; - leaf = path->nodes[0 ]; -btrfs_item_key_to_cpu (leaf, &key, path->slots[0 ]); - -if (key.objectid != ino || key.type !=BTRFS_EXTENT_DATA_KEY ) { -/* inode does not have any extents */ - hole_start =0 ; - hole_size = i_size; - }else { +while (true) {struct btrfs_file_extent_item *extent; +struct extent_buffer *leaf = path->nodes[0 ];u64 len; -/* -* If there's an extent beyond i_size, an explicit hole was -* already inserted by copy_items(). -*/ -if (key.offset >= i_size) -return 0 ; +if (path->slots[0 ] >=btrfs_header_nritems (path->nodes[0 ])) { + ret =btrfs_next_leaf (root, path); +if (ret <0 ) +return ret; +if (ret >0 ) { + ret =0 ; +break ; + } + leaf = path->nodes[0 ]; + } + +btrfs_item_key_to_cpu (leaf, &key, path->slots[0 ]); +if (key.objectid != ino || key.type !=BTRFS_EXTENT_DATA_KEY ) +break ; + +/* We have a hole, log it. */ +if (prev_extent_end < key.offset) { +const u64 hole_len = key.offset - prev_extent_end; + +/* +* Release the path to avoid deadlocks with other code +* paths that search the root while holding locks on +* leafs from the log root. +*/ +btrfs_release_path (path); + ret =btrfs_insert_file_extent (trans, root->log_root, + ino, prev_extent_end,0 , +0 , hole_len,0 , hole_len, +0 ,0 ,0 ); +if (ret <0 ) +return ret; + +/* +* Search for the same key again in the root. Since it's +* an extent item and we are holding the inode lock, the +* key must still exist. If it doesn't just emit warning +* and return an error to fall back to a transaction +* commit. +*/ + ret =btrfs_search_slot (NULL , root, &key, path,0 ,0 ); +if (ret <0 ) +return ret; +if (WARN_ON (ret >0 )) +return -ENOENT ; + leaf = path->nodes[0 ]; + } extent =btrfs_item_ptr (leaf, path->slots[0 ], struct btrfs_file_extent_item); -if (btrfs_file_extent_type (leaf, extent) == -BTRFS_FILE_EXTENT_INLINE ) -return 0 ; +BTRFS_FILE_EXTENT_INLINE ) { + len =btrfs_file_extent_ram_bytes (leaf, extent); + prev_extent_end =ALIGN (key.offset + len, + fs_info->sectorsize); + }else { + len =btrfs_file_extent_num_bytes (leaf, extent); + prev_extent_end = key.offset + len; + } - len =btrfs_file_extent_num_bytes (leaf, extent); -/* Last extent goes beyond i_size, no need to log a hole. */ -if (key.offset + len > i_size) -return 0 ; - hole_start = key.offset + len; - hole_size = i_size - hole_start; + path->slots[0 ]++; +cond_resched (); } -btrfs_release_path (path); -/* Last extent ends at i_size. */ -if (hole_size ==0 ) -return 0 ; +if (prev_extent_end < i_size) { +u64 hole_len; - hole_size =ALIGN (hole_size, fs_info->sectorsize); - ret =btrfs_insert_file_extent (trans, log, ino, hole_start,0 ,0 , - hole_size,0 , hole_size,0 ,0 ,0 ); -return ret; +btrfs_release_path (path); + hole_len =ALIGN (i_size - prev_extent_end, fs_info->sectorsize); + ret =btrfs_insert_file_extent (trans, root->log_root, + ino, prev_extent_end,0 ,0 , + hole_len,0 , hole_len, +0 ,0 ,0 ); +if (ret <0 ) +return ret; + } + +return 0 ; }/*
@@ -4934,7 +4758,6 @@ static int btrfs_log_inode(struct btrfs_struct btrfs_key min_key;struct btrfs_key max_key;struct btrfs_root *log = root->log_root; -u64 last_extent =0 ;int err =0 ;int ret;int nritems;
@@ -5108,7 +4931,7 @@ again: ins_start_slot = path->slots[0 ]; } ret =copy_items (trans, inode, dst_path, path, - &last_extent, ins_start_slot, + ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) {
@@ -5161,17 +4984,13 @@ again:if (ins_nr ==0 ) goto next_slot; ret =copy_items (trans, inode, dst_path, path, - &last_extent, ins_start_slot, + ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) { err = ret; goto out_unlock; } ins_nr =0 ; -if (ret) { -btrfs_release_path (path); -continue ; - } goto next_slot; }
@@ -5184,18 +5003,13 @@ again: goto next_slot; } - ret =copy_items (trans, inode, dst_path, path, &last_extent, + ret =copy_items (trans, inode, dst_path, path, ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) { err = ret; goto out_unlock; } -if (ret) { - ins_nr =0 ; -btrfs_release_path (path); -continue ; - } ins_nr =1 ; ins_start_slot = path->slots[0 ]; next_slot:
@@ -5209,13 +5023,12 @@ next_slot: }if (ins_nr) { ret =copy_items (trans, inode, dst_path, path, - &last_extent, ins_start_slot, + ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) { err = ret; goto out_unlock; } - ret =0 ; ins_nr =0 ; }btrfs_release_path (path);
@@ -5230,14 +5043,13 @@ next_key: } }if (ins_nr) { - ret =copy_items (trans, inode, dst_path, path, &last_extent, + ret =copy_items (trans, inode, dst_path, path, ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) { err = ret; goto out_unlock; } - ret =0 ; ins_nr =0 ; }
@@ -5250,7 +5062,7 @@ next_key:if (max_key.type >=BTRFS_EXTENT_DATA_KEY && !fast_search) {btrfs_release_path (path);btrfs_release_path (dst_path); - err =btrfs_log_trailing_hole (trans, root, inode, path); + err =btrfs_log_holes (trans, root, inode, path);if (err) goto out_unlock; }
Greg Kroah-Hartman
maintainerPATCH 107/195 btrfs: set trans->drity in btrfs_commit_transaction
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit d62b23c94952e78211a383b7d90ef0afbd9a3717 upstream.
If we abort a transaction we have the following sequence
if (!trans->dirty && list_empty(&trans->new_bgs))
return;
WRITE_ONCE(trans->transaction->aborted, err);
The idea being if we didn't modify anything with our trans handle then we don't really need to abort the whole transaction, maybe the other trans handles are fine and we can carry on.
However in the case of create_snapshot we add a pending_snapshot object to our transaction and then commit the transaction. We don't actually modify anything. sync() behaves the same way, attach to an existing transaction and commit it. This means that if we have an IO error in the right places we could abort the committing transaction with our trans->dirty being not set and thus not set transaction->aborted.
This is a problem because in the create_snapshot() case we depend on pending->error being set to something, or btrfs_commit_transaction returning an error.
If we are not the trans handle that gets to commit the transaction, and we're waiting on the commit to happen we get our return value from cur_trans->aborted. If this was not set to anything because sync() hit an error in the transaction commit before it could modify anything then cur_trans->aborted would be 0. Thus we'd return 0 from btrfs_commit_transaction() in create_snapshot.
This is a problem because we then try to do things with pending_snapshot->snap, which will be NULL because we didn't create the snapshot, and then we'll get a NULL pointer dereference like the following
"BUG: kernel NULL pointer dereference, address: 00000000000001f0"
RIP: 0010:btrfs_orphan_cleanup+0x2d/0x330 Call Trace: ? btrfs_mksubvol.isra.31+0x3f2/0x510 btrfs_mksubvol.isra.31+0x4bc/0x510 ? __sb_start_write+0xfa/0x200 ? mnt_want_write_file+0x24/0x50 btrfs_ioctl_snap_create_transid+0x16c/0x1a0 btrfs_ioctl_snap_create_v2+0x11e/0x1a0 btrfs_ioctl+0x1534/0x2c10 ? free_debug_processing+0x262/0x2a3 do_vfs_ioctl+0xa6/0x6b0 ? do_sys_open+0x188/0x220 ? syscall_trace_enter+0x1f8/0x330 ksys_ioctl+0x60/0x90 __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x4a/0x1b0
In order to fix this we need to make sure anybody who calls commit_transaction has trans->dirty set so that they properly set the trans->transaction->aborted value properly so any waiters know bad things happened.
This was found while I was running generic/475 with my modified fsstress, it reproduced within a few runs. I ran with this patch all night and didn't see the problem again.
--- fs/btrfs/transaction.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/btrfs/transaction.c +8 -0
@@ -1936,6 +1936,14 @@ int btrfs_commit_transaction(struct btrfstruct btrfs_transaction *prev_trans =NULL ;int ret; +/* +* Some places just start a transaction to commit it. We need to make +* sure that if this commit fails that the abort code actually marks the +* transaction as failed, so set trans->dirty to make the abort code do +* the right thing. +*/ + trans->dirty = true; +/* Stop the commit early if ->aborted is set */ if (unlikely (READ_ONCE (cur_trans->aborted))) { ret = cur_trans->aborted;
Greg Kroah-Hartman
maintainerPATCH 108/195 Btrfs: fix race between adding and putting tree mod seq elements and nodes
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 7227ff4de55d931bbdc156c8ef0ce4f100c78a5b upstream.
There is a race between adding and removing elements to the tree mod log list and rbtree that can lead to use-after-free problems.
Consider the following example that explains how/why the problems happens:
1) Task A has mod log element with sequence number 200. It currently is the only element in the mod log list;
2) Task A calls btrfs_put_tree_mod_seq() because it no longer needs to access the tree mod log. When it enters the function, it initializes 'min_seq' to (u64)-1. Then it acquires the lock 'tree_mod_seq_lock' before checking if there are other elements in the mod seq list. Since the list it empty, 'min_seq' remains set to (u64)-1. Then it unlocks the lock 'tree_mod_seq_lock';
3) Before task A acquires the lock 'tree_mod_log_lock', task B adds itself to the mod seq list through btrfs_get_tree_mod_seq() and gets a sequence number of 201;
4) Some other task, name it task C, modifies a btree and because there elements in the mod seq list, it adds a tree mod elem to the tree mod log rbtree. That node added to the mod log rbtree is assigned a sequence number of 202;
5) Task B, which is doing fiemap and resolving indirect back references, calls btrfs get_old_root(), with 'time_seq' == 201, which in turn calls tree_mod_log_search() - the search returns the mod log node from the rbtree with sequence number 202, created by task C;
6) Task A now acquires the lock 'tree_mod_log_lock', starts iterating the mod log rbtree and finds the node with sequence number 202. Since 202 is less than the previously computed 'min_seq', (u64)-1, it removes the node and frees it;
7) Task B still has a pointer to the node with sequence number 202, and it dereferences the pointer itself and through the call to __tree_mod_log_rewind(), resulting in a use-after-free problem.
This issue can be triggered sporadically with the test case generic/561 from fstests, and it happens more frequently with a higher number of duperemove processes. When it happens to me, it either freezes the VM or it produces a trace like the following before crashing:
[ 1245.321140] general protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI [ 1245.321200] CPU: 1 PID: 26997 Comm: pool Not tainted 5.5.0-rc6-btrfs-next-52 #1 [ 1245.321235] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014 [ 1245.321287] RIP: 0010:rb_next+0x16/0x50 [ 1245.321307] Code: .... [ 1245.321372] RSP: 0018:ffffa151c4d039b0 EFLAGS: 00010202 [ 1245.321388] RAX: 6b6b6b6b6b6b6b6b RBX: ffff8ae221363c80 RCX: 6b6b6b6b6b6b6b6b [ 1245.321409] RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff8ae221363c80 [ 1245.321439] RBP: ffff8ae20fcc4688 R08: 0000000000000002 R09: 0000000000000000 [ 1245.321475] R10: ffff8ae20b120910 R11: 00000000243f8bb1 R12: 0000000000000038 [ 1245.321506] R13: ffff8ae221363c80 R14: 000000000000075f R15: ffff8ae223f762b8 [ 1245.321539] FS: 00007fdee1ec7700(0000) GS:ffff8ae236c80000(0000) knlGS:0000000000000000 [ 1245.321591] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1245.321614] CR2: 00007fded4030c48 CR3: 000000021da16003 CR4: 00000000003606e0 [ 1245.321642] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1245.321668] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 1245.321706] Call Trace: [ 1245.321798] __tree_mod_log_rewind+0xbf/0x280 [btrfs] [ 1245.321841] btrfs_search_old_slot+0x105/0xd00 [btrfs] [ 1245.321877] resolve_indirect_refs+0x1eb/0xc60 [btrfs] [ 1245.321912] find_parent_nodes+0x3dc/0x11b0 [btrfs] [ 1245.321947] btrfs_check_shared+0x115/0x1c0 [btrfs] [ 1245.321980] ? extent_fiemap+0x59d/0x6d0 [btrfs] [ 1245.322029] extent_fiemap+0x59d/0x6d0 [btrfs] [ 1245.322066] do_vfs_ioctl+0x45a/0x750 [ 1245.322081] ksys_ioctl+0x70/0x80 [ 1245.322092] ? trace_hardirqs_off_thunk+0x1a/0x1c [ 1245.322113] __x64_sys_ioctl+0x16/0x20 [ 1245.322126] do_syscall_64+0x5c/0x280 [ 1245.322139] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 1245.322155] RIP: 0033:0x7fdee3942dd7 [ 1245.322177] Code: .... [ 1245.322258] RSP: 002b:00007fdee1ec6c88 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ 1245.322294] RAX: ffffffffffffffda RBX: 00007fded40210d8 RCX: 00007fdee3942dd7 [ 1245.322314] RDX: 00007fded40210d8 RSI: 00000000c020660b RDI: 0000000000000004 [ 1245.322337] RBP: 0000562aa89e7510 R08: 0000000000000000 R09: 00007fdee1ec6d44 [ 1245.322369] R10: 0000000000000073 R11: 0000000000000246 R12: 00007fdee1ec6d48 [ 1245.322390] R13: 00007fdee1ec6d40 R14: 00007fded40210d0 R15: 00007fdee1ec6d50 [ 1245.322423] Modules linked in: .... [ 1245.323443] ---[ end trace 01de1e9ec5dff3cd ]---
Fix this by ensuring that btrfs_put_tree_mod_seq() computes the minimum sequence number and iterates the rbtree while holding the lock 'tree_mod_log_lock' in write mode. Also get rid of the 'tree_mod_seq_lock' lock, since it is now redundant.
--- fs/btrfs/ctree.c | 8 ++------ fs/btrfs/ctree.h | 6 ++---- fs/btrfs/delayed-ref.c | 8 ++++---- fs/btrfs/disk-io.c | 1 - fs/btrfs/tests/btrfs-tests.c | 1 - 5 files changed, 8 insertions(+), 16 deletions(-)
fs/btrfs/ctree.c +2 -6
@@ -337,12 +337,10 @@ u64 btrfs_get_tree_mod_seq(struct btrfs_ struct seq_list *elem) {write_lock (&fs_info->tree_mod_log_lock); -spin_lock (&fs_info->tree_mod_seq_lock);if (!elem->seq) { elem->seq =btrfs_inc_tree_mod_seq (fs_info);list_add_tail (&elem->list, &fs_info->tree_mod_seq_list); } -spin_unlock (&fs_info->tree_mod_seq_lock);write_unlock (&fs_info->tree_mod_log_lock);return elem->seq;
@@ -362,7 +360,7 @@ void btrfs_put_tree_mod_seq(struct btrfsif (!seq_putting)return ; -spin_lock (&fs_info->tree_mod_seq_lock); +write_lock (&fs_info->tree_mod_log_lock);list_del (&elem->list); elem->seq =0 ;
@@ -373,19 +371,17 @@ void btrfs_put_tree_mod_seq(struct btrfs* blocker with lower sequence number exists, we * cannot remove anything from the log */ -spin_unlock (&fs_info->tree_mod_seq_lock); +write_unlock (&fs_info->tree_mod_log_lock);return ; } min_seq = cur_elem->seq; } } -spin_unlock (&fs_info->tree_mod_seq_lock);/* * anything that's lower than the lowest existing (read: blocked) * sequence number can be removed from the tree. */ -write_lock (&fs_info->tree_mod_log_lock); tm_root = &fs_info->tree_mod_log;for (node =rb_first (tm_root); node; node = next) { next =rb_next (node);
fs/btrfs/ctree.h +2 -4
@@ -893,14 +893,12 @@ struct btrfs_fs_info {struct list_head delayed_iputs;struct mutex cleaner_delayed_iput_mutex; -/* this protects tree_mod_seq_list */ -spinlock_t tree_mod_seq_lock;atomic64_t tree_mod_seq; -struct list_head tree_mod_seq_list; -/* this protects tree_mod_log */ +/* this protects tree_mod_log and tree_mod_seq_list */ rwlock_t tree_mod_log_lock;struct rb_root tree_mod_log; +struct list_head tree_mod_seq_list;atomic_t async_delalloc_pages;
fs/btrfs/delayed-ref.c +4 -4
@@ -301,7 +301,7 @@ void btrfs_merge_delayed_refs(struct btrif (head->is_data)return ; -spin_lock (&fs_info->tree_mod_seq_lock); +read_lock (&fs_info->tree_mod_log_lock);if (!list_empty (&fs_info->tree_mod_seq_list)) {struct seq_list *elem;
@@ -309,7 +309,7 @@ void btrfs_merge_delayed_refs(struct btr struct seq_list, list); seq = elem->seq; } -spin_unlock (&fs_info->tree_mod_seq_lock); +read_unlock (&fs_info->tree_mod_log_lock); again:for (node =rb_first (&head->ref_tree); node; node =rb_next (node)) {
@@ -326,7 +326,7 @@ int btrfs_check_delayed_seq(struct btrfsstruct seq_list *elem;int ret =0 ; -spin_lock (&fs_info->tree_mod_seq_lock); +read_lock (&fs_info->tree_mod_log_lock);if (!list_empty (&fs_info->tree_mod_seq_list)) { elem =list_first_entry (&fs_info->tree_mod_seq_list, struct seq_list, list);
@@ -339,7 +339,7 @@ int btrfs_check_delayed_seq(struct btrfs } } -spin_unlock (&fs_info->tree_mod_seq_lock); +read_unlock (&fs_info->tree_mod_log_lock);return ret; }
fs/btrfs/disk-io.c +0 -1
@@ -2645,7 +2645,6 @@ int open_ctree(struct super_block *sb,spin_lock_init (&fs_info->fs_roots_radix_lock);spin_lock_init (&fs_info->delayed_iput_lock);spin_lock_init (&fs_info->defrag_inodes_lock); -spin_lock_init (&fs_info->tree_mod_seq_lock);spin_lock_init (&fs_info->super_lock);spin_lock_init (&fs_info->qgroup_op_lock);spin_lock_init (&fs_info->buffer_lock);
fs/btrfs/tests/btrfs-tests.c +0 -1
@@ -102,7 +102,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_spin_lock_init (&fs_info->qgroup_op_lock);spin_lock_init (&fs_info->super_lock);spin_lock_init (&fs_info->fs_roots_radix_lock); -spin_lock_init (&fs_info->tree_mod_seq_lock);mutex_init (&fs_info->qgroup_ioctl_lock);mutex_init (&fs_info->qgroup_rescan_lock);rwlock_init (&fs_info->tree_mod_log_lock);
Greg Kroah-Hartman
maintainerPATCH 109/195 ARM: tegra: Enable PLLP bypass during Tegra124 LP1
In reply to Greg Kroah-HartmanFrom: Stephen Warren <[email protected]>
commit 1a3388d506bf5b45bb283e6a4c4706cfb4897333 upstream.
For a little over a year, U-Boot has configured the flow controller to perform automatic RAM re-repair on off->on power transitions of the CPU rail[1]. This is mandatory for correct operation of Tegra124. However, RAM re-repair relies on certain clocks, which the kernel must enable and leave running. PLLP is one of those clocks. This clock is shut down during LP1 in order to save power. Enable bypass (which I believe routes osc_div_clk, essentially the crystal clock, to the PLL output) so that this clock signal toggles even though the PLL is not active. This is required so that LP1 power mode (system suspend) operates correctly.
The bypass configuration must then be undone when resuming from LP1, so that all peripheral clocks run at the expected rate. Without this, many peripherals won't work correctly; for example, the UART baud rate would be incorrect.
NVIDIA's downstream kernel code only does this if not compiled for Tegra30, so the added code is made conditional upon the chip ID. NVIDIA's downstream code makes this change conditional upon the active CPU cluster. The upstream kernel currently doesn't support cluster switching, so this patch doesn't test the active CPU cluster ID.
[1] 3cc7942a4ae5 ARM: tegra: implement RAM repair
--- arch/arm/mach-tegra/sleep-tegra30.S | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/arm/mach-tegra/sleep-tegra30.S +11 -0
@@ -382,6 +382,14 @@ _pll_m_c_x_done: pll_locked r1, r0, CLK_RESET_PLLC_BASE pll_locked r1, r0, CLK_RESET_PLLX_BASE + tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 + cmp r1, #TEGRA30 + beq 1f + ldr r1, [r0, #CLK_RESET_PLLP_BASE] + bic r1, r1, #(1<<31) @ disable PllP bypass + str r1, [r0, #CLK_RESET_PLLP_BASE] +1: + mov32 r7, TEGRA_TMRUS_BASE ldr r1, [r7] add r1, r1, #LOCK_DELAY
@@ -641,7 +649,10 @@ tegra30_switch_cpu_to_clk32k: str r0, [r4, #PMC_PLLP_WB0_OVERRIDE] /* disable PLLP, PLLA, PLLC and PLLX */ + tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 + cmp r1, #TEGRA30 ldr r0, [r5, #CLK_RESET_PLLP_BASE] + orrne r0, r0, #(1 << 31) @ enable PllP bypass on fast cluster bic r0, r0, #(1 << 30) str r0, [r5, #CLK_RESET_PLLP_BASE] ldr r0, [r5, #CLK_RESET_PLLA_BASE]
Greg Kroah-Hartman
maintainerPATCH 110/195 iwlwifi: dont throw error when trying to remove IGTK
In reply to Greg Kroah-HartmanFrom: Luca Coelho <[email protected]>
commit 197288d5ba8a5289f22d3aeb4fca3824bfd9b4af upstream.
The IGTK keys are only removed by mac80211 after it has already removed the AP station. This causes the driver to throw an error because mac80211 is trying to remove the IGTK when the station doesn't exist anymore.
The firmware is aware that the station has been removed and can deal with it the next time we try to add an IGTK for a station, so we shouldn't try to remove the key if the station ID is IWL_MVM_INVALID_STA. Do this by removing the check for mvm_sta before calling iwl_mvm_send_sta_igtk() and check return from that function gracefully if the station ID is invalid.
--- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/sta.c +7 -3
@@ -3045,6 +3045,10 @@ static int iwl_mvm_send_sta_igtk(struct igtk_cmd.sta_id =cpu_to_le32 (sta_id);if (remove_key) { +/* This is a valid situation for IGTK */ +if (sta_id ==IWL_MVM_INVALID_STA ) +return 0 ; + igtk_cmd.ctrl_flags |=cpu_to_le32 (STA_KEY_NOT_VALID ); }else {struct ieee80211_key_seq seq;
@@ -3352,9 +3356,9 @@ int iwl_mvm_remove_sta_key(struct iwl_mvIWL_DEBUG_WEP (mvm,"mvm remove dynamic key: idx=%d sta=%d\n" , keyconf->keyidx, sta_id); -if (mvm_sta && (keyconf->cipher ==WLAN_CIPHER_SUITE_AES_CMAC || - keyconf->cipher ==WLAN_CIPHER_SUITE_BIP_GMAC_128 || - keyconf->cipher ==WLAN_CIPHER_SUITE_BIP_GMAC_256 )) +if (keyconf->cipher ==WLAN_CIPHER_SUITE_AES_CMAC || + keyconf->cipher ==WLAN_CIPHER_SUITE_BIP_GMAC_128 || + keyconf->cipher ==WLAN_CIPHER_SUITE_BIP_GMAC_256 )return iwl_mvm_send_sta_igtk (mvm, keyconf, sta_id, true);if (!__test_and_clear_bit (keyconf->hw_key_idx, mvm->fw_key_table)) {
Greg Kroah-Hartman
maintainerPATCH 111/195 mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
In reply to Greg Kroah-HartmanFrom: Brian Norris <[email protected]>
commit 65b1aae0d9d5962faccc06bdb8e91a2a0b09451c upstream.
We called rcu_read_lock(), so we need to call rcu_read_unlock() before we return.
--- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +1 -0
@@ -232,6 +232,7 @@ static int mwifiex_process_country_ie(stif (country_ie_len > (IEEE80211_COUNTRY_STRING_LEN +MWIFIEX_MAX_TRIPLET_802_11D )) { +rcu_read_unlock ();mwifiex_dbg (priv->adapter,ERROR ,"11D: country_ie_len overflow!, deauth AP\n" );return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 112/195 sunrpc: expiry_time should be seconds not timeval
In reply to Greg Kroah-HartmanFrom: Roberto Bergantinos Corpas <[email protected]>
commit 3d96208c30f84d6edf9ab4fac813306ac0d20c10 upstream.
When upcalling gssproxy, cache_head.expiry_time is set as a timeval, not seconds since boot. As such, RPC cache expiry logic will not clean expired objects created under auth.rpcsec.context cache.
This has proven to cause kernel memory leaks on field. Using 64 bit variants of getboottime/timespec
Expiration times have worked this way since 2010's c5b29f885afe "sunrpc:
use seconds since boot in expiry cache". The gssproxy code introduced in 2012 added gss_proxy_save_rsc and introduced the bug. That's a while for this to lurk, but it required a bit of an extreme case to make it obvious.
--- net/sunrpc/auth_gss/svcauth_gss.c | 4 ++++ 1 file changed, 4 insertions(+)
net/sunrpc/auth_gss/svcauth_gss.c +4 -0
@@ -1224,6 +1224,7 @@ static int gss_proxy_save_rsc(struct cacdprintk ("RPC: No creds found!\n" ); goto out; }else { +struct timespec64 boot;/* steal creds */ rsci.cred = ud->creds;
@@ -1244,6 +1245,9 @@ static int gss_proxy_save_rsc(struct cac &expiry, GFP_KERNEL);if (status) goto out; + +getboottime64 (&boot); + expiry -= boot.tv_sec; } rsci.h.expiry_time = expiry;
Greg Kroah-Hartman
maintainerPATCH 113/195 gfs2: move setting current->backing_dev_info
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit 4c0e8dda608a51855225c611b5c6b442f95fbc56 upstream.
Set current->backing_dev_info just around the buffered write calls to prepare for the next fix.
--- fs/gfs2/file.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
fs/gfs2/file.c +10 -11
@@ -800,18 +800,15 @@ static ssize_t gfs2_file_write_iter(struinode_lock (inode); ret =generic_write_checks (iocb, from);if (ret <=0 ) - goto out; - -/* We can write back this queue in page reclaim */ - current->backing_dev_info =inode_to_bdi (inode); + goto out_unlock; ret =file_remove_privs (file);if (ret) - goto out2; + goto out_unlock; ret =file_update_time (file);if (ret) - goto out2; + goto out_unlock;if (iocb->ki_flags &IOCB_DIRECT ) {struct address_space *mapping = file->f_mapping;
@@ -820,11 +817,13 @@ static ssize_t gfs2_file_write_iter(stru written =gfs2_file_direct_write (iocb, from);if (written <0 || !iov_iter_count (from)) - goto out2; + goto out_unlock; + current->backing_dev_info =inode_to_bdi (inode); ret =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); + current->backing_dev_info =NULL ;if (unlikely (ret <0 )) - goto out2; + goto out_unlock; buffered = ret;/*
@@ -848,14 +847,14 @@ static ssize_t gfs2_file_write_iter(stru*/ } }else { + current->backing_dev_info =inode_to_bdi (inode); ret =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); + current->backing_dev_info =NULL ;if (likely (ret >0 )) iocb->ki_pos += ret; } -out2: - current->backing_dev_info =NULL ; -out: +out_unlock:inode_unlock (inode);if (likely (ret >0 )) {/* Handle various SYNC-type writes */
Greg Kroah-Hartman
maintainerPATCH 114/195 gfs2: fix O_SYNC write handling
In reply to Greg Kroah-HartmanFrom: Andreas Gruenbacher <[email protected]>
commit 6e5e41e2dc4e4413296d5a4af54ac92d7cd52317 upstream.
In gfs2_file_write_iter, for direct writes, the error checking in the buffered write fallback case is incomplete. This can cause inode write errors to go undetected. Fix and clean up gfs2_file_write_iter along the way.
Based on a proposed fix by Christoph Hellwig <[email protected]>.
--- fs/gfs2/file.c | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-)
fs/gfs2/file.c +21 -30
@@ -780,7 +780,7 @@ static ssize_t gfs2_file_write_iter(strustruct file *file = iocb->ki_filp;struct inode *inode =file_inode (file);struct gfs2_inode *ip =GFS2_I (inode); -ssize_t written =0 , ret; +ssize_t ret; ret =gfs2_rsqa_alloc (ip);if (ret)
@@ -812,55 +812,46 @@ static ssize_t gfs2_file_write_iter(struif (iocb->ki_flags &IOCB_DIRECT ) {struct address_space *mapping = file->f_mapping; -loff_t pos, endbyte; -ssize_t buffered; +ssize_t buffered, ret2; - written =gfs2_file_direct_write (iocb, from); -if (written <0 || !iov_iter_count (from)) + ret =gfs2_file_direct_write (iocb, from); +if (ret <0 || !iov_iter_count (from)) goto out_unlock; + iocb->ki_flags |=IOCB_DSYNC ; current->backing_dev_info =inode_to_bdi (inode); - ret =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); + buffered =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); current->backing_dev_info =NULL ; -if (unlikely (ret <0 )) +if (unlikely (buffered <=0 )) goto out_unlock; - buffered = ret;/* * We need to ensure that the page cache pages are written to * disk and invalidated to preserve the expected O_DIRECT -* semantics. +* semantics. If the writeback or invalidate fails, only report +* the direct I/O range as we don't know if the buffered pages +* made it to disk. */ - pos = iocb->ki_pos; - endbyte = pos + buffered -1 ; - ret =filemap_write_and_wait_range (mapping, pos, endbyte); -if (!ret) { - iocb->ki_pos += buffered; - written += buffered; -invalidate_mapping_pages (mapping, - pos >>PAGE_SHIFT , - endbyte >>PAGE_SHIFT ); - }else { -/* -* We don't know how much we wrote, so just return -* the number of bytes which were direct-written -*/ - } + iocb->ki_pos += buffered; + ret2 =generic_write_sync (iocb, buffered); +invalidate_mapping_pages (mapping, + (iocb->ki_pos - buffered) >>PAGE_SHIFT , + (iocb->ki_pos -1 ) >>PAGE_SHIFT ); +if (!ret || ret2 >0 ) + ret += ret2; }else { current->backing_dev_info =inode_to_bdi (inode); ret =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); current->backing_dev_info =NULL ; -if (likely (ret >0 )) +if (likely (ret >0 )) { iocb->ki_pos += ret; + ret =generic_write_sync (iocb, ret); + } } out_unlock:inode_unlock (inode); -if (likely (ret >0 )) { -/* Handle various SYNC-type writes */ - ret =generic_write_sync (iocb, ret); - } -return written ? written : ret; +return ret; } static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
Greg Kroah-Hartman
maintainerPATCH 115/195 drm/rect: Avoid division by zero
In reply to Greg Kroah-HartmanFrom: Ville Syrjälä <[email protected]>
commit 433480c1afd44f3e1e664b85063d98cefeefa0ed upstream.
Check for zero width/height destination rectangle in drm_rect_clip_scaled() to avoid a division by zero.
Testcase: igt/kms_selftest/drm_rect_clip_scaled_div_by_zero
--- drivers/gpu/drm/drm_rect.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_rect.c +6 -1
@@ -52,7 +52,12 @@ EXPORT_SYMBOL(drm_rect_intersect);static u32 clip_scaled (u32 src,u32 dst,u32 clip) { -u64 tmp =mul_u32_u32 (src, dst - clip); +u64 tmp; + +if (dst ==0 ) +return 0 ; + + tmp =mul_u32_u32 (src, dst - clip);/* * Round toward 1.0 when clipping so that we don't accidentally
Greg Kroah-Hartman
maintainerPATCH 116/195 media: rc: ensure lirc is initialized before registering input device
In reply to Greg Kroah-HartmanFrom: Sean Young <[email protected]>
commit 080d89f522e2baddb4fbbd1af4b67b5f92537ef8 upstream.
Once rc_open is called on the input device, lirc events can be delivered. Ensure lirc is ready to do so else we might get this:
Registered IR keymap rc-hauppauge
rc rc0: Hauppauge WinTV PVR-350 as /devices/pci0000:00/0000:00:1e.0/0000:04:00.0/i2c-0/0-0018/rc/rc0
input: Hauppauge WinTV PVR-350 as /devices/pci0000:00/0000:00:1e.0/0000:04:00.0/i2c-0/0-0018/rc/rc0/input9
BUG: kernel NULL pointer dereference, address: 0000000000000038 PGD 0 P4D 0 Oops: 0000 [#1] SMP PTI CPU: 1 PID: 17 Comm: kworker/1:0 Not tainted 5.3.11-300.fc31.x86_64 #1 Hardware name: /DG43NB, BIOS NBG4310H.86A.0096.2009.0903.1845 09/03/2009 Workqueue: events ir_work [ir_kbd_i2c] RIP: 0010:ir_lirc_scancode_event+0x3d/0xb0 Code: a6 b4 07 00 00 49 81 c6 b8 07 00 00 55 53 e8 ba a7 9d ff 4c 89 e7 49 89 45 00 e8 5e 7a 25 00 49 8b 1e 48 89 c5 4c 39 f3 74 58 <8b> 43 38 8b 53 40 89 c1 2b 4b 3c 39 ca 72 41 21 d0 49 8b 7d 00 49 RSP: 0018:ffffaae2000b3d88 EFLAGS: 00010017 RAX: 0000000000000002 RBX: 0000000000000000 RCX: 0000000000000019 RDX: 0000000000000001 RSI: 006e801b1f26ce6a RDI: ffff9e39797c37b4 RBP: 0000000000000002 R08: 0000000000000001 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000001 R12: ffff9e39797c37b4 R13: ffffaae2000b3db8 R14: ffff9e39797c37b8 R15: ffff9e39797c33d8 FS: 0000000000000000(0000) GS:ffff9e397b680000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000038 CR3: 0000000035844000 CR4: 00000000000006e0 Call Trace: ir_do_keydown+0x8e/0x2b0 rc_keydown+0x52/0xc0 ir_work+0xb8/0x130 [ir_kbd_i2c] process_one_work+0x19d/0x340 worker_thread+0x50/0x3b0 kthread+0xfb/0x130 ? process_one_work+0x340/0x340 ? kthread_park+0x80/0x80 ret_from_fork+0x35/0x40 Modules linked in: rc_hauppauge tuner msp3400 saa7127 saa7115 ivtv(+)
tveeprom cx2341x v4l2_common videodev mc i2c_algo_bit ir_kbd_i2c ip_tables firewire_ohci e1000e serio_raw firewire_core ata_generic crc_itu_t pata_acpi pata_jmicron fuse
CR2: 0000000000000038
---[ end trace c67c2697a99fa74b ]--- RIP: 0010:ir_lirc_scancode_event+0x3d/0xb0 Code: a6 b4 07 00 00 49 81 c6 b8 07 00 00 55 53 e8 ba a7 9d ff 4c 89 e7 49 89 45 00 e8 5e 7a 25 00 49 8b 1e 48 89 c5 4c 39 f3 74 58 <8b> 43 38 8b 53 40 89 c1 2b 4b 3c 39 ca 72 41 21 d0 49 8b 7d 00 49 RSP: 0018:ffffaae2000b3d88 EFLAGS: 00010017 RAX: 0000000000000002 RBX: 0000000000000000 RCX: 0000000000000019 RDX: 0000000000000001 RSI: 006e801b1f26ce6a RDI: ffff9e39797c37b4 RBP: 0000000000000002 R08: 0000000000000001 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000001 R12: ffff9e39797c37b4 R13: ffffaae2000b3db8 R14: ffff9e39797c37b8 R15: ffff9e39797c33d8 FS: 0000000000000000(0000) GS:ffff9e397b680000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000038 CR3: 0000000035844000 CR4: 00000000000006e0 rc rc0: lirc_dev: driver ir_kbd_i2c registered at minor = 0, scancode
receiver, no transmitter
tuner-simple 0-0061: creating new instance
tuner-simple 0-0061: type set to 2 (Philips NTSC (FI1236,FM1236 and compatibles))
ivtv0: Registered device video0 for encoder MPG (4096 kB)
ivtv0: Registered device video32 for encoder YUV (2048 kB)
ivtv0: Registered device vbi0 for encoder VBI (1024 kB)
ivtv0: Registered device video24 for encoder PCM (320 kB)
ivtv0: Registered device radio0 for encoder radio
ivtv0: Registered device video16 for decoder MPG (1024 kB)
ivtv0: Registered device vbi8 for decoder VBI (64 kB)
ivtv0: Registered device vbi16 for decoder VOUT
ivtv0: Registered device video48 for decoder YUV (1024 kB)
--- drivers/media/rc/rc-main.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
drivers/media/rc/rc-main.c +16 -11
@@ -1874,23 +1874,28 @@ int rc_register_device(struct rc_dev *de dev->registered = true; -if (dev->driver_type !=RC_DRIVER_IR_RAW_TX ) { - rc =rc_setup_rx_device (dev); -if (rc) - goto out_dev; - } - -/* Ensure that the lirc kfifo is setup before we start the thread */ +/* +* once the the input device is registered in rc_setup_rx_device, +* userspace can open the input device and rc_open() will be called +* as a result. This results in driver code being allowed to submit +* keycodes with rc_keydown, so lirc must be registered first. +*/ if (dev->allowed_protocols !=RC_PROTO_BIT_CEC ) { rc =ir_lirc_register (dev);if (rc <0 ) - goto out_rx; + goto out_dev; + } + +if (dev->driver_type !=RC_DRIVER_IR_RAW_TX ) { + rc =rc_setup_rx_device (dev); +if (rc) + goto out_lirc; }if (dev->driver_type ==RC_DRIVER_IR_RAW ) { rc =ir_raw_event_register (dev);if (rc <0 ) - goto out_lirc; + goto out_rx; } dev_dbg(&dev->dev, "Registered rc%u (driver: %s)\n", dev->minor,
@@ -1898,11 +1903,11 @@ int rc_register_device(struct rc_dev *dereturn 0 ; +out_rx: +rc_free_rx_device (dev); out_lirc:if (dev->allowed_protocols !=RC_PROTO_BIT_CEC )ir_lirc_unregister (dev); -out_rx: -rc_free_rx_device (dev); out_dev:device_del (&dev->dev); out_rx_free:
Greg Kroah-Hartman
maintainerPATCH 117/195 tools/kvm_stat: Fix kvm_exit filter name
In reply to Greg Kroah-HartmanFrom: Gavin Shan <[email protected]>
commit 5fcf3a55a62afb0760ccb6f391d62f20bce4a42f upstream.
The filter name is fixed to "exit_reason" for some kvm_exit events, no matter what architect we have. Actually, the filter name ("exit_reason") is only applicable to x86, meaning it's broken on other architects including aarch64.
This fixes the issue by providing various kvm_exit filter names, depending on architect we're on. Afterwards, the variable filter name is picked and applied through ioctl(fd, SET_FILTER).
--- tools/kvm/kvm_stat/kvm_stat | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
tools/kvm/kvm_stat/kvm_stat +6 -2
@@ -271,6 +271,7 @@ class ArchX86(Arch): def __init__(self, exit_reasons): self.sc_perf_evt_open = 298 self.ioctl_numbers = IOCTL_NUMBERS + self.exit_reason_field = 'exit_reason' self.exit_reasons = exit_reasons def debugfs_is_child(self, field):
@@ -290,6 +291,7 @@ class ArchPPC(Arch): # numbers depend on the wordsize. char_ptr_size = ctypes.sizeof(ctypes.c_char_p) self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16 + self.exit_reason_field = 'exit_nr' self.exit_reasons = {} def debugfs_is_child(self, field):
@@ -301,6 +303,7 @@ class ArchA64(Arch): def __init__(self): self.sc_perf_evt_open = 241 self.ioctl_numbers = IOCTL_NUMBERS + self.exit_reason_field = 'esr_ec' self.exit_reasons = AARCH64_EXIT_REASONS def debugfs_is_child(self, field):
@@ -312,6 +315,7 @@ class ArchS390(Arch): def __init__(self): self.sc_perf_evt_open = 331 self.ioctl_numbers = IOCTL_NUMBERS + self.exit_reason_field = None self.exit_reasons = None def debugfs_is_child(self, field):
@@ -542,8 +546,8 @@ class TracepointProvider(Provider): """ filters = {} filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS) - if ARCH.exit_reasons: - filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons) + if ARCH.exit_reason_field and ARCH.exit_reasons: + filters['kvm_exit'] = (ARCH.exit_reason_field, ARCH.exit_reasons) return filters def _get_available_fields(self):
Greg Kroah-Hartman
maintainerPATCH 118/195 xen/balloon: Support xend-based toolstack take two
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit eda4eabf86fd6806eaabc23fb90dd056fdac037b upstream.
Commit 3aa6c19d2f38be ("xen/balloon: Support xend-based toolstack") tried to fix a regression with running on rather ancient Xen versions. Unfortunately the fix was based on the assumption that xend would just use another Xenstore node, but in reality only some downstream versions of xend are doing that. The upstream xend does not write that Xenstore node at all, so the problem must be fixed in another way.
The easiest way to achieve that is to fall back to the behavior before commit 96edd61dcf4436 ("xen/balloon: don't online new memory initially") in case the static memory maximum can't be read.
This is achieved by setting static_max to the current number of memory pages known by the system resulting in target_diff becoming zero.
--- drivers/xen/xen-balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/xen/xen-balloon.c +1 -1
@@ -83,7 +83,7 @@ static void watch_target(struct xenbus_w "%llu", &static_max) == 1)) static_max >>=PAGE_SHIFT -10 ; else - static_max = new_target; + static_max = balloon_stats.current_pages; target_diff = (xen_pv_domain () ||xen_initial_domain ()) ?0 : static_max - balloon_stats.target_pages;
Greg Kroah-Hartman
maintainerPATCH 119/195 watchdog: fix UAF in reboot notifier handling in watchdog core code
In reply to Greg Kroah-HartmanFrom: Vladis Dronov <[email protected]>
commit 69503e585192fdd84b240f18a0873d20e18a2e0a upstream.
After the commit 44ea39420fc9 ("drivers/watchdog: make use of devm_register_reboot_notifier()") the struct notifier_block reboot_nb in the struct watchdog_device is removed from the reboot notifiers chain at the time watchdog's chardev is closed. But at least in i6300esb.c case reboot_nb is embedded in the struct esb_dev which can be freed on its device removal and before the chardev is closed, thus UAF at reboot:
[ 7.728581] esb_probe: esb_dev.watchdog_device ffff91316f91ab28
ts# uname -r note the address ^^^
5.5.0-rc5-ae6088-wdog
ts# ./openwdog0 &
[1] 696
ts# opened /dev/watchdog0, sleeping 10s...
ts# echo 1 > /sys/devices/pci0000\:00/0000\:00\:09.0/remove
[ 178.086079] devres:rel_nodes: dev ffff91317668a0b0 data ffff91316f91ab28
esb_dev.watchdog_device.reboot_nb memory is freed here ^^^
ts# ...woken up
[ 181.459010] devres:rel_nodes: dev ffff913171781000 data ffff913174a1dae8
[ 181.460195] devm_unreg_reboot_notifier: res ffff913174a1dae8 nb ffff91316f91ab78
attempt to use memory already freed ^^^
[ 181.461063] devm_unreg_reboot_notifier: nb->call 6b6b6b6b6b6b6b6b
[ 181.461243] devm_unreg_reboot_notifier: nb->next 6b6b6b6b6b6b6b6b
freed memory is filled with a slub poison ^^^
[1]+ Done ./openwdog0
ts# reboot
[ 229.921862] systemd-shutdown[1]: Rebooting.
[ 229.939265] notifier_call_chain: nb ffffffff9c6c2f20 nb->next ffffffff9c6d50c0
[ 229.943080] notifier_call_chain: nb ffffffff9c6d50c0 nb->next 6b6b6b6b6b6b6b6b
[ 229.946054] notifier_call_chain: nb 6b6b6b6b6b6b6b6b INVAL
[ 229.957584] general protection fault: 0000 [#1] SMP
[ 229.958770] CPU: 0 PID: 1 Comm: systemd-shutdow Not tainted 5.5.0-rc5-ae6088-wdog
[ 229.960224] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), ...
[ 229.963288] RIP: 0010:notifier_call_chain+0x66/0xd0
[ 229.969082] RSP: 0018:ffffb20dc0013d88 EFLAGS: 00010246
[ 229.970812] RAX: 000000000000002e RBX: 6b6b6b6b6b6b6b6b RCX: 00000000000008b3
[ 229.972929] RDX: 0000000000000000 RSI: 0000000000000096 RDI: ffffffff9ccc46ac
[ 229.975028] RBP: 0000000000000001 R08: 0000000000000000 R09: 00000000000008b3
[ 229.977039] R10: 0000000000000001 R11: ffffffff9c26c740 R12: 0000000000000000
[ 229.979155] R13: 6b6b6b6b6b6b6b6b R14: 0000000000000000 R15: 00000000fffffffa
... slub_debug=FZP poison ^^^
[ 229.989089] Call Trace:
[ 229.990157] blocking_notifier_call_chain+0x43/0x59
[ 229.991401] kernel_restart_prepare+0x14/0x30
[ 229.992607] kernel_restart+0x9/0x30
[ 229.993800] __do_sys_reboot+0x1d2/0x210
[ 230.000149] do_syscall_64+0x3d/0x130
[ 230.001277] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 230.002639] RIP: 0033:0x7f5461bdd177
[ 230.016402] Modules linked in: i6300esb
[ 230.050261] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000bFix the crash by reverting 44ea39420fc9 so unregister_reboot_notifier() is called when watchdog device is removed. This also makes handling of the reboot notifier unified with the handling of the restart handler, which is freed with unregister_restart_handler() in the same place.
--- drivers/watchdog/watchdog_core.c | 35 +++++++++++++++++++++++++++++++++++ drivers/watchdog/watchdog_dev.c | 36 +----------------------------------- 2 files changed, 36 insertions(+), 35 deletions(-)
drivers/watchdog/watchdog_core.c +35 -0
@@ -138,6 +138,25 @@ int watchdog_init_timeout(struct watchdo }EXPORT_SYMBOL_GPL (watchdog_init_timeout); +static int watchdog_reboot_notifier (struct notifier_block *nb, +unsigned long code,void *data) +{ +struct watchdog_device *wdd; + + wdd = container_of(nb, struct watchdog_device, reboot_nb); +if (code ==SYS_DOWN || code ==SYS_HALT ) { +if (watchdog_active (wdd)) { +int ret; + + ret = wdd->ops->stop (wdd); +if (ret) +return NOTIFY_BAD ; + } + } + +return NOTIFY_DONE ; +} +static int watchdog_restart_notifier (struct notifier_block *nb,unsigned long action,void *data) {
@@ -226,6 +245,19 @@ static int __watchdog_register_device(st } } +if (test_bit (WDOG_STOP_ON_REBOOT , &wdd->status)) { + wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; + + ret =register_reboot_notifier (&wdd->reboot_nb); +if (ret) { +pr_err ("watchdog%d: Cannot register reboot notifier (%d)\n" , + wdd->id, ret); +watchdog_dev_unregister (wdd); +ida_simple_remove (&watchdog_ida, id); +return ret; + } + } +if (wdd->ops->restart) { wdd->restart_nb.notifier_call = watchdog_restart_notifier;
@@ -271,6 +303,9 @@ static void __watchdog_unregister_deviceif (wdd->ops->restart)unregister_restart_handler (&wdd->restart_nb); +if (test_bit (WDOG_STOP_ON_REBOOT , &wdd->status)) +unregister_reboot_notifier (&wdd->reboot_nb); +watchdog_dev_unregister (wdd);ida_simple_remove (&watchdog_ida, wdd->id); }
drivers/watchdog/watchdog_dev.c +1 -35
@@ -42,7 +42,6 @@#include <linux/miscdevice.h> /* For handling misc devices */ #include <linux/module.h> /* For module stuff/... */ #include <linux/mutex.h> /* For mutexes */ -#include <linux/reboot.h> /* For reboot notifier */ #include <linux/slab.h> /* For memory functions */ #include <linux/types.h> /* For standard types (like size_t) */ #include <linux/watchdog.h> /* For watchdog specific items */
@@ -1048,25 +1047,6 @@ static void watchdog_cdev_unregister(strput_device (&wd_data->dev); } -static int watchdog_reboot_notifier (struct notifier_block *nb, -unsigned long code,void *data) -{ -struct watchdog_device *wdd; - - wdd = container_of(nb, struct watchdog_device, reboot_nb); -if (code ==SYS_DOWN || code ==SYS_HALT ) { -if (watchdog_active (wdd)) { -int ret; - - ret = wdd->ops->stop (wdd); -if (ret) -return NOTIFY_BAD ; - } - } - -return NOTIFY_DONE ; -} -/* * watchdog_dev_register: register a watchdog device * @wdd: watchdog device
@@ -1085,22 +1065,8 @@ int watchdog_dev_register(struct watchdoreturn ret; ret =watchdog_register_pretimeout (wdd); -if (ret) { +if (ret)watchdog_cdev_unregister (wdd); -return ret; - } - -if (test_bit (WDOG_STOP_ON_REBOOT , &wdd->status)) { - wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; - - ret =devm_register_reboot_notifier (&wdd->wd_data->dev, - &wdd->reboot_nb); -if (ret) { -pr_err ("watchdog%d: Cannot register reboot notifier (%d)\n" , - wdd->id, ret); -watchdog_dev_unregister (wdd); - } - }return ret; }
Greg Kroah-Hartman
maintainerPATCH 120/195 bcache: add readahead cache policy options via sysfs interface
In reply to Greg Kroah-HartmanFrom: Coly Li <[email protected]>
commit 038ba8cc1bffc51250add4a9b9249d4331576d8f upstream.
In year 2007 high performance SSD was still expensive, in order to save more space for real workload or meta data, the readahead I/Os for non-meta data was bypassed and not cached on SSD.
In now days, SSD price drops a lot and people can find larger size SSD with more comfortable price. It is unncessary to alway bypass normal readahead I/Os to save SSD space for now.
This patch adds options for readahead data cache policies via sysfs file /sys/block/bcache<N>/readahead_cache_policy, the options are,
- "all": cache all readahead data I/Os.
- "meta-only": only cache meta data, and bypass other regular I/Os.
If users want to make bcache continue to only cache readahead request for metadata and bypass regular data readahead, please set "meta-only" to this sysfs file. By default, bcache will back to cache all read- ahead requests now.
--- drivers/md/bcache/bcache.h | 3 +++ drivers/md/bcache/request.c | 17 ++++++++++++----- drivers/md/bcache/sysfs.c | 22 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-)
drivers/md/bcache/bcache.h +3 -0
@@ -329,6 +329,9 @@ struct cached_dev {*/ atomic_t has_dirty; +#define BCH_CACHE_READA_ALL 0 +#define BCH_CACHE_READA_META_ONLY 1 +unsigned int cache_readahead_policy;struct bch_ratelimit writeback_rate;struct delayed_work writeback_rate_update;
drivers/md/bcache/request.c +12 -5
@@ -391,13 +391,20 @@ static bool check_should_bypass(struct c goto skip;/* -* Flag for bypass if the IO is for read-ahead or background, -* unless the read-ahead request is for metadata +* If the bio is for read-ahead or background IO, bypass it or +* not depends on the following situations, +* - If the IO is for meta data, always cache it and no bypass +* - If the IO is not meta data, check dc->cache_reada_policy, +* BCH_CACHE_READA_ALL: cache it and not bypass +* BCH_CACHE_READA_META_ONLY: not cache it and bypass +* That is, read-ahead request for metadata always get cached * (eg, for gfs2 or xfs). */ -if (bio->bi_opf & (REQ_RAHEAD |REQ_BACKGROUND ) && - !(bio->bi_opf & (REQ_META |REQ_PRIO ))) - goto skip; +if ((bio->bi_opf & (REQ_RAHEAD |REQ_BACKGROUND ))) { +if (!(bio->bi_opf & (REQ_META |REQ_PRIO )) && + (dc->cache_readahead_policy !=BCH_CACHE_READA_ALL )) + goto skip; + }if (bio->bi_iter.bi_sector & (c->sb.block_size -1 ) ||bio_sectors (bio) & (c->sb.block_size -1 )) {
drivers/md/bcache/sysfs.c +22 -0
@@ -25,6 +25,12 @@ static const char * const bch_cache_modeNULL }; +static const char *const bch_reada_cache_policies[] = { +"all" , +"meta-only" , +NULL +}; +/* Default is -1; we skip past it for stop_when_cache_set_failed */ static const char *const bch_stop_on_failure_modes[] = {"auto" ,
@@ -94,6 +100,7 @@ rw_attribute(congested_write_threshold_urw_attribute (sequential_cutoff);rw_attribute (data_csum);rw_attribute (cache_mode); +rw_attribute (readahead_cache_policy);rw_attribute (stop_when_cache_set_failed);rw_attribute (writeback_metadata);rw_attribute (writeback_running);
@@ -160,6 +167,11 @@ SHOW(__bch_cached_dev) bch_cache_modes, BDEV_CACHE_MODE(&dc->sb)); +if (attr == &sysfs_readahead_cache_policy) +return bch_snprint_string_list (buf,PAGE_SIZE , + bch_reada_cache_policies, + dc->cache_readahead_policy); +if (attr == &sysfs_stop_when_cache_set_failed) return bch_snprint_string_list(buf, PAGE_SIZE, bch_stop_on_failure_modes,
@@ -324,6 +336,15 @@ STORE(__cached_dev) } } +if (attr == &sysfs_readahead_cache_policy) { + v =__sysfs_match_string (bch_reada_cache_policies,-1 , buf); +if (v <0 ) +return v; + +if ((unsigned int ) v != dc->cache_readahead_policy) + dc->cache_readahead_policy = v; + } +if (attr == &sysfs_stop_when_cache_set_failed) { v =__sysfs_match_string (bch_stop_on_failure_modes,-1 , buf);if (v <0 )
@@ -417,6 +438,7 @@ static struct attribute *bch_cached_dev_ &sysfs_data_csum, #endif &sysfs_cache_mode, + &sysfs_readahead_cache_policy, &sysfs_stop_when_cache_set_failed, &sysfs_writeback_metadata, &sysfs_writeback_running,
Greg Kroah-Hartman
maintainerPATCH 121/195 eventfd: track eventfd_signal() recursion depth
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit b5e683d5cab8cd433b06ae178621f083cabd4f63 upstream.
eventfd use cases from aio and io_uring can deadlock due to circular or resursive calling, when eventfd_signal() tries to grab the waitqueue lock. On top of that, it's also possible to construct notification chains that are deep enough that we could blow the stack.
Add a percpu counter that tracks the percpu recursion depth, warn if we exceed it. The counter is also exposed so that users of eventfd_signal() can do the right thing if it's non-zero in the context where it is called.
--- fs/eventfd.c | 15 +++++++++++++++ include/linux/eventfd.h | 14 ++++++++++++++ 2 files changed, 29 insertions(+)
fs/eventfd.c +15 -0
@@ -22,6 +22,8 @@#include <linux/proc_fs.h> #include <linux/seq_file.h> +DEFINE_PER_CPU (int, eventfd_wake_count); +struct eventfd_ctx {struct kref kref;wait_queue_head_t wqh;
@@ -55,12 +57,25 @@ __u64 eventfd_signal(struct eventfd_ctx {unsigned long flags; +/* +* Deadlock or stack overflow issues can happen if we recurse here +* through waitqueue wakeup handlers. If the caller users potentially +* nested waitqueues with custom wakeup handlers, then it should +* check eventfd_signal_count() before calling this function. If +* it returns true, the eventfd_signal() call should be deferred to a +* safe context. +*/ +if (WARN_ON_ONCE (this_cpu_read (eventfd_wake_count))) +return 0 ; +spin_lock_irqsave (&ctx->wqh.lock, flags); +this_cpu_inc (eventfd_wake_count);if (ULLONG_MAX - ctx->count < n) n =ULLONG_MAX - ctx->count; ctx->count += n;if (waitqueue_active (&ctx->wqh))wake_up_locked_poll (&ctx->wqh,EPOLLIN ); +this_cpu_dec (eventfd_wake_count);spin_unlock_irqrestore (&ctx->wqh.lock, flags);return n;
include/linux/eventfd.h +14 -0
@@ -12,6 +12,8 @@#include <linux/fcntl.h> #include <linux/wait.h> #include <linux/err.h> +#include <linux/percpu-defs.h> +#include <linux/percpu.h> /* * CAREFUL: Check include/uapi/asm-generic/fcntl.h when defining
@@ -40,6 +42,13 @@ __u64 eventfd_signal(struct eventfd_ctxint eventfd_ctx_remove_wait_queue (struct eventfd_ctx *ctx,wait_queue_entry_t *wait,__u64 *cnt); +DECLARE_PER_CPU (int, eventfd_wake_count); + +static inline bool eventfd_signal_count (void ) +{ +return this_cpu_read (eventfd_wake_count); +} +#else /* CONFIG_EVENTFD */ /*
@@ -68,6 +77,11 @@ static inline int eventfd_ctx_remove_waireturn -ENOSYS ; } +static inline bool eventfd_signal_count (void ) +{ +return false; +} +#endif #endif /* _LINUX_EVENTFD_H */
Greg Kroah-Hartman
maintainerPATCH 122/195 aio: prevent potential eventfd recursion on poll
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit 01d7a356872eec22ef34a33a5f9cfa917d145468 upstream.
If we have nested or circular eventfd wakeups, then we can deadlock if we run them inline from our poll waitqueue wakeup handler. It's also possible to have very long chains of notifications, to the extent where we could risk blowing the stack.
Check the eventfd recursion count before calling eventfd_signal(). If it's non-zero, then punt the signaling to async context. This is always safe, as it takes us out-of-line in terms of stack and locking context.
--- fs/aio.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
fs/aio.c +18 -2
@@ -1600,6 +1600,14 @@ static int aio_fsync(struct fsync_iocb *return 0 ; } +static void aio_poll_put_work (struct work_struct *work) +{ + struct poll_iocb *req = container_of(work, struct poll_iocb, work); + struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll); + +iocb_put (iocb); +} +static void aio_poll_complete_work (struct work_struct *work) { struct poll_iocb *req = container_of(work, struct poll_iocb, work);
@@ -1664,6 +1672,8 @@ static int aio_poll_wake(struct wait_quelist_del_init (&req->wait.entry);if (mask &&spin_trylock_irqsave (&iocb->ki_ctx->ctx_lock, flags)) { +struct kioctx *ctx = iocb->ki_ctx; +/* * Try to complete the iocb inline if we can. Use * irqsave/irqrestore because not all filesystems (e.g. fuse)
@@ -1673,8 +1683,14 @@ static int aio_poll_wake(struct wait_quelist_del (&iocb->ki_list); iocb->ki_res.res =mangle_poll (mask); req->done = true; -spin_unlock_irqrestore (&iocb->ki_ctx->ctx_lock, flags); -iocb_put (iocb); +if (iocb->ki_eventfd &&eventfd_signal_count ()) { + iocb =NULL ; +INIT_WORK (&req->work, aio_poll_put_work); +schedule_work (&req->work); + } +spin_unlock_irqrestore (&ctx->ctx_lock, flags); +if (iocb) +iocb_put (iocb); }else {schedule_work (&req->work); }
Greg Kroah-Hartman
maintainerPATCH 123/195 KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 14e32321f3606e4b0970200b6e5e47ee6f1e6410 upstream.
This fixes a Spectre-v1/L1TF vulnerability in picdev_write(). It replaces index computations based on the (attacked-controlled) port number with constants through a minor refactoring.
--- arch/x86/kvm/i8259.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/x86/kvm/i8259.c +5 -1
@@ -460,10 +460,14 @@ static int picdev_write(struct kvm_pic *switch (addr) {case 0x20 :case 0x21 : +pic_lock (s); +pic_ioport_write (&s->pics[0 ], addr, data); +pic_unlock (s); +break ;case 0xa0 :case 0xa1 :pic_lock (s); -pic_ioport_write (&s->pics[addr >>7 ], addr, data); +pic_ioport_write (&s->pics[1 ], addr, data);pic_unlock (s);break ;case 0x4d0 :
Greg Kroah-Hartman
maintainerPATCH 124/195 KVM: x86: Refactor prefix decoding to prevent Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 125ffc5e0a56a3eded608dc51e09d5ebf72cf652 upstream.
This fixes Spectre-v1/L1TF vulnerabilities in vmx_read_guest_seg_selector(), vmx_read_guest_seg_base(), vmx_read_guest_seg_limit() and vmx_read_guest_seg_ar(). When invoked from emulation, these functions contain index computations based on the (attacker-influenced) segment value. Using constants prevents the attack.
--- arch/x86/kvm/emulate.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
arch/x86/kvm/emulate.c +14 -2
@@ -5164,16 +5164,28 @@ int x86_decode_insn(struct x86_emulate_c ctxt->ad_bytes = def_ad_bytes ^6 ;break ;case 0x26 :/* ES override */ + has_seg_override = true; + ctxt->seg_override =VCPU_SREG_ES ; +break ;case 0x2e :/* CS override */ + has_seg_override = true; + ctxt->seg_override =VCPU_SREG_CS ; +break ;case 0x36 :/* SS override */ + has_seg_override = true; + ctxt->seg_override =VCPU_SREG_SS ; +break ;case 0x3e :/* DS override */ has_seg_override = true; - ctxt->seg_override = (ctxt->b >>3 ) &3 ; + ctxt->seg_override =VCPU_SREG_DS ;break ;case 0x64 :/* FS override */ + has_seg_override = true; + ctxt->seg_override =VCPU_SREG_FS ; +break ;case 0x65 :/* GS override */ has_seg_override = true; - ctxt->seg_override = ctxt->b &7 ; + ctxt->seg_override =VCPU_SREG_GS ;break ; case 0x40 ... 0x4f: /* REX */if (mode !=X86EMUL_MODE_PROT64 )
Greg Kroah-Hartman
maintainerPATCH 125/195 KVM: x86: Protect pmu_intel.c from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 66061740f1a487f4ed54fde75e724709f805da53 upstream.
This fixes Spectre-v1/L1TF vulnerabilities in intel_find_fixed_event() and intel_rdpmc_ecx_to_pmc().kvm_rdpmc() (ancestor of intel_find_fixed_event()) and reprogram_fixed_counter() (ancestor of intel_rdpmc_ecx_to_pmc()) are exported symbols so KVM should treat them conservatively from a security perspective.
--- arch/x86/kvm/pmu_intel.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
arch/x86/kvm/pmu_intel.c +16 -8
@@ -87,10 +87,14 @@ static unsigned intel_find_arch_event(ststatic unsigned intel_find_fixed_event (int idx) { -if (idx >=ARRAY_SIZE (fixed_pmc_events)) +u32 event; +size_t size =ARRAY_SIZE (fixed_pmc_events); + +if (idx >= size)return PERF_COUNT_HW_MAX ; -return intel_arch_events[fixed_pmc_events[idx]].event_type; + event = fixed_pmc_events[array_index_nospec (idx, size)]; +return intel_arch_events[event].event_type; }/* check if a PMC is enabled by comparing it with globl_ctrl bits. */
@@ -131,16 +135,20 @@ static struct kvm_pmc *intel_msr_idx_to_struct kvm_pmu *pmu =vcpu_to_pmu (vcpu);bool fixed = idx & (1u <<30 );struct kvm_pmc *counters; +unsigned int num_counters; idx &= ~(3u <<30 ); -if (!fixed && idx >= pmu->nr_arch_gp_counters) -return NULL ; -if (fixed && idx >= pmu->nr_arch_fixed_counters) +if (fixed) { + counters = pmu->fixed_counters; + num_counters = pmu->nr_arch_fixed_counters; + }else { + counters = pmu->gp_counters; + num_counters = pmu->nr_arch_gp_counters; + } +if (idx >= num_counters)return NULL ; - counters = fixed ? pmu->fixed_counters : pmu->gp_counters; *mask &= pmu->counter_bitmask[fixed ?KVM_PMC_FIXED :KVM_PMC_GP ]; - -return &counters[idx]; +return &counters[array_index_nospec (idx, num_counters)]; }static bool intel_is_valid_msr (struct kvm_vcpu *vcpu,u32 msr)
Greg Kroah-Hartman
maintainerPATCH 126/195 KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit ea740059ecb37807ba47b84b33d1447435a8d868 upstream.
This fixes a Spectre-v1/L1TF vulnerability in __kvm_set_dr() and kvm_get_dr().
Both kvm_get_dr() and kvm_set_dr() (a wrapper of __kvm_set_dr()) are exported symbols so KVM should tream them conservatively from a security perspective.
--- arch/x86/kvm/x86.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +6 -2
@@ -961,9 +961,11 @@ static u64 kvm_dr6_fixed(struct kvm_vcpustatic int __kvm_set_dr (struct kvm_vcpu *vcpu,int dr,unsigned long val) { +size_t size =ARRAY_SIZE (vcpu->arch.db); +switch (dr) { case 0 ... 3: - vcpu->arch.db[dr] = val; + vcpu->arch.db[array_index_nospec (dr, size)] = val;if (!(vcpu->guest_debug &KVM_GUESTDBG_USE_HW_BP )) vcpu->arch.eff_db[dr] = val;break ;
@@ -1000,9 +1002,11 @@ EXPORT_SYMBOL_GPL(kvm_set_dr);int kvm_get_dr (struct kvm_vcpu *vcpu,int dr,unsigned long *val) { +size_t size =ARRAY_SIZE (vcpu->arch.db); +switch (dr) { case 0 ... 3: - *val = vcpu->arch.db[dr]; + *val = vcpu->arch.db[array_index_nospec (dr, size)];break ;case 4 :/* fall through */
Greg Kroah-Hartman
maintainerPATCH 127/195 KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 4bf79cb089f6b1c6c632492c0271054ce52ad766 upstream.
This fixes a Spectre-v1/L1TF vulnerability in kvm_lapic_reg_write(). This function contains index computations based on the (attacker-controlled) MSR number.
--- arch/x86/kvm/lapic.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
arch/x86/kvm/lapic.c +9 -4
@@ -1862,15 +1862,20 @@ int kvm_lapic_reg_write(struct kvm_lapiccase APIC_LVTTHMR :case APIC_LVTPC :case APIC_LVT1 : -case APIC_LVTERR : +case APIC_LVTERR : {/* TODO: Check vector */ +size_t size; +u32 index; +if (!kvm_apic_sw_enabled (apic)) val |=APIC_LVT_MASKED ; - - val &= apic_lvt_mask[(reg -APIC_LVTT ) >>4 ]; + size =ARRAY_SIZE (apic_lvt_mask); + index =array_index_nospec ( + (reg -APIC_LVTT ) >>4 , size); + val &= apic_lvt_mask[index];kvm_lapic_set_reg (apic, reg, val); -break ; + }case APIC_LVTT :if (!kvm_apic_sw_enabled (apic))
Greg Kroah-Hartman
maintainerPATCH 128/195 KVM: x86: Protect kvm_hv_msr_[get|set]_crash_data() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 8618793750071d66028584a83ed0b4fa7eb4f607 upstream.
This fixes Spectre-v1/L1TF vulnerabilities in kvm_hv_msr_get_crash_data() and kvm_hv_msr_set_crash_data().
These functions contain index computations that use the (attacker-controlled) MSR number.
--- arch/x86/kvm/hyperv.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
arch/x86/kvm/hyperv.c +6 -4
@@ -792,11 +792,12 @@ static int kvm_hv_msr_get_crash_data(str u32 index, u64 *pdata) { struct kvm_hv *hv = &vcpu->kvm->arch.hyperv; +size_t size =ARRAY_SIZE (hv->hv_crash_param); -if (WARN_ON_ONCE (index >=ARRAY_SIZE (hv->hv_crash_param))) +if (WARN_ON_ONCE (index >= size))return -EINVAL ; - *pdata = hv->hv_crash_param[index]; + *pdata = hv->hv_crash_param[array_index_nospec (index, size)];return 0 ; }
@@ -835,11 +836,12 @@ static int kvm_hv_msr_set_crash_data(str u32 index, u64 data) {struct kvm_hv *hv = &vcpu->kvm->arch.hyperv; +size_t size =ARRAY_SIZE (hv->hv_crash_param); -if (WARN_ON_ONCE (index >=ARRAY_SIZE (hv->hv_crash_param))) +if (WARN_ON_ONCE (index >= size))return -EINVAL ; - hv->hv_crash_param[index] = data; + hv->hv_crash_param[array_index_nospec (index, size)] = data;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 129/195 KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 670564559ca35b439c8d8861fc399451ddf95137 upstream.
This fixes a Spectre-v1/L1TF vulnerability in ioapic_write_indirect(). This function contains index computations based on the (attacker-controlled) IOREGSEL register.
This patch depends on patch
"KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks".
--- arch/x86/kvm/ioapic.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kvm/ioapic.c +1 -0
@@ -297,6 +297,7 @@ static void ioapic_write_indirect(structioapic_debug ("change redir index %x val %x\n" , index, val);if (index >=IOAPIC_NUM_PINS )return ; + index =array_index_nospec (index,IOAPIC_NUM_PINS ); e = &ioapic->redirtbl[index]; mask_before = e->fields.mask;/* Preserve read-only fields */
Greg Kroah-Hartman
maintainerPATCH 130/195 KVM: x86: Protect MSR-based index computations in pmu.h from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 13c5183a4e643cc2b03a22d0e582c8e17bb7457d upstream.
This fixes a Spectre-v1/L1TF vulnerability in the get_gp_pmc() and get_fixed_pmc() functions.
They both contain index computations based on the (attacker-controlled) MSR number.
--- arch/x86/kvm/pmu.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
arch/x86/kvm/pmu.h +14 -4
@@ -2,6 +2,8 @@#ifndef __KVM_X86_PMU_H#define __KVM_X86_PMU_H +#include <linux/nospec.h> +#define vcpu_to_pmu (vcpu) (&(vcpu)->arch.pmu)#define pmu_to_vcpu (pmu) (container_of((pmu), struct kvm_vcpu, arch.pmu))#define pmc_to_pmu (pmc) (&(pmc)->vcpu->arch.pmu)
@@ -86,8 +88,12 @@ static inline bool pmc_is_enabled(structstatic inline struct kvm_pmc *get_gp_pmc (struct kvm_pmu *pmu,u32 msr,u32 base) { -if (msr >= base && msr < base + pmu->nr_arch_gp_counters) -return &pmu->gp_counters[msr - base]; +if (msr >= base && msr < base + pmu->nr_arch_gp_counters) { +u32 index =array_index_nospec (msr - base, + pmu->nr_arch_gp_counters); + +return &pmu->gp_counters[index]; + }return NULL ; }
@@ -97,8 +103,12 @@ static inline struct kvm_pmc *get_fixed_ {int base =MSR_CORE_PERF_FIXED_CTR0 ; -if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) -return &pmu->fixed_counters[msr - base]; +if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) { +u32 index =array_index_nospec (msr - base, + pmu->nr_arch_fixed_counters); + +return &pmu->fixed_counters[index]; + }return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 131/195 KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 8c86405f606ca8508b8d9280680166ca26723695 upstream.
This fixes a Spectre-v1/L1TF vulnerability in ioapic_read_indirect(). This function contains index computations based on the (attacker-controlled) IOREGSEL register.
--- arch/x86/kvm/ioapic.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
arch/x86/kvm/ioapic.c +8 -6
@@ -36,6 +36,7 @@#include <linux/io.h> #include <linux/slab.h> #include <linux/export.h> +#include <linux/nospec.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/current.h>
@@ -73,13 +74,14 @@ static unsigned long ioapic_read_indirecdefault : {u32 redir_index = (ioapic->ioregsel -0x10 ) >>1 ; -u64 redir_content; +u64 redir_content = ~0ULL ; -if (redir_index <IOAPIC_NUM_PINS ) - redir_content = - ioapic->redirtbl[redir_index].bits; -else - redir_content = ~0ULL ; +if (redir_index <IOAPIC_NUM_PINS ) { +u32 index =array_index_nospec ( + redir_index,IOAPIC_NUM_PINS ); + + redir_content = ioapic->redirtbl[index].bits; + } result = (ioapic->ioregsel &0x1 ) ? (redir_content >> 32) & 0xffffffff :
Greg Kroah-Hartman
maintainerPATCH 132/195 KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 6ec4c5eee1750d5d17951c4e1960d953376a0dda upstream.
This fixes a Spectre-v1/L1TF vulnerability in set_msr_mce() and get_msr_mce().
Both functions contain index computations based on the (attacker-controlled) MSR number.
--- arch/x86/kvm/x86.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +8 -2
@@ -2273,7 +2273,10 @@ static int set_msr_mce(struct kvm_vcpu *default :if (msr >=MSR_IA32_MC0_CTL && msr <MSR_IA32_MCx_CTL (bank_num)) { -u32 offset = msr -MSR_IA32_MC0_CTL ; +u32 offset =array_index_nospec ( + msr -MSR_IA32_MC0_CTL , +MSR_IA32_MCx_CTL (bank_num) -MSR_IA32_MC0_CTL ); +/* only 0 or all 1s can be written to IA32_MCi_CTL * some Linux kernels though clear bit 10 in bank 4 to * workaround a BIOS/GART TBL issue on AMD K8s, ignore
@@ -2685,7 +2688,10 @@ static int get_msr_mce(struct kvm_vcpu *default :if (msr >=MSR_IA32_MC0_CTL && msr <MSR_IA32_MCx_CTL (bank_num)) { -u32 offset = msr -MSR_IA32_MC0_CTL ; +u32 offset =array_index_nospec ( + msr -MSR_IA32_MC0_CTL , +MSR_IA32_MCx_CTL (bank_num) -MSR_IA32_MC0_CTL ); + data = vcpu->arch.mce_banks[offset];break ; }
Greg Kroah-Hartman
maintainerPATCH 133/195 KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 3c9053a2cae7ba2ba73766a34cea41baa70f57f7 upstream.
This fixes a Spectre-v1/L1TF vulnerability in x86_decode_insn(). kvm_emulate_instruction() (an ancestor of x86_decode_insn()) is an exported symbol, so KVM should treat it conservatively from a security perspective.
--- arch/x86/kvm/emulate.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
arch/x86/kvm/emulate.c +8 -3
@@ -5269,10 +5269,15 @@ done_prefixes: }break ;case Escape: -if (ctxt->modrm >0xbf ) - opcode = opcode.u.esc->high[ctxt->modrm -0xc0 ]; -else +if (ctxt->modrm >0xbf ) { +size_t size =ARRAY_SIZE (opcode.u.esc->high); +u32 index =array_index_nospec ( + ctxt->modrm -0xc0 , size); + + opcode = opcode.u.esc->high[index]; + }else { opcode = opcode.u.esc->op[(ctxt->modrm >>3 ) &7 ]; + }break ;case InstrDual:if ((ctxt->modrm >>6 ) ==3 )
Greg Kroah-Hartman
maintainerPATCH 134/195 KVM: x86: Protect MSR-based index computations in fixed_msr_to_seg_unit() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 25a5edea71b7c154b6a0b8cec14c711cafa31d26 upstream.
This fixes a Spectre-v1/L1TF vulnerability in fixed_msr_to_seg_unit(). This function contains index computations based on the (attacker-controlled) MSR number.
--- arch/x86/kvm/mtrr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
arch/x86/kvm/mtrr.c +6 -2
@@ -194,11 +194,15 @@ static bool fixed_msr_to_seg_unit(u32 msbreak ; case MSR_MTRRfix16K_80000 ... MSR_MTRRfix16K_A0000: *seg =1 ; - *unit = msr - MSR_MTRRfix16K_80000; + *unit =array_index_nospec ( + msr - MSR_MTRRfix16K_80000, + MSR_MTRRfix16K_A0000 - MSR_MTRRfix16K_80000 +1 );break ; case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000: *seg =2 ; - *unit = msr - MSR_MTRRfix4K_C0000; + *unit =array_index_nospec ( + msr - MSR_MTRRfix4K_C0000, + MSR_MTRRfix4K_F8000 - MSR_MTRRfix4K_C0000 +1 );break ;default :return false;
Greg Kroah-Hartman
maintainerPATCH 135/195 KVM: x86: Fix potential put_fpu() w/o load_fpu() on MPX platform
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit f958bd2314d117f8c29f4821401bc1925bc2e5ef upstream.
Unlike most state managed by XSAVE, MPX is initialized to zero on INIT. Because INITs are usually recognized in the context of a VCPU_RUN call, kvm_vcpu_reset() puts the guest's FPU so that the FPU state is resident in memory, zeros the MPX state, and reloads FPU state to hardware. But, in the unlikely event that an INIT is recognized during kvm_arch_vcpu_ioctl_get_mpstate() via kvm_apic_accept_events(), kvm_vcpu_reset() will call kvm_put_guest_fpu() without a preceding kvm_load_guest_fpu() and corrupt the guest's FPU state (and possibly userspace's FPU state as well).
Given that MPX is being removed from the kernel[*], fix the bug with the simple-but-ugly approach of loading the guest's FPU during KVM_GET_MP_STATE.
[*] See commit f240652b6032b ("x86/mpx: Remove MPX APIs").
--- arch/x86/kvm/x86.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86/kvm/x86.c +4 -0
@@ -8235,6 +8235,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(stru struct kvm_mp_state *mp_state) {vcpu_load (vcpu); +if (kvm_mpx_supported ()) +kvm_load_guest_fpu (vcpu);kvm_apic_accept_events (vcpu); if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED &&
@@ -8243,6 +8245,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struelse mp_state->mp_state = vcpu->arch.mp_state; +if (kvm_mpx_supported ()) +kvm_put_guest_fpu (vcpu);vcpu_put (vcpu);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 136/195 KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 1a978d9d3e72ddfa40ac60d26301b154247ee0bc upstream.
Call kvm_vcpu_uninit() if vcore creation fails to avoid leaking any resources allocated by kvm_vcpu_init(), i.e. the vcpu->run page.
--- arch/powerpc/kvm/book3s_hv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/kvm/book3s_hv.c +3 -1
@@ -2065,7 +2065,7 @@ static struct kvm_vcpu *kvmppc_core_vcpumutex_unlock (&kvm->lock);if (!vcore) - goto free_vcpu; + goto uninit_vcpu;spin_lock (&vcore->lock); ++vcore->num_threads;
@@ -2082,6 +2082,8 @@ static struct kvm_vcpu *kvmppc_core_vcpureturn vcpu; +uninit_vcpu: +kvm_vcpu_uninit (vcpu); free_vcpu:kmem_cache_free (kvm_vcpu_cache, vcpu); out:
Greg Kroah-Hartman
maintainerPATCH 137/195 KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit cb10bf9194f4d2c5d830eddca861f7ca0fecdbb4 upstream.
Explicitly free the shared page if kvmppc_mmu_init() fails during kvmppc_core_vcpu_create(), as the page is freed only in kvmppc_core_vcpu_free(), which is not reached via kvm_vcpu_uninit().
--- arch/powerpc/kvm/book3s_pr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/kvm/book3s_pr.c +3 -1
@@ -1772,10 +1772,12 @@ static struct kvm_vcpu *kvmppc_core_vcpu err =kvmppc_mmu_init (vcpu);if (err <0 ) - goto uninit_vcpu; + goto free_shared_page;return vcpu; +free_shared_page: +free_page ((unsigned long )vcpu->arch.shared); uninit_vcpu:kvm_vcpu_uninit (vcpu); free_shadow_vcpu:
Greg Kroah-Hartman
maintainerPATCH 138/195 x86/kvm: Be careful not to clear KVM_VCPU_FLUSH_TLB bit
In reply to Greg Kroah-HartmanFrom: Boris Ostrovsky <[email protected]>
commit 8c6de56a42e0c657955e12b882a81ef07d1d073e upstream.
kvm_steal_time_set_preempted() may accidentally clear KVM_VCPU_FLUSH_TLB bit if it is called more than once while VCPU is preempted.
This is part of CVE-2019-3016.
(This bug was also independently discovered by Jim Mattson <[email protected]>)
--- arch/x86/kvm/x86.c | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/kvm/x86.c +3 -0
@@ -3244,6 +3244,9 @@ static void kvm_steal_time_set_preemptedif (!(vcpu->arch.st.msr_val &KVM_MSR_ENABLED ))return ; +if (vcpu->arch.st.steal.preempted) +return ; + vcpu->arch.st.steal.preempted =KVM_VCPU_PREEMPTED ; kvm_write_guest_offset_cached(vcpu->kvm, &vcpu->arch.st.stime,
Greg Kroah-Hartman
maintainerPATCH 139/195 KVM: x86: Dont let userspace set host-reserved cr4 bits
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit b11306b53b2540c6ba068c4deddb6a17d9f8d95b upstream.
Calculate the host-reserved cr4 bits at runtime based on the system's capabilities (using logic similar to __do_cpuid_func()), and use the dynamically generated mask for the reserved bit check in kvm_set_cr4() instead using of the static CR4_RESERVED_BITS define. This prevents userspace from "enabling" features in cr4 that are not supported by the system, e.g. by ignoring KVM_GET_SUPPORTED_CPUID and specifying a bogus CPUID for the vCPU.
Allowing userspace to set unsupported bits in cr4 can lead to a variety of undesirable behavior, e.g. failed VM-Enter, and in general increases KVM's attack surface. A crafty userspace can even abuse CR4.LA57 to induce an unchecked #GP on a WRMSR.
On a platform without LA57 support:
KVM_SET_CPUID2 // CPUID_7_0_ECX.LA57 = 1
KVM_SET_SREGS // CR4.LA57 = 1
KVM_SET_MSRS // KERNEL_GS_BASE = 0x0004000000000000
KVM_RUN
leads to a #GP when writing KERNEL_GS_BASE into hardware:
unchecked MSR access error: WRMSR to 0xc0000102 (tried to write 0x0004000000000000) at rIP: 0xffffffffa00f239a (vmx_prepare_switch_to_guest+0x10a/0x1d0 [kvm_intel])
Call Trace: kvm_arch_vcpu_ioctl_run+0x671/0x1c70 [kvm] kvm_vcpu_ioctl+0x36b/0x5d0 [kvm] do_vfs_ioctl+0xa1/0x620 ksys_ioctl+0x66/0x70 __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x4c/0x170 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7fc08133bf47
Note, the above sequence fails VM-Enter due to invalid guest state. Userspace can allow VM-Enter to succeed (after the WRMSR #GP) by adding a KVM_SET_SREGS w/ CR4.LA57=0 after KVM_SET_MSRS, in which case KVM will technically leak the host's KERNEL_GS_BASE into the guest. But, as KERNEL_GS_BASE is a userspace-defined value/address, the leak is largely benign as a malicious userspace would simply be exposing its own data to the guest, and attacking a benevolent userspace would require multiple bugs in the userspace VMM.
--- arch/x86/kvm/x86.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-)
arch/x86/kvm/x86.c +34 -1
@@ -92,6 +92,8 @@ u64 __read_mostly efer_reserved_bits = ~static u64 __read_mostly efer_reserved_bits = ~((u64 )EFER_SCE );#endif +static u64 __read_mostly cr4_reserved_bits =CR4_RESERVED_BITS ; +#define VM_STAT (x, ...) offsetof(struct kvm, stat.x), KVM_STAT_VM, ## __VA_ARGS__#define VCPU_STAT (x, ...) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU, ## __VA_ARGS__
@@ -793,9 +795,38 @@ int kvm_set_xcr(struct kvm_vcpu *vcpu, u }EXPORT_SYMBOL_GPL (kvm_set_xcr); +static u64 kvm_host_cr4_reserved_bits (struct cpuinfo_x86 *c) +{ +u64 reserved_bits =CR4_RESERVED_BITS ; + +if (!cpu_has (c,X86_FEATURE_XSAVE )) + reserved_bits |=X86_CR4_OSXSAVE ; + +if (!cpu_has (c,X86_FEATURE_SMEP )) + reserved_bits |=X86_CR4_SMEP ; + +if (!cpu_has (c,X86_FEATURE_SMAP )) + reserved_bits |=X86_CR4_SMAP ; + +if (!cpu_has (c,X86_FEATURE_FSGSBASE )) + reserved_bits |=X86_CR4_FSGSBASE ; + +if (!cpu_has (c,X86_FEATURE_PKU )) + reserved_bits |=X86_CR4_PKE ; + +if (!cpu_has (c,X86_FEATURE_LA57 ) && + !(cpuid_ecx (0x7 ) &bit (X86_FEATURE_LA57 ))) + reserved_bits |=X86_CR4_LA57 ; + +if (!cpu_has (c,X86_FEATURE_UMIP ) && !kvm_x86_ops->umip_emulated ()) + reserved_bits |=X86_CR4_UMIP ; + +return reserved_bits; +} +static int kvm_valid_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4) { -if (cr4 &CR4_RESERVED_BITS ) +if (cr4 & cr4_reserved_bits)return -EINVAL ;if (!guest_cpuid_has (vcpu,X86_FEATURE_XSAVE ) && (cr4 &X86_CR4_OSXSAVE ))
@@ -8864,6 +8895,8 @@ int kvm_arch_hardware_setup(void)if (r !=0 )return r; + cr4_reserved_bits =kvm_host_cr4_reserved_bits (&boot_cpu_data); +if (kvm_has_tsc_control) {/* * Make sure the user can only configure tsc_khz values that