-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmPCczkACgkQONu9yGCS aT4tnRAAsW8h/ohmhP+O2lQ9Ekw6s9VB6KB4aJzLhQXqIZlrzk2DP3CiLxQ7DkFc AcHwFYq+sERo8O7dK6pbCW0zNvLUpbK2wJhwMHujJfSUFboXX85NR6u90U67pBKS p+yVkDSx8LNc7c676xQ7ey5rO1K2fQQ266gexjI9WOkjIFOfplVkZ7tkvt51VwAD mNvOQsZdCE6xs+T3t9YMOtAx3wW8vl1wW3QDWCHznQwOJiMEjfNEOUY/+xELnnWz DVONWPHTFNKQHZwIuVUFZdNuORq5WXoIaMZdaEFkhuOtRMnQ9l+wi8iMxX8zkgBn Ji/dPu3GdAZsJU4/rXHkY2AeZV1oJc3NLYmevoRZirTqMQCqyM+blif7Rf34kBi7 6jlGPWOjyMNe58shfHmjWTl/u4pMDoYOnm5XO+1oL+2Xg8QWCucqAlfPFB3uMh6n aL4ymzo5QRy1+tx8v7o1NOjnGWydvYn3O4fwJVkYTFaJZZr9EI7gpTmEBw/gwfuf 4TH6BC++Ai/8vgKUhpdnWuTrjomWalPTcPBgQYG4gD7ak2TM1rmgMaCl/THUe36R zPC8m2sIXKeI4zGi8TeqTgaRvFSKJnuEmVo5OPkG98fZkjekCzWHp0q1+PG2Ecy8 Mu2/AOnwb1aSfOJh2Qajoke/Wed0U6qszop8C/jPRh8D1uTmRbI= =sOTj -----END PGP SIGNATURE----- Merge 5.10.163 into android12-5.10-lts Changes in 5.10.163 usb: musb: remove extra check in musb_gadget_vbus_draw arm64: dts: qcom: ipq6018-cp01-c1: use BLSPI1 pins arm64: dts: qcom: msm8996: fix GPU OPP table ARM: dts: qcom: apq8064: fix coresight compatible arm64: dts: qcom: sdm630: fix UART1 pin bias arm64: dts: qcom: sdm845-cheza: fix AP suspend pin bias arm64: dts: qcom: msm8916: Drop MSS fallback compatible objtool, kcsan: Add volatile read/write instrumentation to whitelist ARM: dts: stm32: Drop stm32mp15xc.dtsi from Avenger96 ARM: dts: stm32: Fix AV96 WLAN regulator gpio property drivers: soc: ti: knav_qmss_queue: Mark knav_acc_firmwares as static soc: qcom: llcc: make irq truly optional soc: qcom: apr: make code more reuseable soc: qcom: apr: Add check for idr_alloc and of_property_read_string_index arm: dts: spear600: Fix clcd interrupt soc: ti: knav_qmss_queue: Use pm_runtime_resume_and_get instead of pm_runtime_get_sync soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in knav_queue_probe soc: ti: smartreflex: Fix PM disable depth imbalance in omap_sr_probe perf: arm_dsu: Fix hotplug callback leak in dsu_pmu_init() perf/smmuv3: Fix hotplug callback leak in arm_smmu_pmu_init() arm64: dts: ti: k3-am65-main: Drop dma-coherent in crypto node arm64: dts: ti: k3-j721e-main: Drop dma-coherent in crypto node arm64: dts: mt2712e: Fix unit_address_vs_reg warning for oscillators arm64: dts: mt2712e: Fix unit address for pinctrl node arm64: dts: mt2712-evb: Fix vproc fixed regulators unit names arm64: dts: mt2712-evb: Fix usb vbus regulators unit names arm64: dts: mediatek: pumpkin-common: Fix devicetree warnings arm64: dts: mediatek: mt6797: Fix 26M oscillator unit name ARM: dts: dove: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-370: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-xp: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-375: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-38x: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-39x: Fix assigned-addresses for every PCIe Root Port ARM: dts: turris-omnia: Add ethernet aliases ARM: dts: turris-omnia: Add switch port 6 node arm64: dts: armada-3720-turris-mox: Add missing interrupt for RTC pstore/ram: Fix error return code in ramoops_probe() ARM: mmp: fix timer_read delay pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP tpm/tpm_ftpm_tee: Fix error handling in ftpm_mod_init() tpm/tpm_crb: Fix error message in __crb_relinquish_locality() sched/fair: Cleanup task_util and capacity type sched/uclamp: Fix relationship between uclamp and migration margin cpuidle: dt: Return the correct numbers of parsed idle states alpha: fix syscall entry in !AUDUT_SYSCALL case PM: hibernate: Fix mistake in kerneldoc comment fs: don't audit the capability check in simple_xattr_list() cpufreq: qcom-hw: Fix memory leak in qcom_cpufreq_hw_read_lut() selftests/ftrace: event_triggers: wait longer for test_event_enable perf: Fix possible memleak in pmu_dev_alloc() lib/debugobjects: fix stat count and optimize debug_objects_mem_init platform/x86: huawei-wmi: fix return value calculation timerqueue: Use rb_entry_safe() in timerqueue_getnext() proc: fixup uptime selftest lib/fonts: fix undefined behavior in bit shift for get_default_font ocfs2: fix memory leak in ocfs2_stack_glue_init() MIPS: vpe-mt: fix possible memory leak while module exiting MIPS: vpe-cmp: fix possible memory leak while module exiting selftests/efivarfs: Add checking of the test return value PNP: fix name memory leak in pnp_alloc_dev() perf/x86/intel/uncore: Fix reference count leak in hswep_has_limit_sbox() perf/x86/intel/uncore: Fix reference count leak in snr_uncore_mmio_map() perf/x86/intel/uncore: Fix reference count leak in __uncore_imc_init_box() platform/chrome: cros_usbpd_notify: Fix error handling in cros_usbpd_notify_init() irqchip: gic-pm: Use pm_runtime_resume_and_get() in gic_probe() EDAC/i10nm: fix refcount leak in pci_get_dev_wrapper() nfsd: don't call nfsd_file_put from client states seqfile display genirq/irqdesc: Don't try to remove non-existing sysfs files cpufreq: amd_freq_sensitivity: Add missing pci_dev_put() libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value lib/notifier-error-inject: fix error when writing -errno to debugfs file docs: fault-injection: fix non-working usage of negative values debugfs: fix error when writing negative value to atomic_t debugfs file ocfs2: ocfs2_mount_volume does cleanup job before return error ocfs2: rewrite error handling of ocfs2_fill_super ocfs2: fix memory leak in ocfs2_mount_volume() rapidio: fix possible name leaks when rio_add_device() fails rapidio: rio: fix possible name leak in rio_register_mport() clocksource/drivers/sh_cmt: Make sure channel clock supply is enabled clocksource/drivers/sh_cmt: Access registers according to spec futex: Move to kernel/futex/ futex: Resend potentially swallowed owner death notification cpu/hotplug: Make target_store() a nop when target == state clocksource/drivers/timer-ti-dm: Fix missing clk_disable_unprepare in dmtimer_systimer_init_clock() ACPICA: Fix use-after-free in acpi_ut_copy_ipackage_to_ipackage() uprobes/x86: Allow to probe a NOP instruction with 0x66 prefix x86/xen: Fix memory leak in xen_smp_intr_init{_pv}() x86/xen: Fix memory leak in xen_init_lock_cpu() xen/privcmd: Fix a possible warning in privcmd_ioctl_mmap_resource() PM: runtime: Improve path in rpm_idle() when no callback PM: runtime: Do not call __rpm_callback() from rpm_idle() platform/x86: mxm-wmi: fix memleak in mxm_wmi_call_mx[ds|mx]() platform/x86: intel_scu_ipc: fix possible name leak in __intel_scu_ipc_register() MIPS: BCM63xx: Add check for NULL for clk in clk_enable MIPS: OCTEON: warn only once if deprecated link status is being used fs: sysv: Fix sysv_nblocks() returns wrong value rapidio: fix possible UAF when kfifo_alloc() fails eventfd: change int to __u64 in eventfd_signal() ifndef CONFIG_EVENTFD relay: fix type mismatch when allocating memory in relay_create_buf() hfs: Fix OOB Write in hfs_asc2mac rapidio: devices: fix missing put_device in mport_cdev_open wifi: ath9k: hif_usb: fix memory leak of urbs in ath9k_hif_usb_dealloc_tx_urbs() wifi: ath9k: hif_usb: Fix use-after-free in ath9k_hif_usb_reg_in_cb() wifi: rtl8xxxu: Fix reading the vendor of combo chips drm/bridge: adv7533: remove dynamic lane switching from adv7533 bridge libbpf: Fix use-after-free in btf_dump_name_dups libbpf: Fix null-pointer dereference in find_prog_by_sec_insn() pata_ipx4xx_cf: Fix unsigned comparison with less than zero media: coda: jpeg: Add check for kmalloc media: i2c: ad5820: Fix error path venus: pm_helpers: Fix error check in vcodec_domains_get() media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev media: exynos4-is: don't rely on the v4l2_async_subdev internals can: kvaser_usb: do not increase tx statistics when sending error message frames can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device can: kvaser_usb: kvaser_usb_leaf: Rename {leaf,usbcan}_cmd_error_event to {leaf,usbcan}_cmd_can_error_event can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT can: kvaser_usb_leaf: Set Warning state even without bus errors can: kvaser_usb_leaf: Fix improved state not being reported can: kvaser_usb_leaf: Fix wrong CAN state after stopping can: kvaser_usb_leaf: Fix bogus restart events can: kvaser_usb: Add struct kvaser_usb_busparams can: kvaser_usb: Compare requested bittiming parameters with actual parameters in do_set_{,data}_bittiming drm/rockchip: lvds: fix PM usage counter unbalance in poweron clk: renesas: r9a06g032: Repair grave increment error spi: Update reference to struct spi_controller drm/panel/panel-sitronix-st7701: Remove panel on DSI attach failure ima: Fix fall-through warnings for Clang ima: Handle -ESTALE returned by ima_filter_rule_match() drm/msm/hdmi: switch to drm_bridge_connector drm/msm/hdmi: drop unused GPIO support bpf: Fix slot type check in check_stack_write_var_off media: vivid: fix compose size exceed boundary media: platform: exynos4-is: fix return value check in fimc_md_probe() bpf: propagate precision in ALU/ALU64 operations bpf: Check the other end of slot_type for STACK_SPILL bpf: propagate precision across all frames, not just the last one clk: qcom: gcc-sm8250: Use retention mode for USB GDSCs mtd: Fix device name leak when register device failed in add_mtd_device() Input: joystick - fix Kconfig warning for JOYSTICK_ADC wifi: rsi: Fix handling of 802.3 EAPOL frames sent via control port media: camss: Clean up received buffers on failed start of streaming net, proc: Provide PROC_FS=n fallback for proc_create_net_single_write() rxrpc: Fix ack.bufferSize to be 0 when generating an ack drm/radeon: Add the missed acpi_put_table() to fix memory leak drm/mediatek: Modify dpi power on/off sequence. ASoC: pxa: fix null-pointer dereference in filter() regulator: core: fix unbalanced of node refcount in regulator_dev_lookup() amdgpu/pm: prevent array underflow in vega20_odn_edit_dpm_table() drm/fourcc: Add packed 10bit YUV 4:2:0 format drm/fourcc: Fix vsub/hsub for Q410 and Q401 integrity: Fix memory leakage in keyring allocation error path ima: Fix misuse of dereference of pointer in template_desc_init_fields() wifi: ath10k: Fix return value in ath10k_pci_init() mtd: lpddr2_nvm: Fix possible null-ptr-deref Input: elants_i2c - properly handle the reset GPIO when power is off media: vidtv: Fix use-after-free in vidtv_bridge_dvb_init() media: solo6x10: fix possible memory leak in solo_sysfs_init() media: platform: exynos4-is: Fix error handling in fimc_md_init() media: videobuf-dma-contig: use dma_mmap_coherent inet: add READ_ONCE(sk->sk_bound_dev_if) in inet_csk_bind_conflict() bpf: Move skb->len == 0 checks into __bpf_redirect HID: hid-sensor-custom: set fixed size for custom attributes ALSA: pcm: fix undefined behavior in bit shift for SNDRV_PCM_RATE_KNOT ALSA: seq: fix undefined behavior in bit shift for SNDRV_SEQ_FILTER_USE_EVENT regulator: core: use kfree_const() to free space conditionally clk: rockchip: Fix memory leak in rockchip_clk_register_pll() drm/amdgpu: fix pci device refcount leak bonding: fix link recovery in mode 2 when updelay is nonzero mtd: maps: pxa2xx-flash: fix memory leak in probe drbd: fix an invalid memory access caused by incorrect use of list iterator ASoC: qcom: Add checks for devm_kcalloc media: vimc: Fix wrong function called when vimc_init() fails media: imon: fix a race condition in send_packet() clk: imx: replace osc_hdmi with dummy pinctrl: pinconf-generic: add missing of_node_put() media: dvb-core: Fix ignored return value in dvb_register_frontend() media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer() media: s5p-mfc: Add variant data for MFC v7 hardware for Exynos 3250 SoC drm/tegra: Add missing clk_disable_unprepare() in tegra_dc_probe() ASoC: dt-bindings: wcd9335: fix reset line polarity in example ASoC: mediatek: mtk-btcvsd: Add checks for write and read of mtk_btcvsd_snd NFSv4.2: Clear FATTR4_WORD2_SECURITY_LABEL when done decoding NFSv4.2: Fix a memory stomp in decode_attr_security_label NFSv4.2: Fix initialisation of struct nfs4_label NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn NFS: Fix an Oops in nfs_d_automount() ALSA: asihpi: fix missing pci_disable_device() wifi: iwlwifi: mvm: fix double free on tx path. ASoC: mediatek: mt8173: Fix debugfs registration for components ASoC: mediatek: mt8173: Enable IRQ when pdata is ready drm/amd/pm/smu11: BACO is supported when it's in BACO state drm/radeon: Fix PCI device refcount leak in radeon_atrm_get_bios() drm/amdgpu: Fix PCI device refcount leak in amdgpu_atrm_get_bios() ASoC: pcm512x: Fix PM disable depth imbalance in pcm512x_probe netfilter: conntrack: set icmpv6 redirects as RELATED bpf, sockmap: Fix repeated calls to sock_put() when msg has more_data bpf, sockmap: Fix data loss caused by using apply_bytes on ingress redirect bonding: uninitialized variable in bond_miimon_inspect() spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE wifi: mac80211: fix memory leak in ieee80211_if_add() wifi: cfg80211: Fix not unregister reg_pdev when load_builtin_regdb_keys() fails wifi: mt76: fix coverity overrun-call in mt76_get_txpower() regulator: core: fix module refcount leak in set_supply() clk: qcom: clk-krait: fix wrong div2 functions hsr: Add a rcu-read lock to hsr_forward_skb(). net: hsr: generate supervision frame without HSR/PRP tag hsr: Disable netpoll. hsr: Synchronize sending frames to have always incremented outgoing seq nr. hsr: Synchronize sequence number updates. configfs: fix possible memory leak in configfs_create_dir() regulator: core: fix resource leak in regulator_register() hwmon: (jc42) Convert register access and caching to regmap/regcache hwmon: (jc42) Restore the min/max/critical temperatures on resume bpf, sockmap: fix race in sock_map_free() ALSA: pcm: Set missing stop_operating flag at undoing trigger start media: saa7164: fix missing pci_disable_device() ALSA: mts64: fix possible null-ptr-defer in snd_mts64_interrupt xprtrdma: Fix regbuf data not freed in rpcrdma_req_create() SUNRPC: Fix missing release socket in rpc_sockname() NFSv4.x: Fail client initialisation if state manager thread can't run mmc: alcor: fix return value check of mmc_add_host() mmc: moxart: fix return value check of mmc_add_host() mmc: mxcmmc: fix return value check of mmc_add_host() mmc: pxamci: fix return value check of mmc_add_host() mmc: rtsx_usb_sdmmc: fix return value check of mmc_add_host() mmc: toshsd: fix return value check of mmc_add_host() mmc: vub300: fix return value check of mmc_add_host() mmc: wmt-sdmmc: fix return value check of mmc_add_host() mmc: atmel-mci: fix return value check of mmc_add_host() mmc: omap_hsmmc: fix return value check of mmc_add_host() mmc: meson-gx: fix return value check of mmc_add_host() mmc: via-sdmmc: fix return value check of mmc_add_host() mmc: wbsd: fix return value check of mmc_add_host() mmc: mmci: fix return value check of mmc_add_host() media: c8sectpfe: Add of_node_put() when breaking out of loop media: coda: Add check for dcoda_iram_alloc media: coda: Add check for kmalloc clk: samsung: Fix memory leak in _samsung_clk_register_pll() spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode wifi: rtl8xxxu: Add __packed to struct rtl8723bu_c2h wifi: rtl8xxxu: Fix the channel width reporting wifi: brcmfmac: Fix error return code in brcmf_sdio_download_firmware() blktrace: Fix output non-blktrace event when blk_classic option enabled clk: socfpga: clk-pll: Remove unused variable 'rc' clk: socfpga: use clk_hw_register for a5/c5 clk: socfpga: Fix memory leak in socfpga_gate_init() net: vmw_vsock: vmci: Check memcpy_from_msg() net: defxx: Fix missing err handling in dfx_init() net: stmmac: selftests: fix potential memleak in stmmac_test_arpoffload() drivers: net: qlcnic: Fix potential memory leak in qlcnic_sriov_init() of: overlay: fix null pointer dereferencing in find_dup_cset_node_entry() and find_dup_cset_prop() ethernet: s2io: don't call dev_kfree_skb() under spin_lock_irqsave() net: farsync: Fix kmemleak when rmmods farsync net/tunnel: wait until all sk_user_data reader finish before releasing the sock net: apple: mace: don't call dev_kfree_skb() under spin_lock_irqsave() net: apple: bmac: don't call dev_kfree_skb() under spin_lock_irqsave() net: emaclite: don't call dev_kfree_skb() under spin_lock_irqsave() net: ethernet: dnet: don't call dev_kfree_skb() under spin_lock_irqsave() hamradio: don't call dev_kfree_skb() under spin_lock_irqsave() net: amd: lance: don't call dev_kfree_skb() under spin_lock_irqsave() net: amd-xgbe: Fix logic around active and passive cables net: amd-xgbe: Check only the minimum speed for active/passive cables can: tcan4x5x: Remove invalid write in clear_interrupts net: lan9303: Fix read error execution path ntb_netdev: Use dev_kfree_skb_any() in interrupt context sctp: sysctl: make extra pointers netns aware Bluetooth: btusb: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_qca: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_ll: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_bcsp: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_core: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: RFCOMM: don't call kfree_skb() under spin_lock_irqsave() stmmac: fix potential division by 0 apparmor: fix a memleak in multi_transaction_new() apparmor: fix lockdep warning when removing a namespace apparmor: Fix abi check to include v8 abi crypto: sun8i-ss - use dma_addr instead u32 crypto: nitrox - avoid double free on error path in nitrox_sriov_init() scsi: core: Fix a race between scsi_done() and scsi_timeout() apparmor: Use pointer to struct aa_label for lbs_cred PCI: dwc: Fix n_fts[] array overrun RDMA/core: Fix order of nldev_exit call PCI: pci-epf-test: Register notifier if only core_init_notifier is enabled f2fs: Fix the race condition of resize flag between resizefs crypto: rockchip - do not do custom power management crypto: rockchip - do not store mode globally crypto: rockchip - add fallback for cipher crypto: rockchip - add fallback for ahash crypto: rockchip - better handle cipher key crypto: rockchip - remove non-aligned handling crypto: rockchip - delete unneeded variable initialization crypto: rockchip - rework by using crypto_engine apparmor: Fix memleak in alloc_ns() f2fs: fix normal discard process RDMA/siw: Fix immediate work request flush to completion queue RDMA/nldev: Return "-EAGAIN" if the cm_id isn't from expected port RDMA/siw: Set defined status for work completion with undefined status scsi: scsi_debug: Fix a warning in resp_write_scat() crypto: ccree - Remove debugfs when platform_driver_register failed crypto: cryptd - Use request context instead of stack for sub-request crypto: hisilicon/qm - add missing pci_dev_put() in q_num_set() RDMA/hns: Repacing 'dseg_len' by macros in fill_ext_sge_inl_data() RDMA/hns: Fix ext_sge num error when post send PCI: Check for alloc failure in pci_request_irq() RDMA/hfi: Decrease PCI device reference count in error path crypto: ccree - Make cc_debugfs_global_fini() available for module init function RDMA/hns: fix memory leak in hns_roce_alloc_mr() RDMA/rxe: Fix NULL-ptr-deref in rxe_qp_do_cleanup() when socket create failed scsi: hpsa: Fix possible memory leak in hpsa_init_one() crypto: tcrypt - Fix multibuffer skcipher speed test mem leak padata: Always leave BHs disabled when running ->parallel() padata: Fix list iterator in padata_do_serial() scsi: mpt3sas: Fix possible resource leaks in mpt3sas_transport_port_add() scsi: hpsa: Fix error handling in hpsa_add_sas_host() scsi: hpsa: Fix possible memory leak in hpsa_add_sas_device() scsi: scsi_debug: Fix a warning in resp_verify() scsi: scsi_debug: Fix a warning in resp_report_zones() scsi: fcoe: Fix possible name leak when device_register() fails scsi: scsi_debug: Fix possible name leak in sdebug_add_host_helper() scsi: ipr: Fix WARNING in ipr_init() scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails scsi: snic: Fix possible UAF in snic_tgt_create() RDMA/nldev: Add checks for nla_nest_start() in fill_stat_counter_qps() f2fs: avoid victim selection from previous victim section RDMA/nldev: Fix failure to send large messages crypto: amlogic - Remove kcalloc without check crypto: omap-sham - Use pm_runtime_resume_and_get() in omap_sham_probe() riscv/mm: add arch hook arch_clear_hugepage_flags RDMA/hfi1: Fix error return code in parse_platform_config() RDMA/srp: Fix error return code in srp_parse_options() orangefs: Fix sysfs not cleanup when dev init failed RDMA/hns: Fix PBL page MTR find RDMA/hns: Fix page size cap from firmware crypto: img-hash - Fix variable dereferenced before check 'hdev->req' hwrng: amd - Fix PCI device refcount leak hwrng: geode - Fix PCI device refcount leak IB/IPoIB: Fix queue count inconsistency for PKEY child interfaces drivers: dio: fix possible memory leak in dio_init() serial: tegra: Read DMA status before terminating class: fix possible memory leak in __class_register() vfio: platform: Do not pass return buffer to ACPI _RST method uio: uio_dmem_genirq: Fix missing unlock in irq configuration uio: uio_dmem_genirq: Fix deadlock between irq config and handling usb: fotg210-udc: Fix ages old endianness issues staging: vme_user: Fix possible UAF in tsi148_dma_list_add usb: typec: Check for ops->exit instead of ops->enter in altmode_exit usb: typec: tcpci: fix of node refcount leak in tcpci_register_port() usb: typec: tipd: Fix spurious fwnode_handle_put in error path serial: amba-pl011: avoid SBSA UART accessing DMACR register serial: pl011: Do not clear RX FIFO & RX interrupt in unthrottle. serial: pch: Fix PCI device refcount leak in pch_request_dma() tty: serial: clean up stop-tx part in altera_uart_tx_chars() tty: serial: altera_uart_{r,t}x_chars() need only uart_port serial: altera_uart: fix locking in polling mode serial: sunsab: Fix error handling in sunsab_init() test_firmware: fix memory leak in test_firmware_init() misc: ocxl: fix possible name leak in ocxl_file_register_afu() ocxl: fix pci device refcount leak when calling get_function_0() misc: tifm: fix possible memory leak in tifm_7xx1_switch_media() misc: sgi-gru: fix use-after-free error in gru_set_context_option, gru_fault and gru_handle_user_call_os firmware: raspberrypi: fix possible memory leak in rpi_firmware_probe() cxl: fix possible null-ptr-deref in cxl_guest_init_afu|adapter() cxl: fix possible null-ptr-deref in cxl_pci_init_afu|adapter() iio: temperature: ltc2983: make bulk write buffer DMA-safe genirq: Add IRQF_NO_AUTOEN for request_irq/nmi() iio:imu:adis: Use IRQF_NO_AUTOEN instead of irq request then disable iio: adis: handle devices that cannot unmask the drdy pin iio: adis: stylistic changes iio:imu:adis: Move exports into IIO_ADISLIB namespace iio: adis: add '__adis_enable_irq()' implementation counter: stm32-lptimer-cnt: fix the check on arr and cmp registers update usb: roles: fix of node refcount leak in usb_role_switch_is_parent() usb: gadget: f_hid: optional SETUP/SET_REPORT mode usb: gadget: f_hid: fix f_hidg lifetime vs cdev usb: gadget: f_hid: fix refcount leak on error path drivers: mcb: fix resource leak in mcb_probe() mcb: mcb-parse: fix error handing in chameleon_parse_gdd() chardev: fix error handling in cdev_device_add() i2c: pxa-pci: fix missing pci_disable_device() on error in ce4100_i2c_probe staging: rtl8192u: Fix use after free in ieee80211_rx() staging: rtl8192e: Fix potential use-after-free in rtllib_rx_Monitor() vme: Fix error not catched in fake_init() gpiolib: Get rid of redundant 'else' gpiolib: cdev: fix NULL-pointer dereferences i2c: mux: reg: check return value after calling platform_get_resource() i2c: ismt: Fix an out-of-bounds bug in ismt_access() usb: storage: Add check for kcalloc tracing/hist: Fix issue of losting command info in error_log samples: vfio-mdev: Fix missing pci_disable_device() in mdpy_fb_probe() thermal/drivers/imx8mm_thermal: Validate temperature range fbdev: ssd1307fb: Drop optional dependency fbdev: pm2fb: fix missing pci_disable_device() fbdev: via: Fix error in via_core_init() fbdev: vermilion: decrease reference count in error path fbdev: uvesafb: Fixes an error handling path in uvesafb_probe() HSI: omap_ssi_core: fix unbalanced pm_runtime_disable() HSI: omap_ssi_core: fix possible memory leak in ssi_probe() power: supply: fix residue sysfs file in error handle route of __power_supply_register() perf trace: Return error if a system call doesn't exist perf trace: Use macro RAW_SYSCALL_ARGS_NUM to replace number perf trace: Handle failure when trace point folder is missed perf symbol: correction while adjusting symbol HSI: omap_ssi_core: Fix error handling in ssi_init() power: supply: fix null pointer dereferencing in power_supply_get_battery_info RDMA/siw: Fix pointer cast warning iommu/sun50i: Fix reset release iommu/sun50i: Consider all fault sources for reset iommu/sun50i: Fix R/W permission check iommu/sun50i: Fix flush size phy: usb: s2 WoL wakeup_count not incremented for USB->Eth devices include/uapi/linux/swab: Fix potentially missing __always_inline pwm: tegra: Improve required rate calculation dmaengine: idxd: Fix crc_val field for completion record rtc: rtc-cmos: Do not check ACPI_FADT_LOW_POWER_S0 rtc: cmos: Fix event handler registration ordering issue rtc: cmos: Fix wake alarm breakage rtc: cmos: fix build on non-ACPI platforms rtc: cmos: Call cmos_wake_setup() from cmos_do_probe() rtc: cmos: Call rtc_wake_setup() from cmos_do_probe() rtc: cmos: Eliminate forward declarations of some functions rtc: cmos: Rename ACPI-related functions rtc: cmos: Disable ACPI RTC event on removal rtc: snvs: Allow a time difference on clock register read rtc: pcf85063: Fix reading alarm iommu/amd: Fix pci device refcount leak in ppr_notifier() iommu/fsl_pamu: Fix resource leak in fsl_pamu_probe() macintosh: fix possible memory leak in macio_add_one_device() macintosh/macio-adb: check the return value of ioremap() powerpc/52xx: Fix a resource leak in an error handling path cxl: Fix refcount leak in cxl_calc_capp_routing powerpc/xmon: Enable breakpoints on 8xx powerpc/xmon: Fix -Wswitch-unreachable warning in bpt_cmds powerpc/xive: add missing iounmap() in error path in xive_spapr_populate_irq_data() kbuild: remove unneeded mkdir for external modules_install kbuild: unify modules(_install) for in-tree and external modules kbuild: refactor single builds of *.ko powerpc/perf: callchain validate kernel stack pointer bounds powerpc/83xx/mpc832x_rdb: call platform_device_put() in error case in of_fsl_spi_probe() powerpc/hv-gpci: Fix hv_gpci event list selftests/powerpc: Fix resource leaks iommu/sun50i: Remove IOMMU_DOMAIN_IDENTITY pwm: sifive: Call pwm_sifive_update_clock() while mutex is held remoteproc: sysmon: fix memory leak in qcom_add_sysmon_subdev() remoteproc: qcom_q6v5_pas: disable wakeup on probe fail or remove remoteproc: qcom_q6v5_pas: detach power domains on remove remoteproc: qcom_q6v5_pas: Fix missing of_node_put() in adsp_alloc_memory_region() powerpc/eeh: Drop redundant spinlock initialization powerpc/pseries/eeh: use correct API for error log size netfilter: flowtable: really fix NAT IPv6 offload rtc: st-lpc: Add missing clk_disable_unprepare in st_rtc_probe() rtc: pic32: Move devm_rtc_allocate_device earlier in pic32_rtc_probe() rtc: pcf85063: fix pcf85063_clkout_control NFSD: Remove spurious cb_setup_err tracepoint nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure net: macsec: fix net device access prior to holding a lock mISDN: hfcsusb: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave() mISDN: hfcpci: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave() mISDN: hfcmulti: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave() nfc: pn533: Clear nfc_target before being used r6040: Fix kmemleak in probe and remove net: switch to storing KCOV handle directly in sk_buff net: add inline function skb_csum_is_sctp net: igc: use skb_csum_is_sctp instead of protocol check net: add a helper to avoid issues with HW TX timestamping and SO_TXTIME igc: Enhance Qbv scheduling by using first flag bit igc: Use strict cycles for Qbv scheduling igc: Add checking for basetime less than zero igc: recalculate Qbv end_time by considering cycle time igc: Lift TAPRIO schedule restriction igc: Set Qbv start_time and end_time to end_time if not being configured in GCL rtc: mxc_v2: Add missing clk_disable_unprepare() selftests: devlink: fix the fd redirect in dummy_reporter_test openvswitch: Fix flow lookup to use unmasked key skbuff: Account for tail adjustment during pull operations mailbox: zynq-ipi: fix error handling while device_register() fails net_sched: reject TCF_EM_SIMPLE case for complex ematch module rxrpc: Fix missing unlock in rxrpc_do_sendmsg() myri10ge: Fix an error handling path in myri10ge_probe() net: stream: purge sk_error_queue in sk_stream_kill_queues() rcu: Fix __this_cpu_read() lockdep warning in rcu_force_quiescent_state() arm64: make is_ttbrX_addr() noinstr-safe video: hyperv_fb: Avoid taking busy spinlock on panic path x86/hyperv: Remove unregister syscore call from Hyper-V cleanup binfmt_misc: fix shift-out-of-bounds in check_special_flags fs: jfs: fix shift-out-of-bounds in dbAllocAG udf: Avoid double brelse() in udf_rename() fs: jfs: fix shift-out-of-bounds in dbDiscardAG ACPICA: Fix error code path in acpi_ds_call_control_method() nilfs2: fix shift-out-of-bounds/overflow in nilfs_sb2_bad_offset() nilfs2: fix shift-out-of-bounds due to too large exponent of block size acct: fix potential integer overflow in encode_comp_t() hfs: fix OOB Read in __hfs_brec_find drm/etnaviv: add missing quirks for GC300 brcmfmac: return error when getting invalid max_flowrings from dongle wifi: ath9k: verify the expected usb_endpoints are present wifi: ar5523: Fix use-after-free on ar5523_cmd() timed out ASoC: codecs: rt298: Add quirk for KBL-R RVP platform ipmi: fix memleak when unload ipmi driver drm/amd/display: prevent memory leak qed (gcc13): use u16 for fid to be big enough bpf: make sure skb->len != 0 when redirecting to a tunneling device net: ethernet: ti: Fix return type of netcp_ndo_start_xmit() hamradio: baycom_epp: Fix return type of baycom_send_packet() wifi: brcmfmac: Fix potential shift-out-of-bounds in brcmf_fw_alloc_request() igb: Do not free q_vector unless new one was allocated drm/amdgpu: Fix type of second parameter in trans_msg() callback drm/amdgpu: Fix type of second parameter in odn_edit_dpm_table() callback s390/ctcm: Fix return type of ctc{mp,}m_tx() s390/netiucv: Fix return type of netiucv_tx() s390/lcs: Fix return type of lcs_start_xmit() drm/msm: Use drm_mode_copy() drm/rockchip: Use drm_mode_copy() drm/sti: Use drm_mode_copy() drivers/md/md-bitmap: check the return value of md_bitmap_get_counter() md/raid1: stop mdx_raid1 thread when raid1 array run failed drm/amd/display: fix array index out of bound error in bios parser net: add atomic_long_t to net_device_stats fields mrp: introduce active flags to prevent UAF when applicant uninit ppp: associate skb with a device at tx bpf: Prevent decl_tag from being referenced in func_proto arg ethtool: avoiding integer overflow in ethtool_phys_id() media: dvb-frontends: fix leak of memory fw media: dvbdev: adopts refcnt to avoid UAF media: dvb-usb: fix memory leak in dvb_usb_adapter_init() blk-mq: fix possible memleak when register 'hctx' failed libbpf: Avoid enum forward-declarations in public API in C++ mode regulator: core: fix use_count leakage when handling boot-on mmc: f-sdh30: Add quirks for broken timeout clock capability mmc: renesas_sdhi: better reset from HS400 mode media: si470x: Fix use-after-free in si470x_int_in_callback() clk: st: Fix memory leak in st_of_quadfs_setup() hugetlbfs: fix null-ptr-deref in hugetlbfs_parse_param() drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid() drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid() orangefs: Fix kmemleak in orangefs_prepare_debugfs_help_string() orangefs: Fix kmemleak in orangefs_{kernel,client}_debug_init() hwmon: (jc42) Fix missing unlock on error in jc42_write() ALSA/ASoC: hda: move/rename snd_hdac_ext_stop_streams to hdac_stream.c ALSA: hda: add snd_hdac_stop_streams() helper ASoC: Intel: Skylake: Fix driver hang during shutdown ASoC: mediatek: mt8173-rt5650-rt5514: fix refcount leak in mt8173_rt5650_rt5514_dev_probe() ASoC: audio-graph-card: fix refcount leak of cpu_ep in __graph_for_each_link() ASoC: rockchip: pdm: Add missing clk_disable_unprepare() in rockchip_pdm_runtime_resume() ASoC: wm8994: Fix potential deadlock ASoC: rockchip: spdif: Add missing clk_disable_unprepare() in rk_spdif_runtime_resume() ASoC: rt5670: Remove unbalanced pm_runtime_put() LoadPin: Ignore the "contents" argument of the LSM hooks pstore: Switch pmsg_lock to an rt_mutex to avoid priority inversion perf debug: Set debug_peo_args and redirect_to_stderr variable to correct values in perf_quiet_option() afs: Fix lost servers_outstanding count pstore: Make sure CONFIG_PSTORE_PMSG selects CONFIG_RT_MUTEXES ima: Simplify ima_lsm_copy_rule ALSA: usb-audio: add the quirk for KT0206 device ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB ALSA: hda/hdmi: Add HP Device 0x8711 to force connect list usb: dwc3: Fix race between dwc3_set_mode and __dwc3_set_mode usb: dwc3: core: defer probe on ulpi_read_id timeout HID: wacom: Ensure bootloader PID is usable in hidraw mode HID: mcp2221: don't connect hidraw reiserfs: Add missing calls to reiserfs_security_free() iio: adc: ad_sigma_delta: do not use internal iio_dev lock iio: adc128s052: add proper .data members in adc128_of_match table regulator: core: fix deadlock on regulator enable gcov: add support for checksum field ovl: fix use inode directly in rcu-walk mode media: dvbdev: fix build warning due to comments media: dvbdev: fix refcnt bug pwm: tegra: Fix 32 bit build usb: dwc3: qcom: Fix memory leak in dwc3_qcom_interconnect_init cifs: fix oops during encryption nvme-pci: fix doorbell buffer value endianness nvme-pci: fix mempool alloc size nvme-pci: fix page size checks ata: ahci: Fix PCS quirk application for suspend nvme: fix the NVME_CMD_EFFECTS_CSE_MASK definition nvmet: don't defer passthrough commands with trivial effects to the workqueue objtool: Fix SEGFAULT powerpc/rtas: avoid device tree lookups in rtas_os_term() powerpc/rtas: avoid scheduling in rtas_os_term() HID: multitouch: fix Asus ExpertBook P2 P2451FA trackpoint HID: plantronics: Additional PIDs for double volume key presses quirk pstore/zone: Use GFP_ATOMIC to allocate zone buffer hfsplus: fix bug causing custom uid and gid being unable to be assigned with mount binfmt: Fix error return code in load_elf_fdpic_binary() ovl: Use ovl mounter's fsuid and fsgid in ovl_link() ALSA: line6: correct midi status byte when receiving data from podxt ALSA: line6: fix stack overflow in line6_midi_transmit pnode: terminate at peers of source md: fix a crash in mempool_free mm, compaction: fix fast_isolate_around() to stay within boundaries f2fs: should put a page when checking the summary info mmc: vub300: fix warning - do not call blocking ops when !TASK_RUNNING tpm: acpi: Call acpi_put_table() to fix memory leak tpm: tpm_crb: Add the missed acpi_put_table() to fix memory leak tpm: tpm_tis: Add the missed acpi_put_table() to fix memory leak SUNRPC: Don't leak netobj memory when gss_read_proxy_verf() fails kcsan: Instrument memcpy/memset/memmove with newer Clang ASoC: Intel/SOF: use set_stream() instead of set_tdm_slots() for HDAudio ASoC/SoundWire: dai: expand 'stream' concept beyond SoundWire net/mlx5e: Fix nullptr in mlx5e_tc_add_fdb_flow() wifi: rtlwifi: remove always-true condition pointed out by GCC 12 wifi: rtlwifi: 8192de: correct checking of IQK reload torture: Exclude "NOHZ tick-stop error" from fatal errors rcu: Prevent lockdep-RCU splats on lock acquisition/release net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO net/af_packet: make sure to pull mac header media: stv0288: use explicitly signed char soc: qcom: Select REMAP_MMIO for LLCC driver kest.pl: Fix grub2 menu handling for rebooting ktest.pl minconfig: Unset configs instead of just removing them jbd2: use the correct print format arm64: dts: qcom: sdm845-db845c: correct SPI2 pins drive strength mmc: sdhci-sprd: Disable CLK_AUTO when the clock is less than 400K btrfs: fix resolving backrefs for inline extent followed by prealloc ARM: ux500: do not directly dereference __iomem arm64: dts: qcom: sdm850-lenovo-yoga-c630: correct I2C12 pins drive strength selftests: Use optional USERCFLAGS and USERLDFLAGS PM/devfreq: governor: Add a private governor_data for governor cpufreq: Init completion before kobject_init_and_add() ALSA: patch_realtek: Fix Dell Inspiron Plus 16 ALSA: hda/realtek: Apply dual codec fixup for Dell Latitude laptops dm cache: Fix ABBA deadlock between shrink_slab and dm_cache_metadata_abort dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata dm thin: Use last transaction's pmd->root when commit failed dm thin: resume even if in FAIL mode dm thin: Fix UAF in run_timer_softirq() dm integrity: Fix UAF in dm_integrity_dtr() dm clone: Fix UAF in clone_dtr() dm cache: Fix UAF in destroy() dm cache: set needs_check flag after aborting metadata tracing/hist: Fix out-of-bound write on 'action_data.var_ref_idx' perf/core: Call LSM hook after copying perf_event_attr KVM: nVMX: Inject #GP, not #UD, if "generic" VMXON CR0/CR4 check fails x86/microcode/intel: Do not retry microcode reloading on the APs ftrace/x86: Add back ftrace_expected for ftrace bug reports x86/kprobes: Fix kprobes instruction boudary check with CONFIG_RETHUNK tracing/hist: Fix wrong return value in parse_action_params() tracing: Fix infinite loop in tracing_read_pipe on overflowed print_trace_line staging: media: tegra-video: fix chan->mipi value on error ARM: 9256/1: NWFPE: avoid compiler-generated __aeabi_uldivmod media: dvb-core: Fix double free in dvb_register_device() media: dvb-core: Fix UAF due to refcount races at releasing cifs: fix confusing debug message cifs: fix missing display of three mount options rtc: ds1347: fix value written to century register md/bitmap: Fix bitmap chunk size overflow issues efi: Add iMac Pro 2017 to uefi skip cert quirk wifi: wilc1000: sdio: fix module autoloading ASoC: jz4740-i2s: Handle independent FIFO flush bits ipmi: fix long wait in unload when IPMI disconnect mtd: spi-nor: Check for zero erase size in spi_nor_find_best_erase_type() ima: Fix a potential NULL pointer access in ima_restore_measurement_list ipmi: fix use after free in _ipmi_destroy_user() PCI: Fix pci_device_is_present() for VFs by checking PF PCI/sysfs: Fix double free in error path crypto: n2 - add missing hash statesize driver core: Fix bus_type.match() error handling in __driver_attach() iommu/amd: Fix ivrs_acpihid cmdline parsing code remoteproc: core: Do pm_relax when in RPROC_OFFLINE state parisc: led: Fix potential null-ptr-deref in start_task() device_cgroup: Roll back to original exceptions after copy failure drm/connector: send hotplug uevent on connector cleanup drm/vmwgfx: Validate the box size for the snooped cursor drm/i915/dsi: fix VBT send packet port selection for dual link DSI drm/ingenic: Fix missing platform_driver_unregister() call in ingenic_drm_init() ext4: silence the warning when evicting inode with dioread_nolock ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop ext4: fix use-after-free in ext4_orphan_cleanup ext4: fix undefined behavior in bit shift for ext4_check_flag_values ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode ext4: add helper to check quota inums ext4: fix bug_on in __es_tree_search caused by bad quota inode ext4: fix reserved cluster accounting in __es_remove_extent() ext4: check and assert if marking an no_delete evicting inode dirty ext4: fix bug_on in __es_tree_search caused by bad boot loader inode ext4: init quota for 'old.inode' in 'ext4_rename' ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline ext4: fix corruption when online resizing a 1K bigalloc fs ext4: fix error code return to user-space in ext4_get_branch() ext4: avoid BUG_ON when creating xattrs ext4: fix inode leak in ext4_xattr_inode_create() on an error path ext4: initialize quota before expanding inode in setproject ioctl ext4: avoid unaccounted block allocation when expanding inode ext4: allocate extended attribute value in vmalloc area drm/amdgpu: handle polaris10/11 overlap asics (v2) drm/amdgpu: make display pinning more flexible (v2) ARM: renumber bits related to _TIF_WORK_MASK perf/x86/intel/uncore: Generalize I/O stacks to PMON mapping procedure perf/x86/intel/uncore: Clear attr_update properly btrfs: replace strncpy() with strscpy() x86/mce: Get rid of msr_ops x86/MCE/AMD: Clear DFR errors found in THR handler media: s5p-mfc: Fix to handle reference queue during finishing media: s5p-mfc: Clear workbit to handle error condition media: s5p-mfc: Fix in register read and write for H264 perf probe: Use dwarf_attr_integrate as generic DWARF attr accessor perf probe: Fix to get the DW_AT_decl_file and DW_AT_call_file as unsinged data x86/kprobes: Convert to insn_decode() x86/kprobes: Fix optprobe optimization check with CONFIG_RETHUNK staging: media: tegra-video: fix device_node use after free ravb: Fix "failed to switch device to config mode" message during unbind riscv/stacktrace: Fix stack output without ra on the stack top riscv: stacktrace: Fixup ftrace_graph_ret_addr retp argument ext4: goto right label 'failed_mount3a' ext4: correct inconsistent error msg in nojournal mode mm/highmem: Lift memcpy_[to|from]_page to core ext4: use memcpy_to_page() in pagecache_write() fs: ext4: initialize fsdata in pagecache_write() ext4: move functions in super.c ext4: simplify ext4 error translation ext4: fix various seppling typos ext4: fix leaking uninitialized memory in fast-commit journal ext4: use kmemdup() to replace kmalloc + memcpy mbcache: don't reclaim used entries mbcache: add functions to delete entry if unused ext4: remove EA inode entry from mbcache on inode eviction ext4: unindent codeblock in ext4_xattr_block_set() ext4: fix race when reusing xattr blocks mbcache: automatically delete entries from cache on freeing ext4: fix deadlock due to mbcache entry corruption SUNRPC: ensure the matching upcall is in-flight upon downcall bpf: pull before calling skb_postpull_rcsum() drm/panfrost: Fix GEM handle creation ref-counting vmxnet3: correctly report csum_level for encapsulated packet veth: Fix race with AF_XDP exposing old or uninitialized descriptors nfsd: shut down the NFSv4 state objects before the filecache net: hns3: add interrupts re-initialization while doing VF FLR net: sched: fix memory leak in tcindex_set_parms qlcnic: prevent ->dcb use-after-free on qlcnic_dcb_enable() failure nfc: Fix potential resource leaks vhost/vsock: Fix error handling in vhost_vsock_init() vringh: fix range used in iotlb_translate() vhost: fix range used in translate_desc() net/mlx5: Add forgotten cleanup calls into mlx5_init_once() error path net/mlx5: Avoid recovery in probe flows net/mlx5e: IPoIB, Don't allow CQE compression to be turned on by default net/mlx5e: Fix hw mtu initializing at XDP SQ allocation net: amd-xgbe: add missed tasklet_kill net: phy: xgmiitorgmii: Fix refcount leak in xgmiitorgmii_probe RDMA/mlx5: Fix validation of max_rd_atomic caps for DC drm/meson: Reduce the FIFO lines held when AFBC is not used filelock: new helper: vfs_inode_has_locks ceph: switch to vfs_inode_has_locks() to fix file lock bug gpio: sifive: Fix refcount leak in sifive_gpio_probe net: sched: atm: dont intepret cls results when asked to drop net: sched: cbq: dont intepret cls results when asked to drop netfilter: ipset: fix hash:net,port,net hang with /0 subnet netfilter: ipset: Rework long task execution when adding/deleting entries perf tools: Fix resources leak in perf_data__open_dir() drivers/net/bonding/bond_3ad: return when there's no aggregator usb: rndis_host: Secure rndis_query check against int overflow drm/i915: unpin on error in intel_vgpu_shadow_mm_pin() caif: fix memory leak in cfctrl_linkup_request() udf: Fix extension of the last extent in the file ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 tablet nvme: fix multipath crash caused by flush request when blktrace is enabled x86/bugs: Flush IBP in ib_prctl_set() nfsd: fix handling of readdir in v4root vs. mount upcall timeout fbdev: matroxfb: G200eW: Increase max memory from 1 MB to 16 MB riscv: uaccess: fix type of 0 variable on error in get_user() drm/i915/gvt: fix gvt debugfs destroy drm/i915/gvt: fix vgpu debugfs clean in remove ext4: don't allow journal inode to have encrypt flag selftests: set the BUILD variable to absolute path hfs/hfsplus: use WARN_ON for sanity check hfs/hfsplus: avoid WARN_ON() for sanity check, use proper error handling mbcache: Avoid nesting of cache->c_list_lock under bit locks efi: random: combine bootloader provided RNG seed with RNG protocol output io_uring: Fix unsigned 'res' comparison with zero in io_fixup_rw_res() parisc: Align parisc MADV_XXX constants with all other architectures ext4: disable fast-commit of encrypted dir operations ext4: don't set up encryption key during jbd2 transaction fsl_lpuart: Don't enable interrupts too early serial: fixup backport of "serial: Deassert Transmit Enable on probe in driver-specific way" mptcp: mark ops structures as ro_after_init mptcp: remove MPTCP 'ifdef' in TCP SYN cookies mptcp: dedicated request sock for subflow in v6 mptcp: use proper req destructor for IPv6 net: sched: disallow noqueue for qdisc classes net/ulp: prevent ULP without clone op from entering the LISTEN status ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF ALSA: hda/hdmi: Add a HP device 0x8715 to force connect list ALSA: hda - Enable headset mic on another Dell laptop with ALC3254 Linux 5.10.163 Change-Id: I9026971760be8484f1e1fa607f9f91243cc87785 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
1534 lines
40 KiB
C
1534 lines
40 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* fs/libfs.c
|
|
* Library for filesystems writers.
|
|
*/
|
|
|
|
#include <linux/blkdev.h>
|
|
#include <linux/export.h>
|
|
#include <linux/pagemap.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/cred.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/vfs.h>
|
|
#include <linux/quotaops.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/namei.h>
|
|
#include <linux/exportfs.h>
|
|
#include <linux/writeback.h>
|
|
#include <linux/buffer_head.h> /* sync_mapping_buffers */
|
|
#include <linux/fs_context.h>
|
|
#include <linux/pseudo_fs.h>
|
|
#include <linux/fsnotify.h>
|
|
#include <linux/unicode.h>
|
|
#include <linux/fscrypt.h>
|
|
|
|
#include <linux/uaccess.h>
|
|
|
|
#include "internal.h"
|
|
|
|
int simple_getattr(const struct path *path, struct kstat *stat,
|
|
u32 request_mask, unsigned int query_flags)
|
|
{
|
|
struct inode *inode = d_inode(path->dentry);
|
|
generic_fillattr(inode, stat);
|
|
stat->blocks = inode->i_mapping->nrpages << (PAGE_SHIFT - 9);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_getattr);
|
|
|
|
int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|
{
|
|
buf->f_type = dentry->d_sb->s_magic;
|
|
buf->f_bsize = PAGE_SIZE;
|
|
buf->f_namelen = NAME_MAX;
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_statfs);
|
|
|
|
/*
|
|
* Retaining negative dentries for an in-memory filesystem just wastes
|
|
* memory and lookup time: arrange for them to be deleted immediately.
|
|
*/
|
|
int always_delete_dentry(const struct dentry *dentry)
|
|
{
|
|
return 1;
|
|
}
|
|
EXPORT_SYMBOL(always_delete_dentry);
|
|
|
|
const struct dentry_operations simple_dentry_operations = {
|
|
.d_delete = always_delete_dentry,
|
|
};
|
|
EXPORT_SYMBOL(simple_dentry_operations);
|
|
|
|
/*
|
|
* Lookup the data. This is trivial - if the dentry didn't already
|
|
* exist, we know it is negative. Set d_op to delete negative dentries.
|
|
*/
|
|
struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
|
|
{
|
|
if (dentry->d_name.len > NAME_MAX)
|
|
return ERR_PTR(-ENAMETOOLONG);
|
|
if (!dentry->d_sb->s_d_op)
|
|
d_set_d_op(dentry, &simple_dentry_operations);
|
|
d_add(dentry, NULL);
|
|
return NULL;
|
|
}
|
|
EXPORT_SYMBOL(simple_lookup);
|
|
|
|
int dcache_dir_open(struct inode *inode, struct file *file)
|
|
{
|
|
file->private_data = d_alloc_cursor(file->f_path.dentry);
|
|
|
|
return file->private_data ? 0 : -ENOMEM;
|
|
}
|
|
EXPORT_SYMBOL(dcache_dir_open);
|
|
|
|
int dcache_dir_close(struct inode *inode, struct file *file)
|
|
{
|
|
dput(file->private_data);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(dcache_dir_close);
|
|
|
|
/* parent is locked at least shared */
|
|
/*
|
|
* Returns an element of siblings' list.
|
|
* We are looking for <count>th positive after <p>; if
|
|
* found, dentry is grabbed and returned to caller.
|
|
* If no such element exists, NULL is returned.
|
|
*/
|
|
static struct dentry *scan_positives(struct dentry *cursor,
|
|
struct list_head *p,
|
|
loff_t count,
|
|
struct dentry *last)
|
|
{
|
|
struct dentry *dentry = cursor->d_parent, *found = NULL;
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
while ((p = p->next) != &dentry->d_subdirs) {
|
|
struct dentry *d = list_entry(p, struct dentry, d_child);
|
|
// we must at least skip cursors, to avoid livelocks
|
|
if (d->d_flags & DCACHE_DENTRY_CURSOR)
|
|
continue;
|
|
if (simple_positive(d) && !--count) {
|
|
spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
|
|
if (simple_positive(d))
|
|
found = dget_dlock(d);
|
|
spin_unlock(&d->d_lock);
|
|
if (likely(found))
|
|
break;
|
|
count = 1;
|
|
}
|
|
if (need_resched()) {
|
|
list_move(&cursor->d_child, p);
|
|
p = &cursor->d_child;
|
|
spin_unlock(&dentry->d_lock);
|
|
cond_resched();
|
|
spin_lock(&dentry->d_lock);
|
|
}
|
|
}
|
|
spin_unlock(&dentry->d_lock);
|
|
dput(last);
|
|
return found;
|
|
}
|
|
|
|
loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
|
|
{
|
|
struct dentry *dentry = file->f_path.dentry;
|
|
switch (whence) {
|
|
case 1:
|
|
offset += file->f_pos;
|
|
fallthrough;
|
|
case 0:
|
|
if (offset >= 0)
|
|
break;
|
|
fallthrough;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
if (offset != file->f_pos) {
|
|
struct dentry *cursor = file->private_data;
|
|
struct dentry *to = NULL;
|
|
|
|
inode_lock_shared(dentry->d_inode);
|
|
|
|
if (offset > 2)
|
|
to = scan_positives(cursor, &dentry->d_subdirs,
|
|
offset - 2, NULL);
|
|
spin_lock(&dentry->d_lock);
|
|
if (to)
|
|
list_move(&cursor->d_child, &to->d_child);
|
|
else
|
|
list_del_init(&cursor->d_child);
|
|
spin_unlock(&dentry->d_lock);
|
|
dput(to);
|
|
|
|
file->f_pos = offset;
|
|
|
|
inode_unlock_shared(dentry->d_inode);
|
|
}
|
|
return offset;
|
|
}
|
|
EXPORT_SYMBOL(dcache_dir_lseek);
|
|
|
|
/* Relationship between i_mode and the DT_xxx types */
|
|
static inline unsigned char dt_type(struct inode *inode)
|
|
{
|
|
return (inode->i_mode >> 12) & 15;
|
|
}
|
|
|
|
/*
|
|
* Directory is locked and all positive dentries in it are safe, since
|
|
* for ramfs-type trees they can't go away without unlink() or rmdir(),
|
|
* both impossible due to the lock on directory.
|
|
*/
|
|
|
|
int dcache_readdir(struct file *file, struct dir_context *ctx)
|
|
{
|
|
struct dentry *dentry = file->f_path.dentry;
|
|
struct dentry *cursor = file->private_data;
|
|
struct list_head *anchor = &dentry->d_subdirs;
|
|
struct dentry *next = NULL;
|
|
struct list_head *p;
|
|
|
|
if (!dir_emit_dots(file, ctx))
|
|
return 0;
|
|
|
|
if (ctx->pos == 2)
|
|
p = anchor;
|
|
else if (!list_empty(&cursor->d_child))
|
|
p = &cursor->d_child;
|
|
else
|
|
return 0;
|
|
|
|
while ((next = scan_positives(cursor, p, 1, next)) != NULL) {
|
|
if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
|
|
d_inode(next)->i_ino, dt_type(d_inode(next))))
|
|
break;
|
|
ctx->pos++;
|
|
p = &next->d_child;
|
|
}
|
|
spin_lock(&dentry->d_lock);
|
|
if (next)
|
|
list_move_tail(&cursor->d_child, &next->d_child);
|
|
else
|
|
list_del_init(&cursor->d_child);
|
|
spin_unlock(&dentry->d_lock);
|
|
dput(next);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(dcache_readdir);
|
|
|
|
ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t *ppos)
|
|
{
|
|
return -EISDIR;
|
|
}
|
|
EXPORT_SYMBOL_NS(generic_read_dir, ANDROID_GKI_VFS_EXPORT_ONLY);
|
|
|
|
const struct file_operations simple_dir_operations = {
|
|
.open = dcache_dir_open,
|
|
.release = dcache_dir_close,
|
|
.llseek = dcache_dir_lseek,
|
|
.read = generic_read_dir,
|
|
.iterate_shared = dcache_readdir,
|
|
.fsync = noop_fsync,
|
|
};
|
|
EXPORT_SYMBOL(simple_dir_operations);
|
|
|
|
const struct inode_operations simple_dir_inode_operations = {
|
|
.lookup = simple_lookup,
|
|
};
|
|
EXPORT_SYMBOL(simple_dir_inode_operations);
|
|
|
|
static struct dentry *find_next_child(struct dentry *parent, struct dentry *prev)
|
|
{
|
|
struct dentry *child = NULL;
|
|
struct list_head *p = prev ? &prev->d_child : &parent->d_subdirs;
|
|
|
|
spin_lock(&parent->d_lock);
|
|
while ((p = p->next) != &parent->d_subdirs) {
|
|
struct dentry *d = container_of(p, struct dentry, d_child);
|
|
if (simple_positive(d)) {
|
|
spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
|
|
if (simple_positive(d))
|
|
child = dget_dlock(d);
|
|
spin_unlock(&d->d_lock);
|
|
if (likely(child))
|
|
break;
|
|
}
|
|
}
|
|
spin_unlock(&parent->d_lock);
|
|
dput(prev);
|
|
return child;
|
|
}
|
|
|
|
void simple_recursive_removal(struct dentry *dentry,
|
|
void (*callback)(struct dentry *))
|
|
{
|
|
struct dentry *this = dget(dentry);
|
|
while (true) {
|
|
struct dentry *victim = NULL, *child;
|
|
struct inode *inode = this->d_inode;
|
|
|
|
inode_lock(inode);
|
|
if (d_is_dir(this))
|
|
inode->i_flags |= S_DEAD;
|
|
while ((child = find_next_child(this, victim)) == NULL) {
|
|
// kill and ascend
|
|
// update metadata while it's still locked
|
|
inode->i_ctime = current_time(inode);
|
|
clear_nlink(inode);
|
|
inode_unlock(inode);
|
|
victim = this;
|
|
this = this->d_parent;
|
|
inode = this->d_inode;
|
|
inode_lock(inode);
|
|
if (simple_positive(victim)) {
|
|
d_invalidate(victim); // avoid lost mounts
|
|
if (d_is_dir(victim))
|
|
fsnotify_rmdir(inode, victim);
|
|
else
|
|
fsnotify_unlink(inode, victim);
|
|
if (callback)
|
|
callback(victim);
|
|
dput(victim); // unpin it
|
|
}
|
|
if (victim == dentry) {
|
|
inode->i_ctime = inode->i_mtime =
|
|
current_time(inode);
|
|
if (d_is_dir(dentry))
|
|
drop_nlink(inode);
|
|
inode_unlock(inode);
|
|
dput(dentry);
|
|
return;
|
|
}
|
|
}
|
|
inode_unlock(inode);
|
|
this = child;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(simple_recursive_removal);
|
|
|
|
static const struct super_operations simple_super_operations = {
|
|
.statfs = simple_statfs,
|
|
};
|
|
|
|
static int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc)
|
|
{
|
|
struct pseudo_fs_context *ctx = fc->fs_private;
|
|
struct inode *root;
|
|
|
|
s->s_maxbytes = MAX_LFS_FILESIZE;
|
|
s->s_blocksize = PAGE_SIZE;
|
|
s->s_blocksize_bits = PAGE_SHIFT;
|
|
s->s_magic = ctx->magic;
|
|
s->s_op = ctx->ops ?: &simple_super_operations;
|
|
s->s_xattr = ctx->xattr;
|
|
s->s_time_gran = 1;
|
|
root = new_inode(s);
|
|
if (!root)
|
|
return -ENOMEM;
|
|
|
|
/*
|
|
* since this is the first inode, make it number 1. New inodes created
|
|
* after this must take care not to collide with it (by passing
|
|
* max_reserved of 1 to iunique).
|
|
*/
|
|
root->i_ino = 1;
|
|
root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
|
|
root->i_atime = root->i_mtime = root->i_ctime = current_time(root);
|
|
s->s_root = d_make_root(root);
|
|
if (!s->s_root)
|
|
return -ENOMEM;
|
|
s->s_d_op = ctx->dops;
|
|
return 0;
|
|
}
|
|
|
|
static int pseudo_fs_get_tree(struct fs_context *fc)
|
|
{
|
|
return get_tree_nodev(fc, pseudo_fs_fill_super);
|
|
}
|
|
|
|
static void pseudo_fs_free(struct fs_context *fc)
|
|
{
|
|
kfree(fc->fs_private);
|
|
}
|
|
|
|
static const struct fs_context_operations pseudo_fs_context_ops = {
|
|
.free = pseudo_fs_free,
|
|
.get_tree = pseudo_fs_get_tree,
|
|
};
|
|
|
|
/*
|
|
* Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
|
|
* will never be mountable)
|
|
*/
|
|
struct pseudo_fs_context *init_pseudo(struct fs_context *fc,
|
|
unsigned long magic)
|
|
{
|
|
struct pseudo_fs_context *ctx;
|
|
|
|
ctx = kzalloc(sizeof(struct pseudo_fs_context), GFP_KERNEL);
|
|
if (likely(ctx)) {
|
|
ctx->magic = magic;
|
|
fc->fs_private = ctx;
|
|
fc->ops = &pseudo_fs_context_ops;
|
|
fc->sb_flags |= SB_NOUSER;
|
|
fc->global = true;
|
|
}
|
|
return ctx;
|
|
}
|
|
EXPORT_SYMBOL(init_pseudo);
|
|
|
|
int simple_open(struct inode *inode, struct file *file)
|
|
{
|
|
if (inode->i_private)
|
|
file->private_data = inode->i_private;
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_open);
|
|
|
|
int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
|
|
{
|
|
struct inode *inode = d_inode(old_dentry);
|
|
|
|
inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
|
|
inc_nlink(inode);
|
|
ihold(inode);
|
|
dget(dentry);
|
|
d_instantiate(dentry, inode);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_link);
|
|
|
|
int simple_empty(struct dentry *dentry)
|
|
{
|
|
struct dentry *child;
|
|
int ret = 0;
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
list_for_each_entry(child, &dentry->d_subdirs, d_child) {
|
|
spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
|
|
if (simple_positive(child)) {
|
|
spin_unlock(&child->d_lock);
|
|
goto out;
|
|
}
|
|
spin_unlock(&child->d_lock);
|
|
}
|
|
ret = 1;
|
|
out:
|
|
spin_unlock(&dentry->d_lock);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(simple_empty);
|
|
|
|
int simple_unlink(struct inode *dir, struct dentry *dentry)
|
|
{
|
|
struct inode *inode = d_inode(dentry);
|
|
|
|
inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
|
|
drop_nlink(inode);
|
|
dput(dentry);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_unlink);
|
|
|
|
int simple_rmdir(struct inode *dir, struct dentry *dentry)
|
|
{
|
|
if (!simple_empty(dentry))
|
|
return -ENOTEMPTY;
|
|
|
|
drop_nlink(d_inode(dentry));
|
|
simple_unlink(dir, dentry);
|
|
drop_nlink(dir);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_rmdir);
|
|
|
|
int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
struct inode *new_dir, struct dentry *new_dentry,
|
|
unsigned int flags)
|
|
{
|
|
struct inode *inode = d_inode(old_dentry);
|
|
int they_are_dirs = d_is_dir(old_dentry);
|
|
|
|
if (flags & ~RENAME_NOREPLACE)
|
|
return -EINVAL;
|
|
|
|
if (!simple_empty(new_dentry))
|
|
return -ENOTEMPTY;
|
|
|
|
if (d_really_is_positive(new_dentry)) {
|
|
simple_unlink(new_dir, new_dentry);
|
|
if (they_are_dirs) {
|
|
drop_nlink(d_inode(new_dentry));
|
|
drop_nlink(old_dir);
|
|
}
|
|
} else if (they_are_dirs) {
|
|
drop_nlink(old_dir);
|
|
inc_nlink(new_dir);
|
|
}
|
|
|
|
old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
|
|
new_dir->i_mtime = inode->i_ctime = current_time(old_dir);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_rename);
|
|
|
|
/**
|
|
* simple_setattr - setattr for simple filesystem
|
|
* @dentry: dentry
|
|
* @iattr: iattr structure
|
|
*
|
|
* Returns 0 on success, -error on failure.
|
|
*
|
|
* simple_setattr is a simple ->setattr implementation without a proper
|
|
* implementation of size changes.
|
|
*
|
|
* It can either be used for in-memory filesystems or special files
|
|
* on simple regular filesystems. Anything that needs to change on-disk
|
|
* or wire state on size changes needs its own setattr method.
|
|
*/
|
|
int simple_setattr(struct dentry *dentry, struct iattr *iattr)
|
|
{
|
|
struct inode *inode = d_inode(dentry);
|
|
int error;
|
|
|
|
error = setattr_prepare(dentry, iattr);
|
|
if (error)
|
|
return error;
|
|
|
|
if (iattr->ia_valid & ATTR_SIZE)
|
|
truncate_setsize(inode, iattr->ia_size);
|
|
setattr_copy(inode, iattr);
|
|
mark_inode_dirty(inode);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_setattr);
|
|
|
|
int simple_readpage(struct file *file, struct page *page)
|
|
{
|
|
clear_highpage(page);
|
|
flush_dcache_page(page);
|
|
SetPageUptodate(page);
|
|
unlock_page(page);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_readpage);
|
|
|
|
int simple_write_begin(struct file *file, struct address_space *mapping,
|
|
loff_t pos, unsigned len, unsigned flags,
|
|
struct page **pagep, void **fsdata)
|
|
{
|
|
struct page *page;
|
|
pgoff_t index;
|
|
|
|
index = pos >> PAGE_SHIFT;
|
|
|
|
page = grab_cache_page_write_begin(mapping, index, flags);
|
|
if (!page)
|
|
return -ENOMEM;
|
|
|
|
*pagep = page;
|
|
|
|
if (!PageUptodate(page) && (len != PAGE_SIZE)) {
|
|
unsigned from = pos & (PAGE_SIZE - 1);
|
|
|
|
zero_user_segments(page, 0, from, from + len, PAGE_SIZE);
|
|
}
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_write_begin);
|
|
|
|
/**
|
|
* simple_write_end - .write_end helper for non-block-device FSes
|
|
* @file: See .write_end of address_space_operations
|
|
* @mapping: "
|
|
* @pos: "
|
|
* @len: "
|
|
* @copied: "
|
|
* @page: "
|
|
* @fsdata: "
|
|
*
|
|
* simple_write_end does the minimum needed for updating a page after writing is
|
|
* done. It has the same API signature as the .write_end of
|
|
* address_space_operations vector. So it can just be set onto .write_end for
|
|
* FSes that don't need any other processing. i_mutex is assumed to be held.
|
|
* Block based filesystems should use generic_write_end().
|
|
* NOTE: Even though i_size might get updated by this function, mark_inode_dirty
|
|
* is not called, so a filesystem that actually does store data in .write_inode
|
|
* should extend on what's done here with a call to mark_inode_dirty() in the
|
|
* case that i_size has changed.
|
|
*
|
|
* Use *ONLY* with simple_readpage()
|
|
*/
|
|
int simple_write_end(struct file *file, struct address_space *mapping,
|
|
loff_t pos, unsigned len, unsigned copied,
|
|
struct page *page, void *fsdata)
|
|
{
|
|
struct inode *inode = page->mapping->host;
|
|
loff_t last_pos = pos + copied;
|
|
|
|
/* zero the stale part of the page if we did a short copy */
|
|
if (!PageUptodate(page)) {
|
|
if (copied < len) {
|
|
unsigned from = pos & (PAGE_SIZE - 1);
|
|
|
|
zero_user(page, from + copied, len - copied);
|
|
}
|
|
SetPageUptodate(page);
|
|
}
|
|
/*
|
|
* No need to use i_size_read() here, the i_size
|
|
* cannot change under us because we hold the i_mutex.
|
|
*/
|
|
if (last_pos > inode->i_size)
|
|
i_size_write(inode, last_pos);
|
|
|
|
set_page_dirty(page);
|
|
unlock_page(page);
|
|
put_page(page);
|
|
|
|
return copied;
|
|
}
|
|
EXPORT_SYMBOL(simple_write_end);
|
|
|
|
/*
|
|
* the inodes created here are not hashed. If you use iunique to generate
|
|
* unique inode values later for this filesystem, then you must take care
|
|
* to pass it an appropriate max_reserved value to avoid collisions.
|
|
*/
|
|
int simple_fill_super(struct super_block *s, unsigned long magic,
|
|
const struct tree_descr *files)
|
|
{
|
|
struct inode *inode;
|
|
struct dentry *root;
|
|
struct dentry *dentry;
|
|
int i;
|
|
|
|
s->s_blocksize = PAGE_SIZE;
|
|
s->s_blocksize_bits = PAGE_SHIFT;
|
|
s->s_magic = magic;
|
|
s->s_op = &simple_super_operations;
|
|
s->s_time_gran = 1;
|
|
|
|
inode = new_inode(s);
|
|
if (!inode)
|
|
return -ENOMEM;
|
|
/*
|
|
* because the root inode is 1, the files array must not contain an
|
|
* entry at index 1
|
|
*/
|
|
inode->i_ino = 1;
|
|
inode->i_mode = S_IFDIR | 0755;
|
|
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
|
|
inode->i_op = &simple_dir_inode_operations;
|
|
inode->i_fop = &simple_dir_operations;
|
|
set_nlink(inode, 2);
|
|
root = d_make_root(inode);
|
|
if (!root)
|
|
return -ENOMEM;
|
|
for (i = 0; !files->name || files->name[0]; i++, files++) {
|
|
if (!files->name)
|
|
continue;
|
|
|
|
/* warn if it tries to conflict with the root inode */
|
|
if (unlikely(i == 1))
|
|
printk(KERN_WARNING "%s: %s passed in a files array"
|
|
"with an index of 1!\n", __func__,
|
|
s->s_type->name);
|
|
|
|
dentry = d_alloc_name(root, files->name);
|
|
if (!dentry)
|
|
goto out;
|
|
inode = new_inode(s);
|
|
if (!inode) {
|
|
dput(dentry);
|
|
goto out;
|
|
}
|
|
inode->i_mode = S_IFREG | files->mode;
|
|
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
|
|
inode->i_fop = files->ops;
|
|
inode->i_ino = i;
|
|
d_add(dentry, inode);
|
|
}
|
|
s->s_root = root;
|
|
return 0;
|
|
out:
|
|
d_genocide(root);
|
|
shrink_dcache_parent(root);
|
|
dput(root);
|
|
return -ENOMEM;
|
|
}
|
|
EXPORT_SYMBOL(simple_fill_super);
|
|
|
|
static DEFINE_SPINLOCK(pin_fs_lock);
|
|
|
|
int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)
|
|
{
|
|
struct vfsmount *mnt = NULL;
|
|
spin_lock(&pin_fs_lock);
|
|
if (unlikely(!*mount)) {
|
|
spin_unlock(&pin_fs_lock);
|
|
mnt = vfs_kern_mount(type, SB_KERNMOUNT, type->name, NULL);
|
|
if (IS_ERR(mnt))
|
|
return PTR_ERR(mnt);
|
|
spin_lock(&pin_fs_lock);
|
|
if (!*mount)
|
|
*mount = mnt;
|
|
}
|
|
mntget(*mount);
|
|
++*count;
|
|
spin_unlock(&pin_fs_lock);
|
|
mntput(mnt);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_pin_fs);
|
|
|
|
void simple_release_fs(struct vfsmount **mount, int *count)
|
|
{
|
|
struct vfsmount *mnt;
|
|
spin_lock(&pin_fs_lock);
|
|
mnt = *mount;
|
|
if (!--*count)
|
|
*mount = NULL;
|
|
spin_unlock(&pin_fs_lock);
|
|
mntput(mnt);
|
|
}
|
|
EXPORT_SYMBOL(simple_release_fs);
|
|
|
|
/**
|
|
* simple_read_from_buffer - copy data from the buffer to user space
|
|
* @to: the user space buffer to read to
|
|
* @count: the maximum number of bytes to read
|
|
* @ppos: the current position in the buffer
|
|
* @from: the buffer to read from
|
|
* @available: the size of the buffer
|
|
*
|
|
* The simple_read_from_buffer() function reads up to @count bytes from the
|
|
* buffer @from at offset @ppos into the user space address starting at @to.
|
|
*
|
|
* On success, the number of bytes read is returned and the offset @ppos is
|
|
* advanced by this number, or negative value is returned on error.
|
|
**/
|
|
ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
|
|
const void *from, size_t available)
|
|
{
|
|
loff_t pos = *ppos;
|
|
size_t ret;
|
|
|
|
if (pos < 0)
|
|
return -EINVAL;
|
|
if (pos >= available || !count)
|
|
return 0;
|
|
if (count > available - pos)
|
|
count = available - pos;
|
|
ret = copy_to_user(to, from + pos, count);
|
|
if (ret == count)
|
|
return -EFAULT;
|
|
count -= ret;
|
|
*ppos = pos + count;
|
|
return count;
|
|
}
|
|
EXPORT_SYMBOL(simple_read_from_buffer);
|
|
|
|
/**
|
|
* simple_write_to_buffer - copy data from user space to the buffer
|
|
* @to: the buffer to write to
|
|
* @available: the size of the buffer
|
|
* @ppos: the current position in the buffer
|
|
* @from: the user space buffer to read from
|
|
* @count: the maximum number of bytes to read
|
|
*
|
|
* The simple_write_to_buffer() function reads up to @count bytes from the user
|
|
* space address starting at @from into the buffer @to at offset @ppos.
|
|
*
|
|
* On success, the number of bytes written is returned and the offset @ppos is
|
|
* advanced by this number, or negative value is returned on error.
|
|
**/
|
|
ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
|
|
const void __user *from, size_t count)
|
|
{
|
|
loff_t pos = *ppos;
|
|
size_t res;
|
|
|
|
if (pos < 0)
|
|
return -EINVAL;
|
|
if (pos >= available || !count)
|
|
return 0;
|
|
if (count > available - pos)
|
|
count = available - pos;
|
|
res = copy_from_user(to + pos, from, count);
|
|
if (res == count)
|
|
return -EFAULT;
|
|
count -= res;
|
|
*ppos = pos + count;
|
|
return count;
|
|
}
|
|
EXPORT_SYMBOL(simple_write_to_buffer);
|
|
|
|
/**
|
|
* memory_read_from_buffer - copy data from the buffer
|
|
* @to: the kernel space buffer to read to
|
|
* @count: the maximum number of bytes to read
|
|
* @ppos: the current position in the buffer
|
|
* @from: the buffer to read from
|
|
* @available: the size of the buffer
|
|
*
|
|
* The memory_read_from_buffer() function reads up to @count bytes from the
|
|
* buffer @from at offset @ppos into the kernel space address starting at @to.
|
|
*
|
|
* On success, the number of bytes read is returned and the offset @ppos is
|
|
* advanced by this number, or negative value is returned on error.
|
|
**/
|
|
ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
|
|
const void *from, size_t available)
|
|
{
|
|
loff_t pos = *ppos;
|
|
|
|
if (pos < 0)
|
|
return -EINVAL;
|
|
if (pos >= available)
|
|
return 0;
|
|
if (count > available - pos)
|
|
count = available - pos;
|
|
memcpy(to, from + pos, count);
|
|
*ppos = pos + count;
|
|
|
|
return count;
|
|
}
|
|
EXPORT_SYMBOL(memory_read_from_buffer);
|
|
|
|
/*
|
|
* Transaction based IO.
|
|
* The file expects a single write which triggers the transaction, and then
|
|
* possibly a read which collects the result - which is stored in a
|
|
* file-local buffer.
|
|
*/
|
|
|
|
void simple_transaction_set(struct file *file, size_t n)
|
|
{
|
|
struct simple_transaction_argresp *ar = file->private_data;
|
|
|
|
BUG_ON(n > SIMPLE_TRANSACTION_LIMIT);
|
|
|
|
/*
|
|
* The barrier ensures that ar->size will really remain zero until
|
|
* ar->data is ready for reading.
|
|
*/
|
|
smp_mb();
|
|
ar->size = n;
|
|
}
|
|
EXPORT_SYMBOL(simple_transaction_set);
|
|
|
|
char *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
|
|
{
|
|
struct simple_transaction_argresp *ar;
|
|
static DEFINE_SPINLOCK(simple_transaction_lock);
|
|
|
|
if (size > SIMPLE_TRANSACTION_LIMIT - 1)
|
|
return ERR_PTR(-EFBIG);
|
|
|
|
ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL);
|
|
if (!ar)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
spin_lock(&simple_transaction_lock);
|
|
|
|
/* only one write allowed per open */
|
|
if (file->private_data) {
|
|
spin_unlock(&simple_transaction_lock);
|
|
free_page((unsigned long)ar);
|
|
return ERR_PTR(-EBUSY);
|
|
}
|
|
|
|
file->private_data = ar;
|
|
|
|
spin_unlock(&simple_transaction_lock);
|
|
|
|
if (copy_from_user(ar->data, buf, size))
|
|
return ERR_PTR(-EFAULT);
|
|
|
|
return ar->data;
|
|
}
|
|
EXPORT_SYMBOL(simple_transaction_get);
|
|
|
|
ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
|
|
{
|
|
struct simple_transaction_argresp *ar = file->private_data;
|
|
|
|
if (!ar)
|
|
return 0;
|
|
return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
|
|
}
|
|
EXPORT_SYMBOL(simple_transaction_read);
|
|
|
|
int simple_transaction_release(struct inode *inode, struct file *file)
|
|
{
|
|
free_page((unsigned long)file->private_data);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(simple_transaction_release);
|
|
|
|
/* Simple attribute files */
|
|
|
|
struct simple_attr {
|
|
int (*get)(void *, u64 *);
|
|
int (*set)(void *, u64);
|
|
char get_buf[24]; /* enough to store a u64 and "\n\0" */
|
|
char set_buf[24];
|
|
void *data;
|
|
const char *fmt; /* format for read operation */
|
|
struct mutex mutex; /* protects access to these buffers */
|
|
};
|
|
|
|
/* simple_attr_open is called by an actual attribute open file operation
|
|
* to set the attribute specific access operations. */
|
|
int simple_attr_open(struct inode *inode, struct file *file,
|
|
int (*get)(void *, u64 *), int (*set)(void *, u64),
|
|
const char *fmt)
|
|
{
|
|
struct simple_attr *attr;
|
|
|
|
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
|
|
if (!attr)
|
|
return -ENOMEM;
|
|
|
|
attr->get = get;
|
|
attr->set = set;
|
|
attr->data = inode->i_private;
|
|
attr->fmt = fmt;
|
|
mutex_init(&attr->mutex);
|
|
|
|
file->private_data = attr;
|
|
|
|
return nonseekable_open(inode, file);
|
|
}
|
|
EXPORT_SYMBOL_GPL(simple_attr_open);
|
|
|
|
int simple_attr_release(struct inode *inode, struct file *file)
|
|
{
|
|
kfree(file->private_data);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(simple_attr_release); /* GPL-only? This? Really? */
|
|
|
|
/* read from the buffer that is filled with the get function */
|
|
ssize_t simple_attr_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
struct simple_attr *attr;
|
|
size_t size;
|
|
ssize_t ret;
|
|
|
|
attr = file->private_data;
|
|
|
|
if (!attr->get)
|
|
return -EACCES;
|
|
|
|
ret = mutex_lock_interruptible(&attr->mutex);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (*ppos && attr->get_buf[0]) {
|
|
/* continued read */
|
|
size = strlen(attr->get_buf);
|
|
} else {
|
|
/* first read */
|
|
u64 val;
|
|
ret = attr->get(attr->data, &val);
|
|
if (ret)
|
|
goto out;
|
|
|
|
size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
|
|
attr->fmt, (unsigned long long)val);
|
|
}
|
|
|
|
ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
|
|
out:
|
|
mutex_unlock(&attr->mutex);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(simple_attr_read);
|
|
|
|
/* interpret the buffer as a number to call the set function with */
|
|
static ssize_t simple_attr_write_xsigned(struct file *file, const char __user *buf,
|
|
size_t len, loff_t *ppos, bool is_signed)
|
|
{
|
|
struct simple_attr *attr;
|
|
unsigned long long val;
|
|
size_t size;
|
|
ssize_t ret;
|
|
|
|
attr = file->private_data;
|
|
if (!attr->set)
|
|
return -EACCES;
|
|
|
|
ret = mutex_lock_interruptible(&attr->mutex);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = -EFAULT;
|
|
size = min(sizeof(attr->set_buf) - 1, len);
|
|
if (copy_from_user(attr->set_buf, buf, size))
|
|
goto out;
|
|
|
|
attr->set_buf[size] = '\0';
|
|
if (is_signed)
|
|
ret = kstrtoll(attr->set_buf, 0, &val);
|
|
else
|
|
ret = kstrtoull(attr->set_buf, 0, &val);
|
|
if (ret)
|
|
goto out;
|
|
ret = attr->set(attr->data, val);
|
|
if (ret == 0)
|
|
ret = len; /* on success, claim we got the whole input */
|
|
out:
|
|
mutex_unlock(&attr->mutex);
|
|
return ret;
|
|
}
|
|
|
|
ssize_t simple_attr_write(struct file *file, const char __user *buf,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
return simple_attr_write_xsigned(file, buf, len, ppos, false);
|
|
}
|
|
EXPORT_SYMBOL_GPL(simple_attr_write);
|
|
|
|
ssize_t simple_attr_write_signed(struct file *file, const char __user *buf,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
return simple_attr_write_xsigned(file, buf, len, ppos, true);
|
|
}
|
|
EXPORT_SYMBOL_GPL(simple_attr_write_signed);
|
|
|
|
/**
|
|
* generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
|
|
* @sb: filesystem to do the file handle conversion on
|
|
* @fid: file handle to convert
|
|
* @fh_len: length of the file handle in bytes
|
|
* @fh_type: type of file handle
|
|
* @get_inode: filesystem callback to retrieve inode
|
|
*
|
|
* This function decodes @fid as long as it has one of the well-known
|
|
* Linux filehandle types and calls @get_inode on it to retrieve the
|
|
* inode for the object specified in the file handle.
|
|
*/
|
|
struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid,
|
|
int fh_len, int fh_type, struct inode *(*get_inode)
|
|
(struct super_block *sb, u64 ino, u32 gen))
|
|
{
|
|
struct inode *inode = NULL;
|
|
|
|
if (fh_len < 2)
|
|
return NULL;
|
|
|
|
switch (fh_type) {
|
|
case FILEID_INO32_GEN:
|
|
case FILEID_INO32_GEN_PARENT:
|
|
inode = get_inode(sb, fid->i32.ino, fid->i32.gen);
|
|
break;
|
|
}
|
|
|
|
return d_obtain_alias(inode);
|
|
}
|
|
EXPORT_SYMBOL_GPL(generic_fh_to_dentry);
|
|
|
|
/**
|
|
* generic_fh_to_parent - generic helper for the fh_to_parent export operation
|
|
* @sb: filesystem to do the file handle conversion on
|
|
* @fid: file handle to convert
|
|
* @fh_len: length of the file handle in bytes
|
|
* @fh_type: type of file handle
|
|
* @get_inode: filesystem callback to retrieve inode
|
|
*
|
|
* This function decodes @fid as long as it has one of the well-known
|
|
* Linux filehandle types and calls @get_inode on it to retrieve the
|
|
* inode for the _parent_ object specified in the file handle if it
|
|
* is specified in the file handle, or NULL otherwise.
|
|
*/
|
|
struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|
int fh_len, int fh_type, struct inode *(*get_inode)
|
|
(struct super_block *sb, u64 ino, u32 gen))
|
|
{
|
|
struct inode *inode = NULL;
|
|
|
|
if (fh_len <= 2)
|
|
return NULL;
|
|
|
|
switch (fh_type) {
|
|
case FILEID_INO32_GEN_PARENT:
|
|
inode = get_inode(sb, fid->i32.parent_ino,
|
|
(fh_len > 3 ? fid->i32.parent_gen : 0));
|
|
break;
|
|
}
|
|
|
|
return d_obtain_alias(inode);
|
|
}
|
|
EXPORT_SYMBOL_GPL(generic_fh_to_parent);
|
|
|
|
/**
|
|
* __generic_file_fsync - generic fsync implementation for simple filesystems
|
|
*
|
|
* @file: file to synchronize
|
|
* @start: start offset in bytes
|
|
* @end: end offset in bytes (inclusive)
|
|
* @datasync: only synchronize essential metadata if true
|
|
*
|
|
* This is a generic implementation of the fsync method for simple
|
|
* filesystems which track all non-inode metadata in the buffers list
|
|
* hanging off the address_space structure.
|
|
*/
|
|
int __generic_file_fsync(struct file *file, loff_t start, loff_t end,
|
|
int datasync)
|
|
{
|
|
struct inode *inode = file->f_mapping->host;
|
|
int err;
|
|
int ret;
|
|
|
|
err = file_write_and_wait_range(file, start, end);
|
|
if (err)
|
|
return err;
|
|
|
|
inode_lock(inode);
|
|
ret = sync_mapping_buffers(inode->i_mapping);
|
|
if (!(inode->i_state & I_DIRTY_ALL))
|
|
goto out;
|
|
if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
|
|
goto out;
|
|
|
|
err = sync_inode_metadata(inode, 1);
|
|
if (ret == 0)
|
|
ret = err;
|
|
|
|
out:
|
|
inode_unlock(inode);
|
|
/* check and advance again to catch errors after syncing out buffers */
|
|
err = file_check_and_advance_wb_err(file);
|
|
if (ret == 0)
|
|
ret = err;
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(__generic_file_fsync);
|
|
|
|
/**
|
|
* generic_file_fsync - generic fsync implementation for simple filesystems
|
|
* with flush
|
|
* @file: file to synchronize
|
|
* @start: start offset in bytes
|
|
* @end: end offset in bytes (inclusive)
|
|
* @datasync: only synchronize essential metadata if true
|
|
*
|
|
*/
|
|
|
|
int generic_file_fsync(struct file *file, loff_t start, loff_t end,
|
|
int datasync)
|
|
{
|
|
struct inode *inode = file->f_mapping->host;
|
|
int err;
|
|
|
|
err = __generic_file_fsync(file, start, end, datasync);
|
|
if (err)
|
|
return err;
|
|
return blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL);
|
|
}
|
|
EXPORT_SYMBOL(generic_file_fsync);
|
|
|
|
/**
|
|
* generic_check_addressable - Check addressability of file system
|
|
* @blocksize_bits: log of file system block size
|
|
* @num_blocks: number of blocks in file system
|
|
*
|
|
* Determine whether a file system with @num_blocks blocks (and a
|
|
* block size of 2**@blocksize_bits) is addressable by the sector_t
|
|
* and page cache of the system. Return 0 if so and -EFBIG otherwise.
|
|
*/
|
|
int generic_check_addressable(unsigned blocksize_bits, u64 num_blocks)
|
|
{
|
|
u64 last_fs_block = num_blocks - 1;
|
|
u64 last_fs_page =
|
|
last_fs_block >> (PAGE_SHIFT - blocksize_bits);
|
|
|
|
if (unlikely(num_blocks == 0))
|
|
return 0;
|
|
|
|
if ((blocksize_bits < 9) || (blocksize_bits > PAGE_SHIFT))
|
|
return -EINVAL;
|
|
|
|
if ((last_fs_block > (sector_t)(~0ULL) >> (blocksize_bits - 9)) ||
|
|
(last_fs_page > (pgoff_t)(~0ULL))) {
|
|
return -EFBIG;
|
|
}
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(generic_check_addressable);
|
|
|
|
/*
|
|
* No-op implementation of ->fsync for in-memory filesystems.
|
|
*/
|
|
int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
|
{
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(noop_fsync);
|
|
|
|
int noop_set_page_dirty(struct page *page)
|
|
{
|
|
/*
|
|
* Unlike __set_page_dirty_no_writeback that handles dirty page
|
|
* tracking in the page object, dax does all dirty tracking in
|
|
* the inode address_space in response to mkwrite faults. In the
|
|
* dax case we only need to worry about potentially dirty CPU
|
|
* caches, not dirty page cache pages to write back.
|
|
*
|
|
* This callback is defined to prevent fallback to
|
|
* __set_page_dirty_buffers() in set_page_dirty().
|
|
*/
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(noop_set_page_dirty);
|
|
|
|
void noop_invalidatepage(struct page *page, unsigned int offset,
|
|
unsigned int length)
|
|
{
|
|
/*
|
|
* There is no page cache to invalidate in the dax case, however
|
|
* we need this callback defined to prevent falling back to
|
|
* block_invalidatepage() in do_invalidatepage().
|
|
*/
|
|
}
|
|
EXPORT_SYMBOL_GPL(noop_invalidatepage);
|
|
|
|
ssize_t noop_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|
{
|
|
/*
|
|
* iomap based filesystems support direct I/O without need for
|
|
* this callback. However, it still needs to be set in
|
|
* inode->a_ops so that open/fcntl know that direct I/O is
|
|
* generally supported.
|
|
*/
|
|
return -EINVAL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(noop_direct_IO);
|
|
|
|
/* Because kfree isn't assignment-compatible with void(void*) ;-/ */
|
|
void kfree_link(void *p)
|
|
{
|
|
kfree(p);
|
|
}
|
|
EXPORT_SYMBOL(kfree_link);
|
|
|
|
/*
|
|
* nop .set_page_dirty method so that people can use .page_mkwrite on
|
|
* anon inodes.
|
|
*/
|
|
static int anon_set_page_dirty(struct page *page)
|
|
{
|
|
return 0;
|
|
};
|
|
|
|
struct inode *alloc_anon_inode(struct super_block *s)
|
|
{
|
|
static const struct address_space_operations anon_aops = {
|
|
.set_page_dirty = anon_set_page_dirty,
|
|
};
|
|
struct inode *inode = new_inode_pseudo(s);
|
|
|
|
if (!inode)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
inode->i_ino = get_next_ino();
|
|
inode->i_mapping->a_ops = &anon_aops;
|
|
|
|
/*
|
|
* Mark the inode dirty from the very beginning,
|
|
* that way it will never be moved to the dirty
|
|
* list because mark_inode_dirty() will think
|
|
* that it already _is_ on the dirty list.
|
|
*/
|
|
inode->i_state = I_DIRTY;
|
|
inode->i_mode = S_IRUSR | S_IWUSR;
|
|
inode->i_uid = current_fsuid();
|
|
inode->i_gid = current_fsgid();
|
|
inode->i_flags |= S_PRIVATE;
|
|
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
|
|
return inode;
|
|
}
|
|
EXPORT_SYMBOL(alloc_anon_inode);
|
|
|
|
/**
|
|
* simple_nosetlease - generic helper for prohibiting leases
|
|
* @filp: file pointer
|
|
* @arg: type of lease to obtain
|
|
* @flp: new lease supplied for insertion
|
|
* @priv: private data for lm_setup operation
|
|
*
|
|
* Generic helper for filesystems that do not wish to allow leases to be set.
|
|
* All arguments are ignored and it just returns -EINVAL.
|
|
*/
|
|
int
|
|
simple_nosetlease(struct file *filp, long arg, struct file_lock **flp,
|
|
void **priv)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
EXPORT_SYMBOL(simple_nosetlease);
|
|
|
|
/**
|
|
* simple_get_link - generic helper to get the target of "fast" symlinks
|
|
* @dentry: not used here
|
|
* @inode: the symlink inode
|
|
* @done: not used here
|
|
*
|
|
* Generic helper for filesystems to use for symlink inodes where a pointer to
|
|
* the symlink target is stored in ->i_link. NOTE: this isn't normally called,
|
|
* since as an optimization the path lookup code uses any non-NULL ->i_link
|
|
* directly, without calling ->get_link(). But ->get_link() still must be set,
|
|
* to mark the inode_operations as being for a symlink.
|
|
*
|
|
* Return: the symlink target
|
|
*/
|
|
const char *simple_get_link(struct dentry *dentry, struct inode *inode,
|
|
struct delayed_call *done)
|
|
{
|
|
return inode->i_link;
|
|
}
|
|
EXPORT_SYMBOL(simple_get_link);
|
|
|
|
const struct inode_operations simple_symlink_inode_operations = {
|
|
.get_link = simple_get_link,
|
|
};
|
|
EXPORT_SYMBOL(simple_symlink_inode_operations);
|
|
|
|
/*
|
|
* Operations for a permanently empty directory.
|
|
*/
|
|
static struct dentry *empty_dir_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
|
|
{
|
|
return ERR_PTR(-ENOENT);
|
|
}
|
|
|
|
static int empty_dir_getattr(const struct path *path, struct kstat *stat,
|
|
u32 request_mask, unsigned int query_flags)
|
|
{
|
|
struct inode *inode = d_inode(path->dentry);
|
|
generic_fillattr(inode, stat);
|
|
return 0;
|
|
}
|
|
|
|
static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
|
|
{
|
|
return -EPERM;
|
|
}
|
|
|
|
static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static const struct inode_operations empty_dir_inode_operations = {
|
|
.lookup = empty_dir_lookup,
|
|
.permission = generic_permission,
|
|
.setattr = empty_dir_setattr,
|
|
.getattr = empty_dir_getattr,
|
|
.listxattr = empty_dir_listxattr,
|
|
};
|
|
|
|
static loff_t empty_dir_llseek(struct file *file, loff_t offset, int whence)
|
|
{
|
|
/* An empty directory has two entries . and .. at offsets 0 and 1 */
|
|
return generic_file_llseek_size(file, offset, whence, 2, 2);
|
|
}
|
|
|
|
static int empty_dir_readdir(struct file *file, struct dir_context *ctx)
|
|
{
|
|
dir_emit_dots(file, ctx);
|
|
return 0;
|
|
}
|
|
|
|
static const struct file_operations empty_dir_operations = {
|
|
.llseek = empty_dir_llseek,
|
|
.read = generic_read_dir,
|
|
.iterate_shared = empty_dir_readdir,
|
|
.fsync = noop_fsync,
|
|
};
|
|
|
|
|
|
void make_empty_dir_inode(struct inode *inode)
|
|
{
|
|
set_nlink(inode, 2);
|
|
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
|
|
inode->i_uid = GLOBAL_ROOT_UID;
|
|
inode->i_gid = GLOBAL_ROOT_GID;
|
|
inode->i_rdev = 0;
|
|
inode->i_size = 0;
|
|
inode->i_blkbits = PAGE_SHIFT;
|
|
inode->i_blocks = 0;
|
|
|
|
inode->i_op = &empty_dir_inode_operations;
|
|
inode->i_opflags &= ~IOP_XATTR;
|
|
inode->i_fop = &empty_dir_operations;
|
|
}
|
|
|
|
bool is_empty_dir_inode(struct inode *inode)
|
|
{
|
|
return (inode->i_fop == &empty_dir_operations) &&
|
|
(inode->i_op == &empty_dir_inode_operations);
|
|
}
|
|
|
|
#ifdef CONFIG_UNICODE
|
|
/*
|
|
* Determine if the name of a dentry should be casefolded.
|
|
*
|
|
* Return: if names will need casefolding
|
|
*/
|
|
static bool needs_casefold(const struct inode *dir)
|
|
{
|
|
return IS_CASEFOLDED(dir) && dir->i_sb->s_encoding;
|
|
}
|
|
|
|
/**
|
|
* generic_ci_d_compare - generic d_compare implementation for casefolding filesystems
|
|
* @dentry: dentry whose name we are checking against
|
|
* @len: len of name of dentry
|
|
* @str: str pointer to name of dentry
|
|
* @name: Name to compare against
|
|
*
|
|
* Return: 0 if names match, 1 if mismatch, or -ERRNO
|
|
*/
|
|
static int generic_ci_d_compare(const struct dentry *dentry, unsigned int len,
|
|
const char *str, const struct qstr *name)
|
|
{
|
|
const struct dentry *parent = READ_ONCE(dentry->d_parent);
|
|
const struct inode *dir = READ_ONCE(parent->d_inode);
|
|
const struct super_block *sb = dentry->d_sb;
|
|
const struct unicode_map *um = sb->s_encoding;
|
|
struct qstr qstr = QSTR_INIT(str, len);
|
|
char strbuf[DNAME_INLINE_LEN];
|
|
int ret;
|
|
|
|
if (!dir || !needs_casefold(dir))
|
|
goto fallback;
|
|
/*
|
|
* If the dentry name is stored in-line, then it may be concurrently
|
|
* modified by a rename. If this happens, the VFS will eventually retry
|
|
* the lookup, so it doesn't matter what ->d_compare() returns.
|
|
* However, it's unsafe to call utf8_strncasecmp() with an unstable
|
|
* string. Therefore, we have to copy the name into a temporary buffer.
|
|
*/
|
|
if (len <= DNAME_INLINE_LEN - 1) {
|
|
memcpy(strbuf, str, len);
|
|
strbuf[len] = 0;
|
|
qstr.name = strbuf;
|
|
/* prevent compiler from optimizing out the temporary buffer */
|
|
barrier();
|
|
}
|
|
ret = utf8_strncasecmp(um, name, &qstr);
|
|
if (ret >= 0)
|
|
return ret;
|
|
|
|
if (sb_has_strict_encoding(sb))
|
|
return -EINVAL;
|
|
fallback:
|
|
if (len != name->len)
|
|
return 1;
|
|
return !!memcmp(str, name->name, len);
|
|
}
|
|
|
|
/**
|
|
* generic_ci_d_hash - generic d_hash implementation for casefolding filesystems
|
|
* @dentry: dentry of the parent directory
|
|
* @str: qstr of name whose hash we should fill in
|
|
*
|
|
* Return: 0 if hash was successful or unchanged, and -EINVAL on error
|
|
*/
|
|
static int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str)
|
|
{
|
|
const struct inode *dir = READ_ONCE(dentry->d_inode);
|
|
struct super_block *sb = dentry->d_sb;
|
|
const struct unicode_map *um = sb->s_encoding;
|
|
int ret = 0;
|
|
|
|
if (!dir || !needs_casefold(dir))
|
|
return 0;
|
|
|
|
ret = utf8_casefold_hash(um, dentry, str);
|
|
if (ret < 0 && sb_has_strict_encoding(sb))
|
|
return -EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
static const struct dentry_operations generic_ci_dentry_ops = {
|
|
.d_hash = generic_ci_d_hash,
|
|
.d_compare = generic_ci_d_compare,
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_FS_ENCRYPTION
|
|
static const struct dentry_operations generic_encrypted_dentry_ops = {
|
|
.d_revalidate = fscrypt_d_revalidate,
|
|
};
|
|
#endif
|
|
|
|
#if defined(CONFIG_FS_ENCRYPTION) && defined(CONFIG_UNICODE)
|
|
static const struct dentry_operations generic_encrypted_ci_dentry_ops = {
|
|
.d_hash = generic_ci_d_hash,
|
|
.d_compare = generic_ci_d_compare,
|
|
.d_revalidate = fscrypt_d_revalidate,
|
|
};
|
|
#endif
|
|
|
|
/**
|
|
* generic_set_encrypted_ci_d_ops - helper for setting d_ops for given dentry
|
|
* @dentry: dentry to set ops on
|
|
*
|
|
* Casefolded directories need d_hash and d_compare set, so that the dentries
|
|
* contained in them are handled case-insensitively. Note that these operations
|
|
* are needed on the parent directory rather than on the dentries in it, and
|
|
* while the casefolding flag can be toggled on and off on an empty directory,
|
|
* dentry_operations can't be changed later. As a result, if the filesystem has
|
|
* casefolding support enabled at all, we have to give all dentries the
|
|
* casefolding operations even if their inode doesn't have the casefolding flag
|
|
* currently (and thus the casefolding ops would be no-ops for now).
|
|
*
|
|
* Encryption works differently in that the only dentry operation it needs is
|
|
* d_revalidate, which it only needs on dentries that have the no-key name flag.
|
|
* The no-key flag can't be set "later", so we don't have to worry about that.
|
|
*
|
|
* Finally, to maximize compatibility with overlayfs (which isn't compatible
|
|
* with certain dentry operations) and to avoid taking an unnecessary
|
|
* performance hit, we use custom dentry_operations for each possible
|
|
* combination rather than always installing all operations.
|
|
*/
|
|
void generic_set_encrypted_ci_d_ops(struct dentry *dentry)
|
|
{
|
|
#ifdef CONFIG_FS_ENCRYPTION
|
|
bool needs_encrypt_ops = dentry->d_flags & DCACHE_NOKEY_NAME;
|
|
#endif
|
|
#ifdef CONFIG_UNICODE
|
|
bool needs_ci_ops = dentry->d_sb->s_encoding;
|
|
#endif
|
|
#if defined(CONFIG_FS_ENCRYPTION) && defined(CONFIG_UNICODE)
|
|
if (needs_encrypt_ops && needs_ci_ops) {
|
|
d_set_d_op(dentry, &generic_encrypted_ci_dentry_ops);
|
|
return;
|
|
}
|
|
#endif
|
|
#ifdef CONFIG_FS_ENCRYPTION
|
|
if (needs_encrypt_ops) {
|
|
d_set_d_op(dentry, &generic_encrypted_dentry_ops);
|
|
return;
|
|
}
|
|
#endif
|
|
#ifdef CONFIG_UNICODE
|
|
if (needs_ci_ops) {
|
|
d_set_d_op(dentry, &generic_ci_dentry_ops);
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(generic_set_encrypted_ci_d_ops);
|