This is the merge of the upstream LTS release of 5.10.101 into the android12-5.10 branch. This merge contains the following new commits: c194212a0332 Merge 5.10.101 into android12-5.10-lts 3969aba589d6 Linux 5.10.101 cb86e511e78e iommu: Fix potential use-after-free during probe f6b5d51976fc perf: Fix list corruption in perf_cgroup_switch() ce3ca12c632a arm64: dts: imx8mq: fix lcdif port node 759aeacdfe70 scsi: lpfc: Reduce log messages seen after firmware download 57c5d7d42076 scsi: lpfc: Remove NVMe support if kernel has NVME_FC disabled 199dab00f043 can: isotp: fix error path in isotp_sendmsg() to unlock wait queue 3b10ebeb95d7 Makefile.extrawarn: Move -Wunaligned-access to W=1 ad53060bdfc3 hwmon: (dell-smm) Speed up setting of fan speed 3c75d1017cb3 phy: ti: Fix missing sentinel for clk_div_table 6eabe53492c2 speakup-dectlk: Restore pitch setting 3836a5ff4bb7 USB: serial: cp210x: add CPI Bulk Coin Recycler id 51b03a9bcd99 USB: serial: cp210x: add NCR Retail IO box id a21e6b2e0864 USB: serial: ch341: add support for GW Instek USB2.0-Serial devices 7113440a36c7 USB: serial: option: add ZTE MF286D modem b7ed2f9619cc USB: serial: ftdi_sio: add support for Brainboxes US-159/235/320 e07dde31acc9 usb: raw-gadget: fix handling of dual-direction-capable endpoints e9f9b877eb0e usb: gadget: f_uac2: Define specific wTerminalType fb4ff0f96de3 usb: gadget: rndis: check size of RNDIS_MSG_SET command 22ec10047285 USB: gadget: validate interface OS descriptor requests 351159167cd8 usb: gadget: udc: renesas_usb3: Fix host to USB_ROLE_NONE transition 3bfca3891480 usb: dwc3: gadget: Prevent core from processing stale TRBs 2a17bd9f5210 usb: ulpi: Call of_node_put correctly 8b89a6916681 usb: ulpi: Move of_node_put to ulpi_dev_release 758290defe93 net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup a66a2b17b8c8 Revert "usb: dwc2: drd: fix soft connect when gadget is unconfigured" 73961057e9dc usb: dwc2: drd: fix soft connect when gadget is unconfigured a37960df7eac eeprom: ee1004: limit i2c reads to I2C_SMBUS_BLOCK_MAX 1b99fe34e26d n_tty: wake up poll(POLLRDNORM) on receiving data f1b25737156c vt_ioctl: add array_index_nospec to VT_ACTIVATE 778302ca0949 vt_ioctl: fix array_index_nospec in vt_setactivate 22249886dc5b net: dsa: mv88e6xxx: fix use-after-free in mv88e6xxx_mdios_unregister 3a3c65c487a4 net: mscc: ocelot: fix mutex lock error during ethtool stats read 809f030745b2 ice: fix IPIP and SIT TSO offload cf11949b9163 ice: fix an error code in ice_cfg_phy_fec() f8edc6feab4d dpaa2-eth: unregister the netdev before disconnecting from the PHY ff6c9e0fcee5 net: amd-xgbe: disable interrupts during pci removal 657aea782887 tipc: rate limit warning for received illegal binding update ef5cdae8bc00 net: mdio: aspeed: Add missing MODULE_DEVICE_TABLE bf99c144360d veth: fix races around rq->rx_notify_masked 00e6d6c3bc14 net: fix a memleak when uncloning an skb dst and its metadata 2e9fd2d0f69e net: do not keep the dst cache when uncloning an skb dst and its metadata 0bae953d7ab5 nfp: flower: fix ida_idx not being released 09ac0fcb0a82 ipmr,ip6mr: acquire RTNL before calling ip[6]mr_free_table() on failure path e177d2e85ebc net: dsa: lantiq_gswip: don't use devres for mdiobus 95e5402f9430 net: dsa: felix: don't use devres for mdiobus 2770b795294e net: dsa: bcm_sf2: don't use devres for mdiobus 475ce5dcf2d8 net: dsa: ar9331: register the mdiobus under devres 8ccebe77df6e net: dsa: mv88e6xxx: don't use devres for mdiobus 4a384c1e4058 bonding: pair enable_port with slave_arr_updates 1ba45dd32667 gpio: sifive: use the correct register to read output values 48e413087de1 ACPI: PM: s2idle: Cancel wakeup before dispatching EC GPE 3b72d3f0205e drm/panel: simple: Assign data from panel_dpi_probe() correctly bf35639192ed ixgbevf: Require large buffers for build_skb on 82599VF e5a64f548a45 arm64: dts: meson-g12b-odroid-n2: fix typo 'dio2133' 04fe6569a7cf netfilter: ctnetlink: disable helper autoassign a5ce7ee5fcc0 misc: fastrpc: avoid double fput() on failed usercopy 21c890ca8eae drm/vc4: hdmi: Allow DBLCLK modes even if horz timing is odd. 70ea005626a9 gpio: aggregator: Fix calling into sleeping GPIO controllers 0042178a69eb usb: f_fs: Fix use-after-free for epfile 5a37fd9fdcce ARM: dts: imx7ulp: Fix 'assigned-clocks-parents' typo 39bf132a6ed5 phy: xilinx: zynqmp: Fix bus width setting for SGMII 108868dae2ee ARM: dts: imx6qdl-udoo: Properly describe the SD card detect 0a7b5e8d8c1e staging: fbtft: Fix error path in fbtft_driver_module_init() 74cd5cb2190f ARM: dts: meson8b: Fix the UART device-tree schema validation 566b558e9429 ARM: dts: meson8: Fix the UART device-tree schema validation 210d70f08100 ARM: dts: meson: Fix the UART compatible strings 88f0e61354f4 ARM: dts: Fix timer regression for beagleboard revision c c943a297ec3c drm/rockchip: vop: Correct RK3399 VOP register fields a941384fba3f PM: s2idle: ACPI: Fix wakeup interrupts handling fcbac51a64d3 ACPI/IORT: Check node revision for PMCG resources 57ede0ce6500 nvme-tcp: fix bogus request completion when failing to send AER 3a669d77e5b3 ARM: socfpga: fix missing RESET_CONTROLLER 435e62d5666a ARM: dts: Fix boot regression on Skomer b217b89e607c ARM: dts: imx23-evk: Remove MX23_PAD_SSP1_DETECT from hog group 3f9843f2f65e riscv: fix build with binutils 2.38 3aa5c8657292 KVM: VMX: Set vmcs.PENDING_DBG.BS on #DB in STI/MOVSS blocking shadow bd39fe29bbbb KVM: SVM: Don't kill SEV guest if SMAP erratum triggers in usermode 9efad4cb0365 KVM: nVMX: Also filter MSR_IA32_VMX_TRUE_PINBASED_CTLS when eVMCS db58a3d978b4 KVM: nVMX: eVMCS: Filter out VM_EXIT_SAVE_VMX_PREEMPTION_TIMER dc129275a7f7 KVM: eventfd: Fix false positive RCU usage warning 87bbd78a2cd1 net: stmmac: dwmac-sun8i: use return val of readl_poll_timeout() c9b8cc1046f0 nvme-pci: add the IGNORE_DEV_SUBNQN quirk for Intel P4500/P4600 SSDs d0774cf73056 perf: Always wake the parent event a117e986e9cc usb: dwc2: gadget: don't try to disable ep0 in dwc2_hsotg_suspend 4607218fde84 PM: hibernate: Remove register_nosave_region_late() 0e42c4a3d732 scsi: myrs: Fix crash in error case 3bc5b128b9a2 scsi: ufs: Treat link loss as fatal error 12cf1208035d scsi: pm8001: Fix bogus FW crash for maxcpus=1 87f187e5265b scsi: qedf: Fix refcount issue when LOGO is received during TMF aa7352aa155e scsi: qedf: Add stag_work to all the vports 150d448c663d scsi: ufs: ufshcd-pltfrm: Check the return value of devm_kstrdup() 7dbda616fc64 scsi: target: iscsi: Make sure the np under each tpg is unique 67baac10dd5a powerpc/fixmap: Fix VM debug warning on unmap 3d0eafd459b2 net: sched: Clarify error message when qdisc kind is unknown 9b569faabd22 drm: panel-orientation-quirks: Add quirk for the 1Netbook OneXPlayer 0d6b9d15ecb4 x86/perf: Avoid warning for Arch LBR without XSAVE b37dd03f2fc6 NFSv4 handle port presence in fs_location server string 6f2974b52b15 NFSv4 expose nfs_parse_server_name function 5a9c613a29e7 NFSv4 remove zero number of fs_locations entries error check 1c79aad1186b NFSv4.1: Fix uninitialised variable in devicenotify c5619c510f04 nfs: nfs4clinet: check the return value of kstrdup() db053bdece3a NFSv4 only print the label when its queried e2b4435fd340 NFS: change nfs_access_get_cached to only report the mask b4e0c9bcf142 tracing: Propagate is_signed to expression 5234de6c7975 drm/amdgpu: Set a suitable dev_info.gart_page_size 6215fb455893 NFSD: Fix offset type in I/O trace points 3a6a2d43e32a NFSD: Clamp WRITE offsets c72f7c2ec3d4 NFS: Fix initialisation of nfs_client cl_flags field f47ee3a35ffb net: phy: marvell: Fix MDI-x polarity setting in 88e1118-compatible PHYs 6a33aa711327 net: phy: marvell: Fix RGMII Tx/Rx delays setting in 88e1121-compatible PHYs 7b53d2204ce7 can: isotp: fix potential CAN frame reception race in isotp_rcv() c9cc027c55bb mmc: sdhci-of-esdhc: Check for error num after setting mask 8027ba480c00 ima: Do not print policy rule with inactive LSM labels 8171c8a99fea ima: Allow template selection with ima_template[_fmt]= after ima_hash= 0795b7100d25 ima: Remove ima_policy file before directory 7fea2e520003 integrity: check the return value of audit_log_start() 86e6176a4240 Merge 5.10.100 into android12-5.10-lts d4f7d322a4ad Linux 5.10.100 3c7e59435535 tipc: improve size validations for received domain records 2951d2168976 crypto: api - Move cryptomgr soft dependency into algapi b62267b8b06e KVM: s390: Return error on SIDA memop on normal guest be93028d306d moxart: fix potential use-after-free on remove path ca562bf79c65 Merge branch 'android12-5.10' into `android12-5.10-lts` c3b53fcd9007 Merge 5.10.99 into android12-5.10-lts fb063a6465f9 Linux 5.10.99 4889d6ee9e48 selftests: nft_concat_range: add test for reload with no element add/del 557727313534 cgroup/cpuset: Fix "suspicious RCU usage" lockdep warning f1f7d1a22fd7 net: dsa: mt7530: make NET_DSA_MT7530 select MEDIATEK_GE_PHY 84b76a509cc3 ext4: fix incorrect type issue during replay_del_range 62e46e0ffc02 ext4: fix error handling in ext4_fc_record_modified_inode() 764793b4a5d0 ext4: fix error handling in ext4_restore_inline_data() 6c5bd55e36d3 ext4: modify the logic of ext4_mb_new_blocks_simple 8d71fc23fcb8 ext4: prevent used blocks from being allocated during fast commit replay ef2053afd71e EDAC/xgene: Fix deferred probing 2a12faf55bae EDAC/altera: Fix deferred probing dd274cf85269 x86/perf: Default set FREEZE_ON_SMI for all 456f041e0359 perf/x86/intel/pt: Fix crash with stop filters in single-range mode 8c0e6a8a630e perf stat: Fix display of grouped aliased events 57e8859acc60 fbcon: Add option to enable legacy hardware acceleration 460f6b1a238d Revert "fbcon: Disable accelerated scrolling" 460aa9d87340 rtc: cmos: Evaluate century appropriate 2324f5fcdf9d tools/resolve_btfids: Do not print any commands when building silently 1536fafa23ac selftests: futex: Use variable MAKE instead of make 8f0fff8b5968 selftests/exec: Remove pipe from TEST_GEN_FILES 6304a613a97d bpf: Use VM_MAP instead of VM_ALLOC for ringbuf f744a064041c gve: fix the wrong AdminQ buffer queue index check 51e88e892273 nfsd: nfsd4_setclientid_confirm mistakenly expires confirmed client. ec4334152dae scsi: bnx2fc: Make bnx2fc_recv_frame() mp safe fd482f2d63db pinctrl: bcm2835: Fix a few error paths 752d9eafc64e pinctrl: intel: fix unexpected interrupt 14bc9978b486 pinctrl: intel: Fix a glitch when updating IRQ flags on a preconfigured line 5a45448ac95b ASoC: max9759: fix underflow in speaker_gain_control_put() 02f459719832 ASoC: cpcap: Check for NULL pointer after calling of_get_child_by_name cb5f1fbd1f22 ASoC: xilinx: xlnx_formatter_pcm: Make buffer bytes multiple of period bytes 56e0747d59ac ASoC: fsl: Add missing error handling in pcm030_fabric_probe 3e698375517d drm/i915/overlay: Prevent divide by zero bugs in scaling 9ea018536111 net: stmmac: ensure PTP time register reads are consistent 41df2da2c1f3 net: stmmac: dump gmac4 DMA registers correctly 114bf9350413 net: macsec: Verify that send_sci is on when setting Tx sci explicitly 2e7f5b6ee1a7 net: macsec: Fix offload support for NETDEV_UNREGISTER event 87b1c9fab6fe net: ieee802154: Return meaningful error codes from the netlink helpers 78b3f20c17cb net: ieee802154: ca8210: Stop leaking skb's 0bfe50dc5d91 net: ieee802154: mcr20a: Fix lifs/sifs periods 75bbda318987 net: ieee802154: hwsim: Ensure proper channel selection at probe time e895e067d73e spi: uniphier: fix reference count leak in uniphier_spi_probe() ec942d08e070 spi: meson-spicc: add IRQ check in meson_spicc_probe c2cf65e1008b spi: mediatek: Avoid NULL pointer crash in interrupt 30e05c98b99d spi: bcm-qspi: check for valid cs before applying chip select 6d226e8afe88 iommu/amd: Fix loop timeout issue in iommu_ga_log_enable() 9d9995b0371e iommu/vt-d: Fix potential memory leak in intel_setup_irq_remapping() b3958d315163 RDMA/mlx4: Don't continue event handler after memory allocation failure d3f8b927df2f RDMA/siw: Fix broken RDMA Read Fence/Resume logic. c7db20f5be73 IB/rdmavt: Validate remote_addr during loopback atomic tests 75c610212b9f RDMA/ucma: Protect mc during concurrent multicast leaves 371979069a57 RDMA/cma: Use correct address when leaving multicast group aa4ecd995f59 memcg: charge fs_context and legacy_fs_context 080f371d984e Revert "ASoC: mediatek: Check for error clk pointer" 4a9bd1e6780f IB/hfi1: Fix AIP early init panic 5d40f1bdad3d dma-buf: heaps: Fix potential spectre v1 gadget 30de3bc09978 block: bio-integrity: Advance seed correctly for larger interval sizes 352715593e81 mm/kmemleak: avoid scanning potential huge holes 7053188ddba3 mm/pgtable: define pte_index so that preprocessor could recognize it bce7f5d74d74 mm/debug_vm_pgtable: remove pte entry from the page table 2d83a7463d75 nvme-fabrics: fix state check in nvmf_ctlr_matches_baseopts() a0c73dbdd197 drm/amd/display: Force link_rate as LINK_RATE_RBR2 for 2018 15" Apple Retina panels f071d9fa8575 drm/nouveau: fix off by one in BIOS boundary checking 32747e01436a btrfs: fix deadlock between quota disable and qgroup rescan worker aa5d406153c5 ALSA: hda/realtek: Fix silent output on Gigabyte X570 Aorus Xtreme after reboot from Windows d4aa3a98596f ALSA: hda/realtek: Fix silent output on Gigabyte X570S Aorus Master (newer chipset) 3a8a8072e32b ALSA: hda/realtek: Add missing fixup-model entry for Gigabyte X570 ALC1220 quirks 532cde962f5f ALSA: hda/realtek: Add quirk for ASUS GU603 410f231fd70c ALSA: hda: realtek: Fix race at concurrent COEF updates a7de1002135c ALSA: hda: Fix UAF of leds class devs at unbinding 470bbb9cbd8f ALSA: usb-audio: Correct quirk for VF0770 6877f87579ed ASoC: ops: Reject out of bounds values in snd_soc_put_xr_sx() 038f8b7caa74 ASoC: ops: Reject out of bounds values in snd_soc_put_volsw_sx() a9394f21fba0 ASoC: ops: Reject out of bounds values in snd_soc_put_volsw() 0ff6b8050695 audit: improve audit queue handling when "audit=1" on cmdline f446089a268c selinux: fix double free of cond_list on error paths 08942dae64d3 Merge 5.10.98 into android-5.10 26d02dc8ef49 Merge 5.10.97 into android12-5.10-lts e33a5b611c98 Revert "perf: Fix perf_event_read_local() time" 0b4470b56e6a Merge 5.10.96 into android12-5.10-lts 12a0a56cbae3 Linux 5.10.98 97a47e25559e Revert "drm/vc4: hdmi: Make sure the device is powered with CEC" again e27042060f81 Revert "drm/vc4: hdmi: Make sure the device is powered with CEC" c8ed22bd97d4 Linux 5.10.97 176356550ced tcp: add missing tcp_skb_can_collapse() test in tcp_shift_skb_data() 32e179971085 af_packet: fix data-race in packet_setsockopt / packet_setsockopt aa9e96db3121 cpuset: Fix the bug that subpart_cpus updated wrongly in update_cpumask() 3bbe2019dd12 rtnetlink: make sure to refresh master_dev/m_ops in __rtnl_newlink() e7be56926397 net: sched: fix use-after-free in tc_new_tfilter() 7b4741644cf7 fanotify: Fix stale file descriptor in copy_event_to_user() 4d3fcfe84648 net: amd-xgbe: Fix skb data length underflow cadfa7dce526 net: amd-xgbe: ensure to reset the tx_timer_active flag 77534b114f24 ipheth: fix EOVERFLOW in ipheth_rcvbulk_callback b4ced7a46d9f net/mlx5: E-Switch, Fix uninitialized variable modact 502c37b033fa net/mlx5: Use del_timer_sync in fw reset flow of halting poll a01ee1b8165f net/mlx5e: Fix handling of wrong devices during bond netevent 1fc3444cda9a cgroup-v1: Require capabilities to set release_agent ac4ba79bb028 drm/vc4: hdmi: Make sure the device is powered with CEC 46f919c6bdc5 x86/cpu: Add Xeon Icelake-D to list of CPUs that support PPIN fbdbf6743f77 x86/mce: Add Xeon Sapphire Rapids to list of CPUs that support PPIN d4e4e61d4a5b psi: Fix uaf issue when psi trigger is destroyed while being polled 080dbe7e9b86 KVM: x86: Forcibly leave nested virt when SMM state is toggled 063029a8820e Revert "drivers: bus: simple-pm-bus: Add support for probing simple bus only devices" 42fdbf8b7dab net: ipa: prevent concurrent replenish ad81380d3a48 net: ipa: use a bitmap for endpoint replenish_enabled 2ed912e3e057 net: ipa: fix atomic update in ipa_endpoint_replenish() 3b4c966fb156 PCI: pciehp: Fix infinite loop in IRQ handler upon power fault a9839858b556 Merge 5.10.95 into android12-5.10-lts f255ac9e8776 Linux 5.10.96 b43e9d2f6fc7 mtd: rawnand: mpc5121: Remove unused variable in ads5121_select_chip() b63e120189fd block: Fix wrong offset in bio_truncate() 0b4e82403c84 fsnotify: invalidate dcache before IN_DELETE event 8bae6db29c7f usr/include/Makefile: add linux/nfc.h to the compile-test coverage f36554de7897 dt-bindings: can: tcan4x5x: fix mram-cfg RX FIFO config 446ff1fc37c7 net: bridge: vlan: fix memory leak in __allowed_ingress bc58a5bb9e6c ipv4: remove sparse error in ip_neigh_gw4() ebc5b8e471e5 ipv4: tcp: send zero IPID in SYNACK messages 58f72918f942 ipv4: raw: lock the socket in raw_bind() 9ffc94a81b0f net: bridge: vlan: fix single net device option dumping 869f1704f1c2 Revert "ipv6: Honor all IPv6 PIO Valid Lifetime values" 699eef4ed910 net: hns3: handle empty unknown interrupt for VF c9c81b393c74 net: cpsw: Properly initialise struct page_pool_params 729e54636b3e yam: fix a memory leak in yam_siocdevprivate() 93a6e920d8cc drm/msm/dpu: invalid parameter check in dpu_setup_dspp_pcc 0b7d8db87d0b drm/msm/hdmi: Fix missing put_device() call in msm_hdmi_get_phy d1d4616d3e75 video: hyperv_fb: Fix validation of screen resolution 0a60d04abc62 ibmvnic: don't spin in tasklet 55258b505996 ibmvnic: init ->running_cap_crqs early b469cf91fb63 ipv4: fix ip option filtering for locally generated fragments 9b4444197252 net: ipv4: Fix the warning for dereference 2f56c4845df9 net: ipv4: Move ip_options_fragment() out of loop 55402a461872 powerpc/perf: Fix power_pmu_disable to call clear_pmi_irq_pending only if PMI is pending 0bdbf93ee253 hwmon: (lm90) Mark alert as broken for MAX6654 c534287a57dc efi/libstub: arm64: Fix image check alignment at entry 3572205b194c rxrpc: Adjust retransmission backoff 5067f5699de7 octeontx2-pf: Forward error codes to VF bd024e36f681 phylib: fix potential use-after-free a839a79f4d6b net: phy: broadcom: hook up soft_reset for BCM54616S 57b2f3632b2f sched/pelt: Relax the sync of util_sum with util_avg 91b04e83c710 perf: Fix perf_event_read_local() time cffed7e631b5 kernel: delete repeated words in comments 1af995c98b81 netfilter: conntrack: don't increment invalid counter on NF_REPEAT 129c71829d7f powerpc64/bpf: Limit 'ldbrx' to processors compliant with ISA v2.06 7a32824f7a9c NFS: Ensure the server has an up to date ctime before renaming 666f6ab882ea NFS: Ensure the server has an up to date ctime before hardlinking 4cd0ef621509 ipv6: annotate accesses to fn->fn_sernum 79c0b5287ded drm/msm/dsi: invalid parameter check in msm_dsi_phy_enable 3ab44a408bba drm/msm/dsi: Fix missing put_device() call in dsi_get_phy 82c310d04b0f drm/msm: Fix wrong size calculation f57a99c9a55c net-procfs: show net devices bound packet types 87880e3803ce NFSv4: nfs_atomic_open() can race when looking up a non-regular file ce8c552b88ca NFSv4: Handle case where the lookup of a directory fails b48a05cee2c0 hwmon: (lm90) Reduce maximum conversion rate for G781 b26fed25e67b ipv4: avoid using shared IP generator for connected sockets 283aa5a5afbc ping: fix the sk_bound_dev_if match in ping_lookup 7bcb0c19abf4 hwmon: (lm90) Mark alert as broken for MAX6680 925cbd596aa2 hwmon: (lm90) Mark alert as broken for MAX6646/6647/6649 db044d97460e net: fix information leakage in /proc/net/ptype feb770cc00a8 ipv6_tunnel: Rate limit warning messages 00849de10f79 scsi: bnx2fc: Flush destroy_work queue before calling bnx2fc_interface_put() fcaf94c49a84 rpmsg: char: Fix race between the release of rpmsg_eptdev and cdev 1dbb206730f3 rpmsg: char: Fix race between the release of rpmsg_ctrldev and cdev 20f667582189 usb: roles: fix include/linux/usb/role.h compile issue 6aeff8a7c742 i40e: fix unsigned stat widths d2ed5997a94b i40e: Fix for failed to init adminq while VF reset 768eb705e638 i40e: Fix queues reservation for XDP 39896710f732 i40e: Fix issue when maximum queues is exceeded 9068bcb2195b i40e: Increase delay to 1 s after global EMP reset b4c9b6afa3a7 powerpc/32: Fix boot failure with GCC latent entropy plugin 50f5d0a8bd0e powerpc/32s: Fix kasan_init_region() for KASAN 5d3af1dfdf0f powerpc/32s: Allocate one 256k IBAT instead of two consecutives 128k IBATs 08f090bb9b69 x86/MCE/AMD: Allow thresholding interface updates after init 791e5d5daa2c sched/membarrier: Fix membarrier-rseq fence command missing from query bitmask afbde455ebf4 ocfs2: fix a deadlock when commit trans 97f75e7d4c30 jbd2: export jbd2_journal_[grab|put]_journal_head 3921d081c9c3 ucsi_ccg: Check DEV_INT bit only when starting CCG4 598a884c772c usb: typec: tcpm: Do not disconnect while receiving VBUS off e3b131e30e61 USB: core: Fix hang in usb_kill_urb by adding memory barriers 3ca928c82427 usb: gadget: f_sourcesink: Fix isoc transfer for USB_SPEED_SUPER_PLUS 053274bc6baa usb: common: ulpi: Fix crash in ulpi_match() 20c51a4c5220 usb: xhci-plat: fix crash when suspend if remote wake enable 38d1bf67a310 usb-storage: Add unusual-devs entry for VL817 USB-SATA bridge e0fcae7bd72b tty: Add support for Brainboxes UC cards. 7079283d32a2 tty: n_gsm: fix SW flow control encoding/handling 2683b0d5d7d5 serial: stm32: fix software flow control transfer 4628b26df51c serial: 8250: of: Fix mapped region size when using reg-offset property 94b23988c305 netfilter: nft_payload: do not update layer 4 checksum when mangling fragments bf0d4ae5c6c2 arm64: errata: Fix exec handling in erratum 1418040 workaround e92cac1dd803 KVM: x86: Update vCPU's runtime CPUID on write to MSR_IA32_XSS 6b55af102b39 drm/etnaviv: relax submit size limits 7a32d17fb73a perf/x86/intel/uncore: Fix CAS_COUNT_WRITE issue for ICX a2c8e1d9e41b Revert "KVM: SVM: avoid infinite loop on NPF from bad address" abae88fb37bf fsnotify: fix fsnotify hooks in pseudo filesystems 6ceac38e9b0c ceph: set pool_ns in new inode layout for async creates e7be12ca7d39 ceph: properly put ceph_string reference after async create attempt 39986696fef5 tracing: Don't inc err_log entry count if entry allocation fails d71b06aa9950 tracing/histogram: Fix a potential memory leak for kstrdup() 561a22d44acc PM: wakeup: simplify the output logic of pm_show_wakelocks() b0f1cc093bc2 efi: runtime: avoid EFIv2 runtime services on Apple x86 machines de7cc8bcca90 udf: Fix NULL ptr deref when converting from inline format 0a3cfd258923 udf: Restore i_lenAlloc when inode expansion fails f08801252d26 scsi: zfcp: Fix failed recovery on gone remote port with non-NPIV FCP devices ff6bdc205fd0 bpf: Guard against accessing NULL pt_regs in bpf_get_task_stack() 6520fedfcebb s390/hypfs: include z/VM guests with access control group set c10e0627c71c s390/module: fix loading modules with a lot of relocations ba7c71a777c1 net: stmmac: skip only stmmac_ptp_register when resume from suspend 11191406f2f1 net: sfp: ignore disabled SFP node e651772adced media: venus: core: Drop second v4l2 device unregister 83d5196b65d1 Bluetooth: refactor malicious adv data check 34fd8cb7e75c ANDROID: Fix CRC issue up with xfrm headers in 5.10.94 a50b0691652f Revert "xfrm: rate limit SA mapping change message to user space" 67ea95e0e8c3 Revert "clocksource: Reduce clocksource-skew threshold" fae0741a780e Revert "clocksource: Avoid accidental unstable marking of clocksources" 77656fde3c01 Linux 5.10.95 ae2b20f27732 drm/vmwgfx: Fix stale file descriptors on failed usercopy 11ba2c6dfb90 select: Fix indefinitely sleeping task in poll_schedule_timeout() a447d7f786ec KVM: x86/mmu: Fix write-protection of PTs mapped by the TDP MMU 12d3389b7af6 rcu: Tighten rcu_advance_cbs_nowake() checks 4d63363c88e3 bnx2x: Invalidate fastpath HSI version for VFs fdcfabd0952d bnx2x: Utilize firmware 7.13.21.0 6a6acf927895 drm/i915: Flush TLBs before releasing backing store 4ec3c2eea583 Merge 5.10.94 into android12-5.10-lts c525532e4f87 Linux 5.10.94 c76c132444df scripts: sphinx-pre-install: Fix ctex support on Debian 133cef0b6154 scripts: sphinx-pre-install: add required ctex dependency 15ce9329a532 ath10k: Fix the MTU size on QCA9377 SDIO 25b1a6d33039 mtd: nand: bbt: Fix corner case in bad block table handling 8104e589fa4a lib/test_meminit: destroy cache in kmem_cache_alloc_bulk() test 629250370052 mm/hmm.c: allow VM_MIXEDMAP to work with hmm_range_fault 33bb7f027b06 lib82596: Fix IRQ check in sni_82596_probe 078b5a4498e0 scripts/dtc: dtx_diff: remove broken example from help text 21513c461557 dt-bindings: watchdog: Require samsung,syscon-phandle for Exynos7 23bcf3615be7 dt-bindings: display: meson-vpu: Add missing amlogic,canvas property 66467cc87a35 dt-bindings: display: meson-dw-hdmi: add missing sound-name-prefix property 4496e4a427a0 net: mscc: ocelot: fix using match before it is set ee64479c9ce6 net: sfp: fix high power modules without diagnostic monitoring 819e76bc572e net: ethernet: mtk_eth_soc: fix error checking in mtk_mac_config() 4691c9f047a8 bcmgenet: add WOL IRQ check 6973b38b9dba net_sched: restore "mpu xxx" handling 20949c381646 net: bonding: fix bond_xmit_broadcast return value error bug 799730d182d1 arm64: dts: qcom: msm8996: drop not documented adreno properties f6d4c0e017ec devlink: Remove misleading internal_flags from health reporter dump 2e51a761b7ab perf probe: Fix ppc64 'perf probe add events failed' case 59b44f77601d dmaengine: at_xdmac: Fix at_xdmac_lld struct definition 0078f053714d dmaengine: at_xdmac: Fix lld view setting 7ab120636d4e dmaengine: at_xdmac: Fix concurrency over xfers_list b5b27c5e3315 dmaengine: at_xdmac: Print debug message after realeasing the lock c536b351a75f dmaengine: at_xdmac: Start transfer for cyclic channels in issue_pending cd22e22e8eac dmaengine: at_xdmac: Don't start transactions at tx_submit level 68a83051c8b1 perf script: Fix hex dump character output 7b9d40e9f60d libcxgb: Don't accidentally set RTO_ONLINK in cxgb_find_route() cd5c24d2230f gre: Don't accidentally set RTO_ONLINK in gre_fill_metadata_dst() 7f2ca96bd266 xfrm: Don't accidentally set RTO_ONLINK in decode_session4() 2b1415c60b2e netns: add schedule point in ops_exit_list() edc09548ffc5 inet: frags: annotate races around fqdir->dead and fqdir->high_thresh 69e7e979ed66 taskstats: Cleanup the use of task->exit_code 56daa21414e9 virtio_ring: mark ring unused on error 0c4ebcb00d88 vdpa/mlx5: Fix wrong configuration of virtio_version_1_0 c736ec01a2fc rtc: pxa: fix null pointer dereference 8b8ff4c793ee HID: vivaldi: fix handling devices not using numbered reports d7544cf6939c net: axienet: increase default TX ring size to 128 557829d42d1f net: axienet: fix for TX busy handling 41831d496772 net: axienet: fix number of TX ring slots for available check 6301f3566aef net: axienet: Fix TX ring slot available check 7a3d3d7f6d7b net: axienet: limit minimum TX ring size 2f548489d64d net: axienet: add missing memory barriers bcc5d57e6091 net: axienet: reset core on initialization prior to MDIO access 46c0ccaff285 net: axienet: Wait for PhyRstCmplt after core reset 34942a228aec net: axienet: increase reset timeout a66b9bccf732 net/smc: Fix hung_task when removing SMC-R devices 51b52cf35485 clk: si5341: Fix clock HW provider cleanup fe40f7aef387 clk: Emit a stern warning with writable debugfs enabled 38221afa03af af_unix: annote lockless accesses to unix_tot_inflight & gc_in_progress a49e402f2309 f2fs: fix to reserve space for IO align feature 39ad0581176d f2fs: compress: fix potential deadlock of compress file e1840365ed4f parisc: pdc_stable: Fix memory leak in pdcs_register_pathentries d806eb5f4e23 net/fsl: xgmac_mdio: Fix incorrect iounmap when removing module 38c798384b90 net/fsl: xgmac_mdio: Add workaround for erratum A-009885 734f4b0f831e ipv4: avoid quadratic behavior in netns dismantle 86f0587f7432 ipv4: update fib_info_cnt under spinlock protection 10e99ae9b5da perf evsel: Override attr->sample_period for non-libpfm4 events 58fa3e900255 xdp: check prog type before updating BPF link 38ee417f59c8 bpftool: Remove inclusion of utilities.mak from Makefiles 2bcab471a26f block: Fix fsync always failed if once failed 5e59f885353e powerpc/fsl/dts: Enable WA for erratum A-009885 on fman3l MDIO buses 19aaef651948 powerpc/cell: Fix clang -Wimplicit-fallthrough warning 4cb7aba1e086 Revert "net/mlx5: Add retry mechanism to the command entry index allocation" 78cf5f63a3a9 dmaengine: stm32-mdma: fix STM32_MDMA_CTBR_TSEL_MASK 16ad0aa917c9 RDMA/rxe: Fix a typo in opcode name 885860717c29 RDMA/hns: Modify the mapping attribute of doorbell to device 57cd8597c3ef dmaengine: uniphier-xdmac: Fix type of address variables 4fe77b7cd272 scsi: core: Show SCMD_LAST in text form b30240911da4 Bluetooth: hci_sync: Fix not setting adv set duration 55698d11c8da Documentation: fix firewire.rst ABI file path error 5d38cbf66dd7 Documentation: refer to config RANDOMIZE_BASE for kernel address-space randomization abecf9d74836 Documentation: ACPI: Fix data node reference documentation d1e85fcd73b5 Documentation: dmaengine: Correctly describe dmatest with channel unset f6736bd81db4 media: correct MEDIA_TEST_SUPPORT help text 55b10b88ac86 drm/vc4: hdmi: Make sure the device is powered with CEC 81ac08a800b0 media: rcar-csi2: Optimize the selection PHTW register 0baa3729d2eb can: mcp251xfd: mcp251xfd_tef_obj_read(): fix typo in error message f62bf6ee4fa3 firmware: Update Kconfig help text for Google firmware 12224c0d19f3 of: base: Improve argument length mismatch error 7bb99c7e13f8 drm/radeon: fix error handling in radeon_driver_open_kms 0ca7ec6db20c ext4: don't use the orphan list when migrating an inode 679fb065326b ext4: fix null-ptr-deref in '__ext4_journal_ensure_credits' d60e9daba29e ext4: destroy ext4_fc_dentry_cachep kmemcache on module removal f26b24b4c115 ext4: fast commit may miss tracking unwritten range during ftruncate 04b562730677 ext4: use ext4_ext_remove_space() for fast commit replay delete range 53998b3f6dcd ext4: Fix BUG_ON in ext4_bread when write quota data da364ab35892 ext4: set csum seed in tmp inode while migrating to extents e4221629d5e1 ext4: fix fast commit may miss tracking range for FALLOC_FL_ZERO_RANGE 720508dd118d ext4: initialize err_blk before calling __ext4_get_inode_loc f9ed0ea0a9fc ext4: fix a possible ABBA deadlock due to busy PA 115b762b48ab ext4: make sure quota gets properly shutdown on error 762e4c33e9e5 ext4: make sure to reset inode lockdep class when quota enabling fails f8c3ec2e21b9 btrfs: respect the max size in the header when activating swap file e7764bccae77 btrfs: check the root node for uptodate before returning it 09e0ef287e93 btrfs: fix deadlock between quota enable and other quota operations 56f974d583fc xfrm: fix policy lookup for ipv6 gre packets 84166c1177f3 PCI: pci-bridge-emul: Set PCI_STATUS_CAP_LIST for PCIe device 7aeeb9fe9ca0 PCI: pci-bridge-emul: Correctly set PCIe capabilities af1d0acdaca7 PCI: pci-bridge-emul: Fix definitions of reserved bits 0f2ae6691e73 PCI: pci-bridge-emul: Properly mark reserved PCIe bits in PCI config space 2a0d437d8a76 PCI: pci-bridge-emul: Make expansion ROM Base Address register read-only def2825b09ec PCI: pciehp: Use down_read/write_nested(reset_lock) to fix lockdep errors 6cbe8f8deb62 PCI: xgene: Fix IB window setup e09f47e77b6e powerpc/64s/radix: Fix huge vmap false positive eb44b1386af5 parisc: Fix lpa and lpa_user defines 9b78ee2341d4 drm/bridge: analogix_dp: Make PSR-exit block less 8cbbf4a6f1ac drm/nouveau/kms/nv04: use vzalloc for nv04_display 605583fcccb5 drm/etnaviv: limit submit sizes 6c1e3d8b1bff device property: Fix fwnode_graph_devcon_match() fwnode leak ecb71f7bd584 s390/mm: fix 2KB pgtable release race 798754ba48b7 iwlwifi: mvm: Increase the scan timeout guard to 30 seconds c524f4cfb3e5 tracing/kprobes: 'nmissed' not showed correctly for kretprobe b72075e395b3 cputime, cpuacct: Include guest time in user time in cpuacct.stat 13518f058fde serial: Fix incorrect rs485 polarity on uart open 9668cf9e4af0 fuse: Pass correct lend value to filemap_write_and_wait_range() 9fbaddd783fd xen/gntdev: fix unmap notification order 67b078d996f7 spi: uniphier: Fix a bug that doesn't point to private data correctly 05026c4e94c9 tpm: fix NPE on probe for missing device 76006d33f1c8 ubifs: Error path in ubifs_remount_rw() seems to wrongly free write buffers 4f0762ac32b5 crypto: caam - replace this_cpu_ptr with raw_cpu_ptr 9e6ff2d5725b crypto: stm32/crc32 - Fix kernel BUG triggered in probe() 2031e0246e45 crypto: omap-aes - Fix broken pm_runtime_and_get() usage 43e94431c313 rpmsg: core: Clean up resources on announce_create failure. 082ff9e12b4a phy: mediatek: Fix missing check in mtk_mipi_tx_probe ff08cf1e34a1 ASoC: mediatek: mt8183: fix device_node leak f28672eef4a9 ASoC: mediatek: mt8173: fix device_node leak 0df51040089d scsi: sr: Don't use GFP_DMA de9a936b04c5 MIPS: Octeon: Fix build errors using clang da7df943e254 i2c: designware-pci: Fix to change data types of hcnt and lcnt parameters f09f7ccb28bb irqchip/gic-v4: Disable redistributors' view of the VPE table at boot time bc2d961d821b MIPS: OCTEON: add put_device() after of_find_device_by_node() ce34b03a71b6 udf: Fix error handling in udf_new_inode() 15be042e7fd9 powerpc/fadump: Fix inaccurate CPU state info in vmcore generated with panic f2e658d9bda2 powerpc: handle kdump appropriately with crash_kexec_post_notifiers option 044164b4198e selftests/powerpc/spectre_v2: Return skip code when miss_percent is high 21125e011620 powerpc/40x: Map 32Mbytes of memory at startup c330442f46ea MIPS: Loongson64: Use three arguments for slti af8d07735083 ALSA: seq: Set upper limit of processed events 297210783a7a scsi: lpfc: Trigger SLI4 firmware dump before doing driver cleanup dfde7afed711 dm: fix alloc_dax error handling in alloc_dev 2e2086f49e08 nvmem: core: set size for sysfs bin file 4a273a94bda8 w1: Misuse of get_user()/put_user() reported by sparse 87e91d6c6a5e KVM: PPC: Book3S: Suppress failed alloc warning in H_COPY_TOFROM_GUEST 23bb3f01ceb5 KVM: PPC: Book3S: Suppress warnings when allocating too big memory slots 03c1595a181c powerpc/powermac: Add missing lockdep_register_key() df29c01b9fbe clk: meson: gxbb: Fix the SDM_EN bit for MPLL0 on GXBB 30d35a1abd9e i2c: mpc: Correct I2C reset procedure 4b25aad655c9 powerpc/smp: Move setup_profiling_timer() under CONFIG_PROFILING 25714ad6bf5e i2c: i801: Don't silently correct invalid transfer size 75e2cfa5fae9 powerpc/watchdog: Fix missed watchdog reset due to memory ordering race a83639521a4f powerpc/btext: add missing of_node_put fc10d8f00a89 powerpc/cell: add missing of_node_put 297ff7d5f157 powerpc/powernv: add missing of_node_put c83ba875d7be powerpc/6xx: add missing of_node_put d240b08d8ac4 x86/kbuild: Enable CONFIG_KALLSYMS_ALL=y in the defconfigs 3681e9f3f0f7 parisc: Avoid calling faulthandler_disabled() twice f2a27dd7a2de random: do not throw away excess input to crng_fast_load f8fdebfb4b37 serial: core: Keep mctrl register state and cached copy in sync a03fd1b19891 serial: pl010: Drop CR register reset on set_termios 40ac33892630 regulator: qcom_smd: Align probe function with rpmh-regulator 3dc751213fe9 net: gemini: allow any RGMII interface mode 1063de897563 net: phy: marvell: configure RGMII delays for 88E1118 00580670b98b mlxsw: pci: Avoid flow control for EMAD packets eaf8cffcf5d5 dm space map common: add bounds check to sm_ll_lookup_bitmap() 5850bef8e955 dm btree: add a defensive bounds check to insert_at() 754b663ea916 mac80211: allow non-standard VHT MCS-10/11 e8da60b3a629 net: mdio: Demote probed message to debug print 6b22c9824ddb btrfs: remove BUG_ON(!eie) in find_parent_nodes 623c65bc7336 btrfs: remove BUG_ON() in find_parent_nodes() 44cbd2a16a07 ACPI: battery: Add the ThinkPad "Not Charging" quirk 7b6dc07c6e69 amdgpu/pm: Make sysfs pm attributes as read-only for VFs 516e332d6fce drm/amdgpu: fixup bad vram size on gmc v8 ee88ff140de2 ACPICA: Hardware: Do not flush CPU cache when entering S4 and S5 8544074762e2 ACPICA: Fix wrong interpretation of PCC address e70be176961d ACPICA: Executer: Fix the REFCLASS_REFOF case in acpi_ex_opcode_1A_0T_1R() 8ea9216d20b7 ACPICA: Utilities: Avoid deleting the same object twice in a row fcfd8282c5d2 ACPICA: actypes.h: Expand the ACPI_ACCESS_ definitions e3a51d6c90a8 jffs2: GC deadlock reading a page that is used in jffs2_write_begin() e35cb5b122fc drm/etnaviv: consider completed fence seqno in hang check a0b13335a342 xfrm: rate limit SA mapping change message to user space 0b7beb2fea8f Bluetooth: vhci: Set HCI_QUIRK_VALID_LE_STATES 6ac117edac18 ath11k: Fix napi related hang 756a7188b277 um: registers: Rename function names to avoid conflicts and build problems d817d10f7a00 iwlwifi: pcie: make sure prph_info is set when treating wakeup IRQ f266e1c5bf88 iwlwifi: mvm: Fix calculation of frame length 6e44b600543c iwlwifi: remove module loading failure message febab6b60d61 iwlwifi: fix leaks/bad data after failed firmware load 81d2e96ababb PM: AVS: qcom-cpr: Use div64_ul instead of do_div c0a1d844e3e7 rtw88: 8822c: update rx settings to prevent potential hw deadlock 3ef25f3122c0 ath9k: Fix out-of-bound memcpy in ath9k_hif_usb_rx_stream e10de3105547 usb: hub: Add delay for SuperSpeed hub resume to let links transit to U0 282286c632a2 cpufreq: Fix initialization of min and max frequency QoS requests 37b25de3af10 PM: runtime: Add safety net to supplier device release 5dfc6fa0b8c2 arm64: tegra: Adjust length of CCPLEX cluster MMIO region b68c56a149e4 arm64: dts: ls1028a-qds: move rtc node to the correct i2c bus b6f7f0ad5af5 audit: ensure userspace is penalized the same as the kernel when under pressure 5d54ed155031 mmc: core: Fixup storing of OCR for MMC_QUIRK_NONSTD_SDIO 51a5156bb779 media: saa7146: hexium_gemini: Fix a NULL pointer dereference in hexium_attach() f6bc6b178ce1 media: igorplugusb: receiver overflow should be reported d698e024be2e HID: quirks: Allow inverting the absolute X/Y values 59f03633463f bpf: Do not WARN in bpf_warn_invalid_xdp_action() 0e8805f73b69 net: bonding: debug: avoid printing debug logs when bond is not notifying peers 8c72de32ff13 x86/mce: Mark mce_read_aux() noinstr 1ad3e60f1fec x86/mce: Mark mce_end() noinstr f21ca973b43f x86/mce: Mark mce_panic() noinstr de360d944386 x86/mce: Allow instrumentation during task work queueing af371e0abb6c ath11k: Avoid false DEADLOCK warning reported by lockdep aec69e2f33b4 selftests/ftrace: make kprobe profile testcase description unique 07ecabf15ad3 gpio: aspeed: Convert aspeed_gpio.lock to raw_spinlock 7e09f9d15e43 net: phy: prefer 1000baseT over 1000baseKX 443133330a5d net-sysfs: update the queue counts in the unregistration path 58b4c1ce8328 ath10k: Fix tx hanging fcba0bce3357 ath11k: avoid deadlock by change ieee80211_queue_work for regd_update_work 93a108d466f8 iwlwifi: mvm: avoid clearing a just saved session protection id ec01e0fe2184 iwlwifi: mvm: synchronize with FW after multicast commands c1976a424807 thunderbolt: Runtime PM activate both ends of the device link 830e5d1b4344 media: m920x: don't use stack on USB reads c33f0f22bfea media: saa7146: hexium_orion: Fix a NULL pointer dereference in hexium_attach() 526b6c9b4521 media: rcar-vin: Update format alignment constraints 74e60c1dce06 media: uvcvideo: Increase UVC_CTRL_CONTROL_TIMEOUT to 5 seconds. d0e3ab637de1 drm: rcar-du: Fix CRTC timings when CMM is used e61aa46d0f27 x86/mm: Flush global TLB when switching to trampoline page-table 0946fdd9290a floppy: Add max size check for user space request 409d45bcd381 usb: uhci: add aspeed ast2600 uhci support d0aec428c072 arm64: dts: ti: j7200-main: Fix 'dtbs_check' serdes_ln_ctrl node fcb45ac39f90 ACPI / x86: Add not-present quirk for the PCI0.SDHB.BRC1 device on the GPD win b8b2e74a8751 ACPI / x86: Allow specifying acpi_device_override_status() quirks by path cda755506df4 ACPI: Change acpi_device_always_present() into acpi_device_override_status() b029625063c1 ACPI / x86: Drop PWM2 device on Lenovo Yoga Book from always present table cf3b1a160dc2 media: venus: avoid calling core_clk_setrate() concurrently during concurrent video sessions adbe14867277 ath11k: Avoid NULL ptr access during mgmt tx cleanup ab523ea096ef rsi: Fix out-of-bounds read in rsi_read_pkt() 752587675068 rsi: Fix use-after-free in rsi_rx_done_handler() 6036500fdf77 mwifiex: Fix skb_over_panic in mwifiex_usb_recv() 8a6371d84c5f crypto: jitter - consider 32 LSB for APT 240cf5d3cb5e HSI: core: Fix return freed object in hsi_new_client f4295b7dca87 gpiolib: acpi: Do not set the IRQ type if the IRQ is already in use f0653cd4da66 tty: serial: imx: disable UCR4_OREN in .stop_rx() instead of .shutdown() b8d10f601f22 drm/bridge: megachips: Ensure both bridges are probed before registration 43fc9e267e2e mlxsw: pci: Add shutdown method in PCI driver b2e921fa9219 soc: ti: pruss: fix referenced node in error message 07fbbc4dc79d drm/amdgpu/display: set vblank_disable_immediate for DC 019fe9723a83 drm/amd/display: check top_pipe_to_program pointer 3c3c0b6c4ae9 ARM: imx: rename DEBUG_IMX21_IMX27_UART to DEBUG_IMX27_UART f54d8cd831be EDAC/synopsys: Use the quirk for version instead of ddr version 0b85d73fdbc8 media: b2c2: Add missing check in flexcop_pci_isr: c978d39a8b14 HID: apple: Do not reset quirks when the Fn key is not found 2df002e3276b drm: panel-orientation-quirks: Add quirk for the Lenovo Yoga Book X91F/L 5aa57672c66c usb: gadget: f_fs: Use stream_open() for endpoint files 129e8faaee97 ath11k: Fix crash caused by uninitialized TX ring e8b271f2aadd media: atomisp: handle errors at sh_css_create_isp_params() ebe9c978d9e7 batman-adv: allow netlink usage in unprivileged containers ff452db96163 ARM: shmobile: rcar-gen2: Add missing of_node_put() ff2138d6c2a3 media: atomisp-ov2680: Fix ov2680_set_fmt() clobbering the exposure 51ef6582a218 media: atomisp: set per-device's default mode ac08140677c0 media: atomisp: fix try_fmt logic 518e059789f6 drm/nouveau/pmu/gm200-: avoid touching PMU outside of DEVINIT/PREOS/ACR e3ba02b043f2 drm/bridge: dw-hdmi: handle ELD when DRM_BRIDGE_ATTACH_NO_CONNECTOR 2f13f10fddf4 ar5523: Fix null-ptr-deref with unexpected WDCMSG_TARGET_START reply a9d2ccfc7d2c selftests/bpf: Fix bpf_object leak in skb_ctx selftest b207356933f4 drm/lima: fix warning when CONFIG_DEBUG_SG=y & CONFIG_DMA_API_DEBUG=y db1e878373bf fs: dlm: filter user dlm messages for kernel locks f9c9a46efd94 Bluetooth: Fix debugfs entry leak in hci_register_dev() 852d7d436fd1 ARM: dts: omap3-n900: Fix lp5523 for multi color b5793aff11d7 of: base: Fix phandle argument length mismatch error message e16e836d510c clk: bm1880: remove kfrees on static allocations 36d46e21c9c4 ASoC: fsl_asrc: refine the check of available clock divider 5a6864e2e6ab RDMA/cxgb4: Set queue pair state when being queried 80524c8cdf29 ASoC: fsl_mqs: fix MODULE_ALIAS 74988d017dd1 powerpc/xive: Add missing null check after calling kmalloc 588e0b81ce38 mips: bcm63xx: add support for clk_set_parent() e3de89d010c0 mips: lantiq: add support for clk_set_parent() 8f8468a089b0 arm64: tegra: Remove non existent Tegra194 reset 702902fc7fb0 arm64: tegra: Fix Tegra194 HDA {clock,reset}-names ordering 24b047d72c77 counter: stm32-lptimer-cnt: remove iio counter abi a39460610452 misc: lattice-ecp3-config: Fix task hung when firmware load failed 696a50abbc7c ASoC: samsung: idma: Check of ioremap return value d491a2c2cf96 ASoC: mediatek: Check for error clk pointer c73ccdd62d21 phy: uniphier-usb3ss: fix unintended writing zeros to PHY register d781f4cd8c71 scsi: block: pm: Always set request queue runtime active in blk_post_runtime_resume() 6e2a16954459 iommu/iova: Fix race between FQ timeout and teardown 57bc8985753c ASoC: Intel: catpt: Test dmaengine_submit() result before moving on 676049a3d2c6 iommu/amd: Restore GA log/tail pointer on host resume c2bd7c31de1a iommu/amd: Remove iommu_init_ga() 62ea255f2bde dmaengine: pxa/mmp: stop referencing config->slave_id 0be9ae1e532e mips: fix Kconfig reference to PHYS_ADDR_T_64BIT 88d78b25db1f mips: add SYS_HAS_CPU_MIPS64_R5 config for MIPS Release 5 support 51b8e814bcef clk: stm32: Fix ltdc's clock turn off by clk_disable_unused() after system enter shell dff359e04260 of: unittest: 64 bit dma address test requires arch support 918105df78b7 of: unittest: fix warning on PowerPC frame size warning 0e04518b1dd9 ASoC: rt5663: Handle device_property_read_u32_array error codes 7c0d9c815ce8 RDMA/cma: Let cma_resolve_ib_dev() continue search even after empty entry 2432d325f946 RDMA/core: Let ib_find_gid() continue search even after empty entry d77916df161b powerpc/powermac: Add additional missing lockdep_register_key() 8b3783e517f6 PCI/MSI: Fix pci_irq_vector()/pci_irq_get_affinity() 7be2a0bcaf8e RDMA/qedr: Fix reporting max_{send/recv}_wr attrs e19469468b7b scsi: ufs: Fix race conditions related to driver data ed43b2e048fe iommu/io-pgtable-arm: Fix table descriptor paddr formatting e9e4d1fb4590 openrisc: Add clone3 ABI wrapper 551a785c26f6 binder: fix handling of error during copy 88ddf033a5e4 char/mwave: Adjust io port register size 8937aee4c0fa ALSA: usb-audio: Drop superfluous '0' in Presonus Studio 1810c's ID bcd533417fd0 ALSA: oss: fix compile error when OSS_DEBUG is enabled fd99aeb97845 clocksource: Avoid accidental unstable marking of clocksources cacc6c30e3eb clocksource: Reduce clocksource-skew threshold 86ad478c99d2 powerpc/32s: Fix shift-out-of-bounds in KASAN init ef798cd035f3 powerpc/perf: Fix PMU callbacks to clear pending PMI before resetting an overflown PMC 58014442a9e8 powerpc/irq: Add helper to set regs->softe c9ffa84a3bd1 powerpc/perf: move perf irq/nmi handling details into traps.c a0758b3be46d powerpc/perf: MMCR0 control for PMU registers under PMCC=00 f4df6db5b0b8 powerpc/64s: Convert some cpu_setup() and cpu_restore() functions to C a9c9d2ff6423 dt-bindings: thermal: Fix definition of cooling-maps contribution property 2bd8d937957f ASoC: uniphier: drop selecting non-existing SND_SOC_UNIPHIER_AIO_DMA 5a821af769bb powerpc/prom_init: Fix improper check of prom_getprop() 9ca761ef946d clk: imx8mn: Fix imx8mn_clko1_sels 999528d8a749 scsi: pm80xx: Update WARN_ON check in pm8001_mpi_build_cmd() c5f414d69ac9 RDMA/hns: Validate the pkey index 04a032ea2498 RDMA/bnxt_re: Scan the whole bitmap when checking if "disabling RCFW with pending cmd-bit" 84cd5c029d48 ALSA: hda: Add missing rwsem around snd_ctl_remove() calls 180e9d7384c6 ALSA: PCM: Add missing rwsem around snd_ctl_remove() calls 49d76154ba8d ALSA: jack: Add missing rwsem around snd_ctl_remove() calls f871cd8ee0f0 ext4: avoid trim error on fs with small groups 99590e820feb net: mcs7830: handle usb read errors properly 2b948524ae65 iwlwifi: mvm: Use div_s64 instead of do_div in iwl_mvm_ftm_rtt_smoothing() 04ce9e2aeda7 pcmcia: fix setting of kthread task states 5064bfe046b0 can: xilinx_can: xcan_probe(): check for error irq b6dd1577bc92 can: softing: softing_startstop(): fix set but not used variable warning b9ac866c23bb tpm_tis: Fix an error handling path in 'tpm_tis_core_init()' fb46223c9f94 tpm: add request_locality before write TPM_INT_ENABLE 20edf903a3a5 can: mcp251xfd: add missing newline to printed strings d71fca5d0167 regmap: Call regmap_debugfs_exit() prior to _init() 838acddcdf75 netrom: fix api breakage in nr_setsockopt() 0d04479857bc ax25: uninitialized variable in ax25_setsockopt() 27e9910c4516 spi: spi-meson-spifc: Add missing pm_runtime_disable() in meson_spifc_probe 9d6350cf8e5a Bluetooth: L2CAP: uninitialized variables in l2cap_sock_setsockopt() 9defd7d4c084 lib/mpi: Add the return value check of kcalloc() e801f81cee3c net/mlx5: Set command entry semaphore up once got index free d2b9ce705d79 Revert "net/mlx5e: Block offload of outer header csum for UDP tunnels" 67e1a449a165 net/mlx5e: Don't block routes with nexthop objects in SW cc40fa05c0a6 net/mlx5e: Fix page DMA map/unmap attributes b3dda01d1d47 debugfs: lockdown: Allow reading debugfs files that are not world readable b9b5da3e187e HID: hid-uclogic-params: Invalid parameter check in uclogic_params_frame_init_v1_buttonpad 541c3a044b46 HID: hid-uclogic-params: Invalid parameter check in uclogic_params_huion_init c47f842e0c3c HID: hid-uclogic-params: Invalid parameter check in uclogic_params_get_str_desc cf5ad827ee69 HID: hid-uclogic-params: Invalid parameter check in uclogic_params_init 94177fcecc35 usb: dwc3: qcom: Fix NULL vs IS_ERR checking in dwc3_qcom_probe 4579954bf4cc Bluetooth: hci_qca: Fix NULL vs IS_ERR_OR_NULL check in qca_serdev_probe f6bf3d66393b Bluetooth: hci_bcm: Check for error irq f5e4f68d57d6 fsl/fman: Check for null pointer after calling devm_ioremap 60aca6fdc167 staging: greybus: audio: Check null pointer a1068bfee47a rocker: fix a sleeping in atomic bug 2db344725e17 ppp: ensure minimum packet size in ppp_write() 45643b1b6ce1 netfilter: nft_set_pipapo: allocate pcpu scratch maps on clone 8772700a9f1e bpf: Fix SO_RCVBUF/SO_SNDBUF handling in _bpf_setsockopt(). 342332fb0be6 bpf: Don't promote bogus looking registers after null check. 0036c78c492a netfilter: ipt_CLUSTERIP: fix refcount leak in clusterip_tg_check() 2e718389b986 power: reset: mt6397: Check for null res pointer 4210c35fe81b pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in nonstatic_find_mem_region() 2dee347f356d pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in __nonstatic_find_io_region() 0f03132191ba ACPI: scan: Create platform device for BCM4752 and LNV4752 ACPI nodes 595e1ec55b30 x86/mce/inject: Avoid out-of-bounds write when setting flags df1268181928 hwmon: (mr75203) fix wrong power-up delay value aea5302d9ddc x86/boot/compressed: Move CLANG_FLAGS to beginning of KBUILD_CFLAGS 70eec71f32eb Bluetooth: hci_qca: Stop IBS timer during BT OFF 1d4e722b62d2 software node: fix wrong node passed to find nargs_prop f8f3c1720d77 backlight: qcom-wled: Respect enabled-strings in set_brightness de79bcbfaf4d backlight: qcom-wled: Use cpu_to_le16 macro to perform conversion c79f9b8d8e26 backlight: qcom-wled: Override default length with qcom,enabled-strings bf4daf6153c9 backlight: qcom-wled: Fix off-by-one maximum with default num_strings 09aed85e8c98 backlight: qcom-wled: Pass number of elements to read to read_u32_array f4ed4fc504fd backlight: qcom-wled: Validate enabled string indices in DT e668ac6506d3 bpftool: Enable line buffering for stdout 009bb7ee1577 Bluetooth: L2CAP: Fix using wrong mode 1a2241ad400b um: virtio_uml: Fix time-travel external time propagation 8411722e5652 um: fix ndelay/udelay defines b2b1b490bd29 selinux: fix potential memleak in selinux_add_opt() 3253cf091464 mmc: meson-mx-sdio: add IRQ check decb2099549d mmc: meson-mx-sdhc: add IRQ check bdc6c9fc5f78 iwlwifi: mvm: test roc running status bits before removing the sta a750fcd604a6 iwlwifi: mvm: fix 32-bit build in FTM 86b0122d2682 ARM: dts: armada-38x: Add generic compatible to UART nodes 1f5428e43806 arm64: dts: marvell: cn9130: enable CP0 GPIO controllers 874b97e86278 arm64: dts: marvell: cn9130: add GPIO and SPI aliases 407ef1db4036 usb: ftdi-elan: fix memory leak on device disconnect 2a65da5a1ea3 ARM: 9159/1: decompressor: Avoid UNPREDICTABLE NOP encoding 47dd693c94bf xfrm: state and policy should fail if XFRMA_IF_ID 0 db369047e3b3 xfrm: interface with if_id 0 should return error 37441ddadc1e media: hantro: Fix probe func error path 3849ec830bf7 drm/tegra: vic: Fix DMA API misuse b230114bc57a drm/bridge: ti-sn65dsi86: Set max register for regmap db97fc2c4425 drm/msm/dpu: fix safe status debugfs file 3580055d1fca arm64: dts: qcom: ipq6018: Fix gpio-ranges property 6f20a5a98a90 arm64: dts: qcom: c630: Fix soundcard setup 394ee480aa3e ath11k: Fix a NULL pointer dereference in ath11k_mac_op_hw_scan() f6e4a6cbdb6f media: coda/imx-vdoa: Handle dma_set_coherent_mask error codes 1a8869de328a media: msi001: fix possible null-ptr-deref in msi001_probe() a79327bb0191 media: dw2102: Fix use after free 958a8819d414 ARM: dts: gemini: NAS4220-B: fis-index-block with 128 KiB sectors 3e51460638a6 ath11k: Fix deleting uninitialized kernel timer during fragment cache flush b35263f000a5 crypto: stm32 - Revert broken pm_runtime_resume_and_get changes 1f5b81874f27 crypto: stm32/cryp - fix bugs and crash in tests 1f6151b0774b crypto: stm32/cryp - fix lrw chaining mode 2bd40e3a3aa2 crypto: stm32/cryp - fix double pm exit 533af1621d1c crypto: stm32/cryp - check early input data 5deb24e50372 crypto: stm32/cryp - fix xts and race condition in crypto_engine requests e9e0dd5da8ca crypto: stm32/cryp - fix CTR counter carry c40b1bc851e0 crypto: stm32 - Fix last sparse warning in stm32_cryp_check_ctr_counter 93033bbbdc25 selftests: harness: avoid false negatives if test has no ASSERTs f568fd97d751 selftests: clone3: clone3: add case CLONE3_ARGS_NO_TEST d21b47c60737 x86/uaccess: Move variable into switch case statement 3e801ea43c4b xfrm: fix a small bug in xfrm_sa_len() b87034d7a2a8 mwifiex: Fix possible ABBA deadlock 0836f9404017 rcu/exp: Mark current CPU as exp-QS in IPI loop second pass 027165c491e4 drm/msm/dp: displayPort driver need algorithm rational 268f35245650 sched/rt: Try to restart rt period timer when rt runtime exceeded bb0579ab5077 wireless: iwlwifi: Fix a double free in iwl_txq_dyn_alloc_dma b4b911b1648c media: si2157: Fix "warm" tuner state detection 7009a5fbc589 media: saa7146: mxb: Fix a NULL pointer dereference in mxb_attach() df79d2bf95e0 media: dib8000: Fix a memleak in dib8000_init() f0cb43a2c674 arm64: clear_page() shouldn't use DC ZVA when DCZID_EL0.DZP == 1 88ed31aab481 arm64: lib: Annotate {clear, copy}_page() as position-independent 69e402a98541 bpf: Remove config check to enable bpf support for branch records 924886fa2246 bpf: Disallow BPF_LOG_KERNEL log level for bpf(BPF_BTF_LOAD) 218d952160f7 bpf: Adjust BTF log size limit. b77ef5b4ead6 sched/fair: Fix per-CPU kthread and wakee stacking for asym CPU capacity d7d5b3bc5263 sched/fair: Fix detection of per-CPU kthreads waking a task ec121517ac8d Bluetooth: btmtksdio: fix resume failure 2a7edcb3ef72 staging: rtl8192e: rtllib_module: fix error handle case in alloc_rtllib() 49f5cd2b7c41 staging: rtl8192e: return error code from rtllib_softmac_init() 04fdd426cef2 floppy: Fix hang in watchdog when disk is ejected 45bbe008013f serial: amba-pl011: do not request memory region twice 8409d2394cca tty: serial: uartlite: allow 64 bit address a001a15ab374 arm64: dts: ti: k3-j7200: Correct the d-cache-sets info 75919207c16a arm64: dts: ti: k3-j721e: Fix the L2 cache sets 2dcfa3c76596 arm64: dts: ti: k3-j7200: Fix the L2 cache sets f277978d6c46 drm/radeon/radeon_kms: Fix a NULL pointer dereference in radeon_driver_open_kms() 3ca1b3b82fe7 drm/amdgpu: Fix a NULL pointer dereference in amdgpu_connector_lcd_native_mode() 96e05d2d9370 thermal/drivers/imx8mm: Enable ADC when enabling monitor ef72449e2d79 ACPI: EC: Rework flushing of EC work while suspended to idle c0acd5a09796 cgroup: Trace event cgroup id fields should be u64 e7e178e26418 arm64: dts: qcom: msm8916: fix MMC controller aliases 894d91c6334b netfilter: bridge: add support for pppoe filtering 13f64bbe4255 thermal/drivers/imx: Implement runtime PM support c3a59f34e87c media: venus: core: Fix a resource leak in the error handling path of 'venus_probe()' 50c4244906d6 media: venus: core: Fix a potential NULL pointer dereference in an error handling path eeefa2eae8fc media: venus: core, venc, vdec: Fix probe dependency error 53f65afc260f media: venus: pm_helpers: Control core power domain manually 89f518b153d1 media: coda: fix CODA960 JPEG encoder buffer overflow 1da628d351a9 media: mtk-vcodec: call v4l2_m2m_ctx_release first when file is released 2028fb832da6 media: si470x-i2c: fix possible memory leak in si470x_i2c_probe() e8d78f924f02 media: imx-pxp: Initialize the spinlock prior to using it 621e8ce75d66 media: rcar-csi2: Correct the selection of hsfreqrange ad52b9890b83 mfd: atmel-flexcom: Use .resume_noirq 46d6a2311409 mfd: atmel-flexcom: Remove #ifdef CONFIG_PM_SLEEP f93c9aa1d36f tty: serial: atmel: Call dma_async_issue_pending() 755a6c873b9c tty: serial: atmel: Check return code of dmaengine_submit() bd85b2e77aa9 arm64: dts: ti: k3-j721e: correct cache-sets info 32e9947e6639 ath11k: Use host CE parameters for CE interrupts configuration 6a49acfacab5 crypto: qat - fix undetected PFVF timeout in ACK loop 475ac5c5653f crypto: qat - make pfvf send message direction agnostic ee1c74c3c9c2 crypto: qat - remove unnecessary collision prevention step in PFVF 472f76835200 crypto: qat - fix spelling mistake: "messge" -> "message" ae766527e6b7 ARM: dts: stm32: fix dtbs_check warning on ili9341 dts binding on stm32f429 disco eab4204588a0 mtd: hyperbus: rpc-if: fix bug in rpcif_hb_remove 867d4ace48da crypto: qce - fix uaf on qce_skcipher_register_one e19b3c1b5768 crypto: qce - fix uaf on qce_ahash_register_one 5de640f59f99 media: dmxdev: fix UAF when dvb_register_device() fails 1d64e2bd2222 arm64: dts: renesas: cat875: Add rx/tx delays a33eef23a658 drm/vboxvideo: fix a NULL vs IS_ERR() check 43220a61e7b8 fs: dlm: fix build with CONFIG_IPV6 disabled 0d7c5d10e7db tee: fix put order in teedev_close_context() 097e601eb887 ath11k: reset RSN/WPA present state for open BSS fa51addd391d ath11k: clear the keys properly via DISABLE_KEY df94b37e902b ath11k: Fix ETSI regd with weather radar overlap ffc9019bd991 Bluetooth: stop proccessing malicious adv data 3273541fed60 memory: renesas-rpc-if: Return error in case devm_ioremap_resource() fails 55917db35976 fs: dlm: don't call kernel_getpeername() in error_report() 98923ebb034b fs: dlm: use sk->sk_socket instead of con->sock 6edd1bd8e3d8 arm64: dts: meson-gxbb-wetek: fix missing GPIO binding eb1f75fa2458 arm64: dts: meson-gxbb-wetek: fix HDMI in early boot 6f012f2c445b arm64: dts: amlogic: Fix SPI NOR flash node name for ODROID N2/N2+ 96d710b1c6ff arm64: dts: amlogic: meson-g12: Fix GPU operating point table node name 0b57480ed51a media: aspeed: Update signal status immediately to ensure sane hw state 0ff0ae69d27c media: em28xx: fix memory leak in em28xx_init_dev b441d9428735 media: aspeed: fix mode-detect always time out at 2nd run 8d132d9dd8ba media: atomisp: fix uninitialized bug in gmin_get_pmic_id_and_addr() fc2b95e7aeae media: atomisp: fix enum formats logic 6e5353238c55 media: atomisp: add NULL check for asd obtained from atomisp_video_pipe 6cbabad304c4 media: staging: media: atomisp: pci: Balance braces around conditional statements in file atomisp_cmd.c 22b0b68f7d9f media: atomisp: fix ifdefs in sh_css.c 0bf5e8af6eb6 media: atomisp: fix inverted error check for ia_css_mipi_is_source_port_valid() 3cb3e66f583c media: atomisp: do not use err var when checking port validity for ISP2400 08e43223fb4e media: atomisp: fix inverted logic in buffers_needed() fb370f6dc7d5 media: atomisp: fix punit_ddr_dvfs_enable() argument for mrfld_power up case 1daacf9bb69a media: atomisp: add missing media_device_cleanup() in atomisp_unregister_entities() e1da9301cf54 media: videobuf2: Fix the size printk format 90807ab437e8 mtd: hyperbus: rpc-if: Check return value of rpcif_sw_init() 9bfed11dcf59 ath11k: Send PPDU_STATS_CFG with proper pdev mask to firmware 2fe056d9791a wcn36xx: fix RX BD rate mapping for 5GHz legacy rates 22406ed4e389 wcn36xx: populate band before determining rate on RX 92fea7bd5af3 wcn36xx: Put DXE block into reset before freeing memory 0d53c47f6ab5 wcn36xx: Release DMA channel descriptor allocations 1850195a852d wcn36xx: Fix DMA channel enable/disable cycle 38a7842889f5 wcn36xx: Indicate beacon not connection loss on MISSED_BEACON_IND fcb267bb9577 wcn36xx: ensure pairing of init_scan/finish_scan and start_scan/end_scan e53ff4dd7095 drm/vc4: hdmi: Set a default HSM rate b9c2343373f6 clk: bcm-2835: Remove rounding up the dividers 836dd37fe2bb clk: bcm-2835: Pick the closest clock rate 88f1b613c37f Bluetooth: cmtp: fix possible panic when cmtp_init_sockets() fails 9ddfa1c19191 drm/rockchip: dsi: Reconfigure hardware on resume() 58904ed18628 drm/rockchip: dsi: Disable PLL clock on bind error 6215cde02085 drm/rockchip: dsi: Hold pm-runtime across bind/unbind 8ccaafa1caf0 drm/rockchip: dsi: Fix unbalanced clock on probe error 9bc19022aa08 drm/panel: innolux-p079zca: Delete panel on attach() failure b01b7b868479 drm/panel: kingdisplay-kd097d04: Delete panel on attach() failure 0499c863a8db drm: fix null-ptr-deref in drm_dev_init_release() 7798757013ec drm/bridge: display-connector: fix an uninitialized pointer in probe() cb5813b0e591 Bluetooth: L2CAP: Fix not initializing sk_peer_pid ed0b1fd3ec6e drm/ttm: Put BO in its memory manager's lru list 7b9fa915a58d shmem: fix a race between shmem_unused_huge_shrink and shmem_evict_inode 6c6f86bb618b mm/page_alloc.c: do not warn allocation failure on zone DMA if no managed pages e04b1dfe15ce dma/pool: create dma atomic pool only if dma zone has managed pages d2e572411738 mm_zone: add function to check if managed dma zone exists 2142a7e9bd1f PCI: Add function 1 DMA alias quirk for Marvell 88SE9125 SATA controller 45c74f4f54db dma_fence_array: Fix PENDING_ERROR leak in dma_fence_array_signaled() 191a24ceae75 gpu: host1x: Add back arm_iommu_detach_device() 068067453690 iommu/io-pgtable-arm-v7s: Add error handle for page table allocation failure 3dae11f8e381 lkdtm: Fix content of section containing lkdtm_rodata_do_nothing() e4a2c924a17e iio: adc: ti-adc081c: Partial revert of removal of ACPI IDs 256302cb2f86 can: softing_cs: softingcs_probe(): fix memleak on registration failure aa57725e2d2a media: cec-pin: fix interrupt en/disable handling 2e566cacc321 media: stk1160: fix control-message timeouts 1a0ca711dff6 media: pvrusb2: fix control-message timeouts 2dbf430ead59 media: redrat3: fix control-message timeouts 6e9c120bf956 media: dib0700: fix undefined behavior in tuner shutdown 5e98ac260de6 media: s2255: fix control-message timeouts 09b0b918a69b media: cpia2: fix control-message timeouts d90833106c09 media: em28xx: fix control-message timeouts 2182575c83f9 media: mceusb: fix control-message timeouts 460525acc953 media: flexcop-usb: fix control-message timeouts 7cac8a562427 media: v4l2-ioctl.c: readbuffers depends on V4L2_CAP_READWRITE 1da0b1cd4212 rtc: cmos: take rtc_lock while reading from CMOS 14f6cfe0d790 tools/nolibc: fix incorrect truncation of exit code 5e258640ba54 tools/nolibc: i386: fix initial stack alignment 06f7528d641b tools/nolibc: x86-64: Fix startup code bug 98259dd54e8e x86/gpu: Reserve stolen memory for first integrated Intel GPU e2a17dcad56e mtd: rawnand: davinci: Rewrite function description 8933138a6660 mtd: rawnand: davinci: Avoid duplicated page read 677764634b42 mtd: rawnand: davinci: Don't calculate ECC when reading page a8a607b0049d mtd: Fixed breaking list in __mtd_del_partition. ff10cd7bb295 mtd: rawnand: gpmi: Remove explicit default gpmi clock setting for i.MX6 538a5e208e7d mtd: rawnand: gpmi: Add ERR007117 protection for nfc_apply_timings 777a700ccfa6 nfc: llcp: fix NULL error pointer dereference on sendmsg() after failed bind() 08283b076f4e f2fs: fix to do sanity check in is_alive() 57cfc965e375 HID: wacom: Avoid using stale array indicies to read contact count 7fd22c99bbed HID: wacom: Ignore the confidence flag when a touch is removed 9a4800e0f6a5 HID: wacom: Reset expected and received contact counts at the same time c2e39d5df028 HID: uhid: Fix worker destroying device without any protection aa1346113c75 KVM: VMX: switch blocked_vcpu_on_cpu_lock to raw spinlock 0347b1658399 Merge 5.10.93 into android12-5.10-lts fd187a492557 Linux 5.10.93 bed97c903621 mtd: fixup CFI on ixp4xx f50803b519c3 powerpc/pseries: Get entry and uaccess flush required bits from H_GET_CPU_CHARACTERISTICS 68c1aa82be00 ALSA: hda/realtek: Re-order quirk entries for Lenovo 4d15a17d065d ALSA: hda/realtek: Add quirk for Legion Y9000X 2020 d7b41464f1b7 ALSA: hda: ALC287: Add Lenovo IdeaPad Slim 9i 14ITL5 speaker quirk 87246ae94b73 ALSA: hda/realtek - Fix silent output on Gigabyte X570 Aorus Master after reboot from Windows 9c27e513fb33 ALSA: hda/realtek: Add speaker fixup for some Yoga 15ITL5 devices 4c7fb4d519e5 KVM: x86: remove PMU FIXED_CTR3 from msrs_to_save_all 6b8c3a185377 firmware: qemu_fw_cfg: fix kobject leak in probe error path 889c73305b48 firmware: qemu_fw_cfg: fix NULL-pointer deref on duplicate entries ff9588cf1592 firmware: qemu_fw_cfg: fix sysfs information leak 358a4b054abe rtlwifi: rtl8192cu: Fix WARNING when calling local_irq_restore() with interrupts enabled 93c4506f9f8b media: uvcvideo: fix division by zero at stream start 4c3f70be6f3a video: vga16fb: Only probe for EGA and VGA 16 color graphic cards 161e43ab8cc1 9p: only copy valid iattrs in 9P2000.L setattr implementation 0e6c0f3f4055 KVM: s390: Clarify SIGP orders versus STOP/RESTART 413b427f5fff KVM: x86: Register Processor Trace interrupt hook iff PT enabled in guest 723acd75a062 perf: Protect perf_guest_cbs with RCU eadde287a62e vfs: fs_context: fix up param length parsing in legacy_parse_param c5f38277163e remoteproc: qcom: pil_info: Don't memcpy_toio more than is provided 5d88e24b23af orangefs: Fix the size of a memory allocation in orangefs_bufmap_alloc() 0084fefe2960 devtmpfs regression fix: reconfigure on each mount ee40594c95ae kbuild: Add $(KBUILD_HOSTLDFLAGS) to 'has_libelf' test f45f895af546 Merge branch 'android12-5.10' into `android12-5.10-lts` 7dd0d263fe9f Merge 5.10.92 into android12-5.10-lts c982c1a83932 Linux 5.10.92 c0091233f3d8 staging: greybus: fix stack size warning with UBSAN 66d21c005d9b drm/i915: Avoid bitwise vs logical OR warning in snb_wm_latency_quirk() 2d4fda471dc3 staging: wlan-ng: Avoid bitwise vs logical OR warning in hfa384x_usb_throttlefn() 3609fed7ac8b media: Revert "media: uvcvideo: Set unique vdev name based in type" 9b3c761e78d5 random: fix crash on multiple early calls to add_bootloader_randomness() 61cca7d191c7 random: fix data race on crng init time 3de9478230c3 random: fix data race on crng_node_pool 43c494294f30 can: gs_usb: gs_can_start_xmit(): zero-initialize hf->{flags,reserved} 45221a57b609 can: isotp: convert struct tpcon::{idx,len} to unsigned int bd61ae808b15 can: gs_usb: fix use of uninitialized variable, detach device on reception of invalid USB data f68e60001735 mfd: intel-lpss: Fix too early PM enablement in the ACPI ->probe() 5f76445a31b7 veth: Do not record rx queue hint in veth_xmit ddfa53825f3d mmc: sdhci-pci: Add PCI ID for Intel ADL 2e691f9894cc ath11k: Fix buffer overflow when scanning with extraie a87cecf94375 USB: Fix "slab-out-of-bounds Write" bug in usb_hcd_poll_rh_status 15982330b61d USB: core: Fix bug in resuming hub's handling of wakeup requests 413108ce3b56 ARM: dts: exynos: Fix BCM4330 Bluetooth reset polarity in I9100 b6dd07023699 Bluetooth: bfusb: fix division by zero in send path 869e1677a058 Bluetooth: btusb: Add support for Foxconn QCA 0xe0d0 c20021ce945f Bluetooth: btusb: Add support for Foxconn MT7922A 83493918380f Bluetooth: btusb: Add two more Bluetooth parts for WCN6855 294c0dd80d8a Bluetooth: btusb: fix memory leak in btusb_mtk_submit_wmt_recv_urb() 35ab8c9085b0 bpf: Fix out of bounds access from invalid *_or_null type verification c84fbba8a945 workqueue: Fix unbind_workers() VS wq_worker_running() race c39d68ab3836 md: revert io stats accounting d605f2f30d54 Merge 5.10.91 into android12-5.10-lts df395c763ba0 Linux 5.10.91 674071c9eb26 Input: zinitix - make sure the IRQ is allocated before it gets enabled ef81f7d406c2 ARM: dts: gpio-ranges property is now required f63fa1a0d4df ipv6: raw: check passed optlen before reading cf07884e6bec drm/amd/display: Added power down for DCN10 10b9ccd0674d mISDN: change function names to avoid conflicts dd8a09cfbb99 atlantic: Fix buff_ring OOB in aq_ring_rx_clean c2f4bb251eb4 net: udp: fix alignment problem in udp4_seq_show() f82b48d1d86b ip6_vti: initialize __ip6_tnl_parm struct in vti6_siocdevprivate 8c87a83ef891 scsi: libiscsi: Fix UAF in iscsi_conn_get_param()/iscsi_conn_teardown() b798b677f94d usb: mtu3: fix interval value for intr and isoc 498d77fc5e38 ipv6: Do cleanup if attribute validation fails in multipath route 72b0d14a0a88 ipv6: Continue processing multipath route even if gateway attribute is invalid 5a7d650bb181 power: bq25890: Enable continuous conversion for ADC at charging 4f260ea5537d phonet: refcount leak in pep_sock_accep 61952934608c rndis_host: support Hytera digital radios 62cbde77d9c1 power: reset: ltc2952: Fix use of floating point literals 998d157e3b2a power: supply: core: Break capacity loop 16d8568378f9 xfs: map unwritten blocks in XFS_IOC_{ALLOC,FREE}SP just like fallocate aa606b82cdfb net: ena: Fix error handling when calculating max IO queues number e7f5480978fd net: ena: Fix undefined state when tx request id is out of bounds 2de3d961f8e7 sch_qfq: prevent shift-out-of-bounds in qfq_init_qdisc 4c34d5fd8c96 batman-adv: mcast: don't send link-local multicast to mcast routers f403b5f96e9a lwtunnel: Validate RTA_ENCAP_TYPE attribute length 48d5adb08d60 ipv6: Check attribute length for RTA_GATEWAY when deleting multipath route 173bfa2782fa ipv6: Check attribute length for RTA_GATEWAY in multipath route 914420a2a6c5 ipv4: Check attribute length for RTA_FLOW in multipath route a8fe915be6c2 ipv4: Check attribute length for RTA_GATEWAY in multipath route 786a335fef18 ftrace/samples: Add missing prototypes direct functions c859c4de0bd7 i40e: Fix incorrect netdev's real number of RX/TX queues d0ad64438fb5 i40e: Fix for displaying message regarding NVM version 32845aa60203 i40e: fix use-after-free in i40e_sync_filters_subtask() f7edb6b9438b sfc: The RX page_ring is optional 2b3f34da0d79 mac80211: initialize variable have_higher_than_11mbit 16e5cad6eca1 RDMA/uverbs: Check for null return of kmalloc_array a7c2cae997db netrom: fix copying in user data in nr_setsockopt beeb0fdedae8 RDMA/core: Don't infoleak GRH fields 3ca132e6b065 iavf: Fix limit of total number of queues to active queues of VF 396e3016905d i40e: Fix to not show opcode msg on unsuccessful VF MAC change 7f13d14e563c ieee802154: atusb: fix uninit value in atusb_set_extended_addr 7db1e245cb71 tracing: Tag trace_percpu_buffer as a percpu pointer 760c6a625506 tracing: Fix check for trace_percpu_buffer validity in get_trace_buf() c1e2da4b3f72 selftests: x86: fix [-Wstringop-overread] warn in test_process_vm_readv() 384111e12367 f2fs: quota: fix potential deadlock a1bb21475ef8 Merge 5.10.90 into android12-5.10-lts d3e491a20d15 Linux 5.10.90 8c15bfb36a44 bpf: Add kconfig knob for disabling unpriv bpf by default d8a5b1377bf6 perf script: Fix CPU filtering of a script's switch events 2386e81a1d27 net: fix use-after-free in tw_timer_handler 34087cf96046 Input: spaceball - fix parsing of movement data packets 9f329d0d6c91 Input: appletouch - initialize work before device registration 2a4f551dec1a scsi: vmw_pvscsi: Set residual data length conditionally 1cb8444f3114 binder: fix async_free_space accounting for empty parcels a6e26251dd3a usb: mtu3: set interval of FS intr and isoc endpoint 3b6efe0b7ba0 usb: mtu3: fix list_head check warning f10b01c48f85 usb: mtu3: add memory barrier before set GPD's HWO 1c4ace3e6b85 usb: gadget: f_fs: Clear ffs_eventfd in ffs_data_clear. 1933fe8ce712 xhci: Fresco FL1100 controller should not have BROKEN_MSI quirk set. b8553330a077 drm/amdgpu: add support for IP discovery gc_info table v2 28863ffe21ff drm/amdgpu: When the VCN(1.0) block is suspended, powergating is explicitly enabled a0f3ac399ef5 uapi: fix linux/nfc.h userspace compilation errors 818c9e0a04df nfc: uapi: use kernel size_t to fix user-space builds 8d31cbab4c29 i2c: validate user data in compat ioctl 51c94d8fbd09 fsl/fman: Fix missing put_device() call in fman_port_probe 920932b20e0c net/ncsi: check for error return from call to nla_put_u32 610af55f9fbe selftests/net: udpgso_bench_tx: fix dst ip argument 78503589b1e0 net/mlx5e: Fix wrong features assignment in case of error 61146008087a ionic: Initialize the 'lif->dbid_inuse' bitmap b7c9a1427b32 igc: Fix TX timestamp support for non-MSI-X platforms e8a5988a85c7 net/smc: fix kernel panic caused by race of smc_sock 97c87c1db9ff net/smc: don't send CDC/LLC message if link not ready 99f19566b1c4 net/smc: improved fix wait on already cleared link e553265ea564 NFC: st21nfca: Fix memory leak in device probe and remove 8d70dc0eecf0 net: lantiq_xrx200: fix statistics of received bytes 7ef89bd1e8f1 net: ag71xx: Fix a potential double free in error handling paths 40d36186913b net: usb: pegasus: Do not drop long Ethernet frames a67becdaa8ad net/smc: fix using of uninitialized completions 769d14abd35e sctp: use call_rcu to free endpoint 13c1bf43b674 selftests: Calculate udpgso segment count without header adjustment abe74fb43378 udp: using datalen to cap ipv6 udp max gso segments 5e6ad649e927 net/mlx5e: Fix ICOSQ recovery flow for XSK 73665165b64a net/mlx5e: Wrap the tx reporter dump callback to extract the sq 4cd1da02f0c3 net/mlx5: DR, Fix NULL vs IS_ERR checking in dr_domain_init_resources fcb32eb3d04d scsi: lpfc: Terminate string in lpfc_debugfs_nvmeio_trc_write() 4833ad4908a1 selinux: initialize proto variable in selinux_ip_postroute_compat() ec941a2277a1 recordmcount.pl: fix typo in s390 mcount regex a0e82d5ef992 memblock: fix memblock_phys_alloc() section mismatch error 7da855e93964 platform/x86: apple-gmux: use resource_size() with res d01e9ce1af61 parisc: Clear stale IIR value on instruction access rights trap 0643d9175dc6 tomoyo: use hwight16() in tomoyo_domain_quota_is_ok() e2048a1f9186 tomoyo: Check exceeded quota early in tomoyo_domain_quota_is_ok(). 210c7c6908f3 Input: i8042 - enable deferred probe quirk for ASUS UM325UA bb672eff7447 Input: i8042 - add deferred probe support 9b28b48fb343 Merge 5.10.89 into android12-5.10-lts eb967e323f7f Linux 5.10.89 52ad5da8e316 phonet/pep: refuse to enable an unbound pipe 7dd52af1eb57 hamradio: improve the incomplete fix to avoid NPD 450121075a6a hamradio: defer ax25 kfree after unregister_netdev 8e34d07dd4d9 ax25: NPD bug when detaching AX25 device 50f78486f90b hwmon: (lm90) Do not report 'busy' status bit as alarm ec1d222d37ea hwmom: (lm90) Fix citical alarm status for MAX6680/MAX6681 441d3873664d pinctrl: mediatek: fix global-out-of-bounds issue 9c75a9657bdc ASoC: rt5682: fix the wrong jack type detected 94caab5af19a ASoC: tas2770: Fix setting of high sample rates c7282790c782 Input: goodix - add id->model mapping for the "9111" model 3bb3bf50d69f Input: elants_i2c - do not check Remark ID on eKTH3900/eKTH5312 ee6f34215c5d mm: mempolicy: fix THP allocations escaping mempolicy restrictions 8008fc1d0be1 KVM: VMX: Fix stale docs for kvm-intel.emulate_invalid_guest_state d91ed251fd70 usb: gadget: u_ether: fix race in setting MAC address in setup phase 6697f29bf56b ceph: fix up non-directory creation in SGID directories fffb6581a23a f2fs: fix to do sanity check on last xattr entry in __f2fs_setxattr() ad338d825e3f tee: optee: Fix incorrect page free bug 1f2070767401 mm/hwpoison: clear MF_COUNT_INCREASED before retrying get_any_page() ac61b9c6c054 mac80211: fix locking in ieee80211_start_ap error path 89876d10830d ARM: 9169/1: entry: fix Thumb2 bug in iWMMXt exception handling c3253d3a38bc mmc: mmci: stm32: clear DLYB_CR after sending tuning command 0d66b395210c mmc: core: Disable card detect during shutdown c8e366a01c20 mmc: meson-mx-sdhc: Set MANUAL_STOP for multi-block SDIO commands 4af79153617b mmc: sdhci-tegra: Fix switch to HS400ES mode 9a7ec7979785 gpio: dln2: Fix interrupts when replugging the device f5b02912e2dd pinctrl: stm32: consider the GPIO offset to expose all the GPIO lines 28626e76baf5 KVM: VMX: Wake vCPU when delivering posted IRQ even if vCPU == this vCPU 7a37f2e37069 platform/x86: intel_pmc_core: fix memleak on registration failure b57afd124046 x86/pkey: Fix undefined behaviour with PKRU_WD_BIT c05d8f66ec34 tee: handle lookup of shm with reference count 0 0ffb9f83e4f6 parisc: Fix mask used to select futex spinlock 5deeb9ad598b parisc: Correct completer in lws start 8b745616ba8f ipmi: fix initialization when workqueue allocation fails 1f6ab847461c ipmi: ssif: initialize ssif_info->client early a5192f31160c ipmi: bail out if init_srcu_struct fails bc674f1b2119 Input: atmel_mxt_ts - fix double free in mxt_read_info_block 30140e252fdb ASoC: meson: aiu: Move AIU_I2S_MISC hold setting to aiu-fifo-i2s 2b4c020b70cc ALSA: hda/realtek: Fix quirk for Clevo NJ51CU 7470780f3b0c ALSA: hda/realtek: Add new alc285-hp-amp-init model 4cb7dc2e3074 ALSA: hda/realtek: Amp init fixup for HP ZBook 15 G6 69e492161c7b ALSA: drivers: opl3: Fix incorrect use of vp->state a96c08e0b41e ALSA: jack: Check the return value of kstrdup() 51c7b2a7b86a hwmon: (lm90) Drop critical attribute support for MAX6654 2464738d0ee4 hwmon: (lm90) Introduce flag indicating extended temperature support 196df56c3dc8 hwmon: (lm90) Add basic support for TI TMP461 fa2e149260bf hwmon: (lm90) Fix usage of CONFIG2 register in detect function ba696b470839 pinctrl: bcm2835: Change init order for gpio hogs 676c572439e5 Input: elantech - fix stack out of bound access in elantech_change_report_id() 2792fde84cce sfc: falcon: Check null pointer of rx_queue->page_ring d70b4001ef74 sfc: Check null pointer of rx_queue->page_ring 75c962f02a4f net: ks8851: Check for error irq 9db0f8d395fd drivers: net: smc911x: Check for error irq ca2a15053b07 fjes: Check for error irq c6d2754006c1 bonding: fix ad_actor_system option setting to default 6809da518514 ipmi: Fix UAF when uninstall ipmi_si and ipmi_msghandler module 61e6b82e7b6c igb: fix deadlock caused by taking RTNL in RPM resume path e00eace2325c net: skip virtio_net_hdr_set_proto if protocol already set ed05e4dcfba6 net: accept UFOv6 packages in virtio_net_hdr_to_skb 56b0bbba782b qlcnic: potential dereference null pointer of rx_queue->page_ring 78e49d77e517 net: marvell: prestera: fix incorrect return of port_find 861b4413e41d ARM: dts: imx6qdl-wandboard: Fix Ethernet support d79f5e0d458b netfilter: fix regression in looped (broad|multi)cast's MAC handling 579cefef7c42 RDMA/hns: Replace kfree() with kvfree() 7cf6466e00a7 IB/qib: Fix memory leak in qib_user_sdma_queue_pkts() cd9c90682b2f ASoC: meson: aiu: fifo: Add missing dma_coerce_mask_and_coherent() 580ecf86e772 spi: change clk_disable_unprepare to clk_unprepare 93a957bbf46c arm64: dts: allwinner: orangepi-zero-plus: fix PHY mode ef2dce43257d HID: potential dereference of null pointer 3110bc5862d2 HID: holtek: fix mouse probing 0875873b2a97 ext4: check for inconsistent extents between index and leaf block 76366c024f56 ext4: check for out-of-order index extents in ext4_valid_extent_entries() 1d4b1c4e8bbd ext4: prevent partial update of the extent blocks f69a47fcbb9c net: usb: lan78xx: add Allied Telesis AT29M2-AF 8c0059a25cb1 arm64: vdso32: require CROSS_COMPILE_COMPAT for gcc+bfd b16b124a42e0 arm64: vdso32: drop -no-integrated-as flag ba13eb1927e1 Merge 5.10.88 into android12-5.10-lts 856f88f27bbc Linux 5.10.88 88f20cccbeec xen/netback: don't queue unlimited number of packages 525875c410df xen/netback: fix rx queue stall detection 8fa3a370cc2a xen/console: harden hvc_xen against event channel storms d31b3379179d xen/netfront: harden netfront against event channel storms 8ac3b6ee7c9f xen/blkfront: harden blkfront against event channel storms 76ec7fe2d866 Revert "xsk: Do not sleep in poll() when need_wakeup set" e24fc8983025 bus: ti-sysc: Fix variable set but not used warning for reinit_modules 70692b06208c rcu: Mark accesses to rcu_state.n_force_qs a9078e791426 scsi: scsi_debug: Sanity check block descriptor length in resp_mode_select() bdb854f134b9 scsi: scsi_debug: Fix type in min_t to avoid stack OOB aa1f912712a1 scsi: scsi_debug: Don't call kcalloc() if size arg is zero 6859985a2fbd ovl: fix warning in ovl_create_real() 5fd7d62daa24 fuse: annotate lock in fuse_reverse_inval_entry() b99bdf127af9 media: mxl111sf: change mutex_init() location 0413f7a1a533 xsk: Do not sleep in poll() when need_wakeup set 6b8d8ecdd980 ARM: dts: imx6ull-pinfunc: Fix CSI_DATA07__ESAI_TX0 pad name 8affa1b68db6 Input: touchscreen - avoid bitwise vs logical OR warning aec5897b277b drm/amdgpu: correct register access for RLC_JUMP_TABLE_RESTORE c1d519263ded libata: if T_LENGTH is zero, dma direction should be DMA_NONE a9f2c6af5a60 timekeeping: Really make sure wall_to_monotonic isn't positive 6471ebcd6f15 serial: 8250_fintek: Fix garbled text for console a7c80674538f iocost: Fix divide-by-zero on donation from low hweight cgroup bcebb8eb1948 zonefs: add MODULE_ALIAS_FS 1c414ff63b2d btrfs: fix double free of anon_dev after failure to create subvolume 005d9292b5b2 btrfs: fix memory leak in __add_inode_ref() cd98cb5216a0 USB: serial: option: add Telit FN990 compositions 5c93584d9a2f USB: serial: cp210x: fix CP2105 GPIO registration 8f207f12630b usb: xhci: Extend support for runtime power management for AMD's Yellow carp. e5949933f313 PCI/MSI: Mask MSI-X vectors only on success f8aa09186c30 PCI/MSI: Clear PCI_MSIX_FLAGS_MASKALL on error d17c5a389768 usb: dwc2: fix STM ID/VBUS detection startup delay in dwc2_driver_probe 2b2edc8fc5a8 USB: NO_LPM quirk Lenovo USB-C to Ethernet Adapher(RTL8153-04) fd623e16b2ff tty: n_hdlc: make n_hdlc_tty_wakeup() asynchronous 9439fabfc349 KVM: x86: Drop guest CPUID check for host initiated writes to MSR_IA32_PERF_CAPABILITIES 5fe305c6d485 Revert "usb: early: convert to readl_poll_timeout_atomic()" 2b54f485f2c1 USB: gadget: bRequestType is a bitfield, not a enum 151ffac3ac27 powerpc/85xx: Fix oops when CONFIG_FSL_PMC=n fcf9194d366c bpf, selftests: Fix racing issue in btf_skc_cls_ingress test 6f46c59e60b6 sit: do not call ipip6_dev_free() from sit_init_net() 6e1011cd183f net: systemport: Add global locking for descriptor lifecycle d1765f984c99 net/smc: Prevent smc_release() from long blocking 337bb7bf7c31 net: Fix double 0x prefix print in SKB dump 734a3f310605 sfc_ef100: potential dereference of null pointer 7da349f07e45 net/packet: rx_owner_map depends on pg_vec 1a34fb9e2bf3 netdevsim: Zero-initialize memory for new map's value in function nsim_bpf_map_alloc d3e1f54508f1 ixgbe: set X550 MDIO speed before talking to PHY 48e01e388182 ixgbe: Document how to enable NBASE-T support 776ed8b36697 igc: Fix typo in i225 LTR functions 74a16e062b23 igbvf: fix double free in `igbvf_probe` ddac50d04f34 igb: Fix removal of unicast MAC filters of VFs 12c1938870dc soc/tegra: fuse: Fix bitwise vs. logical OR warning 451f1eded7f5 mptcp: clear 'kern' flag from fallback sockets 222cebd995cd drm/amd/pm: fix a potential gpu_metrics_table memory leak 74dc97dfb276 rds: memory leak in __rds_conn_create() 67f4362ae286 flow_offload: return EOPNOTSUPP for the unsupported mpls action type 03fd6ca05601 mac80211: fix lookup when adding AddBA extension element bef59d6a83d3 mac80211: agg-tx: don't schedule_and_wake_txq() under sta->lock 96bc86cac0a9 drm/ast: potential dereference of null pointer cac0fd4b9bd3 selftest/net/forwarding: declare NETIFS p9 p10 81fbdd45652d net/sched: sch_ets: don't remove idle classes from the round-robin list be32c8a78887 dmaengine: st_fdma: fix MODULE_ALIAS dfff1d5e85ff selftests: Fix IPv6 address bind tests 08896ecfffc3 selftests: Fix raw socket bind tests with VRF 5ba4dfb8b8a1 selftests: Add duplicate config only for MD5 VRF tests 12512bc8f25b net: hns3: fix use-after-free bug in hclgevf_send_mbx_msg 3a4f6dba1eb9 inet_diag: fix kernel-infoleak for UDP sockets 20ad1ef02f9a sch_cake: do not call cake_destroy() from cake_init() 1208b445a497 s390/kexec_file: fix error handling when applying relocations c058c544e73a selftests: net: Correct ping6 expected rc from 2 to 1 9983425c203b virtio/vsock: fix the transport to work with VMADDR_CID_ANY 94a01e6fb2d8 soc: imx: Register SoC device only on i.MX boards cc426a91d384 clk: Don't parent clks until the parent is fully registered 429bb01e4dda ARM: socfpga: dts: fix qspi node compatible 7b4cc168d9ca ceph: initialize pathlen variable in reconnect_caps_cb e0f06c32afb2 ceph: fix duplicate increment of opened_inodes metric 640e28d618e8 tee: amdtee: fix an IS_ERR() vs NULL bug eed897a22230 mac80211: track only QoS data frames for admission control 24983f750881 arm64: dts: rockchip: fix audio-supply for Rock Pi 4 49bd597719bf arm64: dts: rockchip: fix rk3399-leez-p710 vcc3v3-lan supply 9fcdbbf3964d arm64: dts: rockchip: fix rk3308-roc-cc vcc-sd supply ba866840b240 arm64: dts: rockchip: remove mmc-hs400-enhanced-strobe from rk3399-khadas-edge 3516bc149223 arm64: dts: imx8mp-evk: Improve the Ethernet PHY description 06294e7e341a arm64: dts: imx8m: correct assigned clocks for FEC 4cc6badff97f audit: improve robustness of the audit queue handling 0e21e6cd5eeb dm btree remove: fix use after free in rebalance_children() f5187a9d52ae recordmcount.pl: look for jgnop instruction as well as bcrl on s390 51f6302f81d2 vdpa: check that offsets are within bounds e3a1ab5aea4c virtio_ring: Fix querying of maximum DMA mapping size for virtio device 0612679e48d0 bpf, selftests: Add test case trying to taint map value pointer 279e0bf80d95 bpf: Make 32->64 bounds propagation slightly more robust e2aad0b5f2cb bpf: Fix signed bounds propagation after mov32 f0f484714f35 firmware: arm_scpi: Fix string overflow in SCPI genpd driver 7fd214fc7f2e mac80211: validate extended element ID is present 0bb50470f1e0 mac80211: send ADDBA requests using the tid/queue of the aggregation session 29bb131dbbb5 mac80211: mark TX-during-stop for TX in in_reconfig 15640e40e3bb mac80211: fix regression in SSN handling of addba tx 49b7e496928e KVM: downgrade two BUG_ONs to WARN_ON_ONCE 8d0f56c2ed71 KVM: selftests: Make sure kvm_create_max_vcpus test won't hit RLIMIT_NOFILE c4d08791d941 Merge 5.10.87 into android12-5.10-lts 272aedd4a305 Linux 5.10.87 8dd559d53b3b arm: ioremap: don't abuse pfn_valid() to check if pfn is in RAM 65c578935bcc arm: extend pfn_valid to take into account freed memory map alignment 6e634c0e7155 memblock: ensure there is no overflow in memblock_overlaps_region() 74551f13c62f memblock: align freed memory map on pageblock boundaries with SPARSEMEM b4b54c7ba149 memblock: free_unused_memmap: use pageblock units instead of MAX_ORDER b6a1cbd187fc perf intel-pt: Fix error timestamp setting on the decoder error path 0612aa02c2c8 perf intel-pt: Fix missing 'instruction' events with 'q' option 71c795028b31 perf intel-pt: Fix next 'err' value, walking trace 02681dd1780a perf intel-pt: Fix state setting when receiving overflow (OVF) packet cbed09b44ce0 perf intel-pt: Fix intel_pt_fup_event() assumptions about setting state type 3bb7fd4be8c4 perf intel-pt: Fix sync state when a PSB (synchronization) packet is found 731ff7884138 perf intel-pt: Fix some PGE (packet generation enable/control flow packets) usage b23f9252a41d perf inject: Fix itrace space allowed for new attributes 7c26da3be1e9 ethtool: do not perform operations on net devices being unregistered 6992d8c215c8 hwmon: (dell-smm) Fix warning on /proc/i8k creation error c31470a30c0d fuse: make sure reclaim doesn't write the inode 613725436e69 bpf: Fix integer overflow in argument calculation for bpf_map_area_alloc 9099f3512678 staging: most: dim2: use device release method ac76adc87a78 KVM: x86: Ignore sparse banks size for an "all CPUs", non-sparse IPI req 6f0d9d3e74dc tracing: Fix a kmemleak false positive in tracing_map f35f7f04aa80 drm/amd/display: add connector type check for CRC source set dd3cea342522 drm/amd/display: Fix for the no Audio bug with Tiled Displays dadce61247c6 net: netlink: af_netlink: Prevent empty skb by adding a check on len. bca6af4325d6 i2c: rk3x: Handle a spurious start completion interrupt flag d6edec8a7b55 parisc/agp: Annotate parisc agp init functions with __init cf520ccffd9a ALSA: hda/hdmi: fix HDA codec entry table order for ADL-P 701a07fd0274 ALSA: hda: Add Intel DG2 PCI ID and HDMI codec vid 6d22a96d12d7 net/mlx4_en: Update reported link modes for 1/10G 999069d8b040 Revert "tty: serial: fsl_lpuart: drop earlycon entry for i.MX8QXP" 27f4ce02b31a s390/test_unwind: use raw opcode instead of invalid instruction 9eab949e2b90 KVM: arm64: Save PSTATE early on exit 990fd815ec88 drm/msm/dsi: set default num_data_lanes c602863ad28e nfc: fix segfault in nfc_genl_dump_devices_done 4f0b8b90b862 Merge 5.10.86 into android12-5.10-lts 37050f17f2d2 Linux 5.10.86 32414491834c netfilter: selftest: conntrack_vrf.sh: fix file permission afc997898ece Merge 5.10.85 into android12-5.10-lts e4f2aee6612e Linux 5.10.85 47301c06f602 Documentation/Kbuild: Remove references to gcc-plugin.sh af5ba49cf705 MAINTAINERS: adjust GCC PLUGINS after gcc-plugin.sh removal ad13421fd2cd doc: gcc-plugins: update gcc-plugins.rst 9fc17c3af56c kbuild: simplify GCC_PLUGINS enablement in dummy-tools/gcc d428e5477493 bpf: Add selftests to cover packet access corner cases 0ec0eda3f3c3 misc: fastrpc: fix improper packet size calculation 261d45a4c254 irqchip: nvic: Fix offset for Interrupt Priority Offsets cd946f0ebe78 irqchip/irq-gic-v3-its.c: Force synchronisation when issuing INVALL e1c6611f822e irqchip/armada-370-xp: Fix support for Multi-MSI interrupts 8f3ed9deaaac irqchip/armada-370-xp: Fix return value of armada_370_xp_msi_alloc() d530e9943d64 irqchip/aspeed-scu: Replace update_bits with write_bits. 014c2fa5dc49 csky: fix typo of fpu config macro ee86d0bad80b iio: accel: kxcjk-1013: Fix possible memory leak in probe and remove c10c53419d8d iio: ad7768-1: Call iio_trigger_notify_done() on error 0f86c9e818e7 iio: adc: axp20x_adc: fix charging current reporting on AXP22x af7fbb8c0b54 iio: adc: stm32: fix a current leak by resetting pcsel before disabling vdda fff92f3712d7 iio: at91-sama5d2: Fix incorrect sign extension a2545b147d23 iio: dln2: Check return value of devm_iio_trigger_register() 69ae78c1abe7 iio: dln2-adc: Fix lockdep complaint 416383999c66 iio: itg3200: Call iio_trigger_notify_done() on error bc4d8367ed0d iio: kxsd9: Don't return error code in trigger handler 28ea539a311e iio: ltr501: Don't return error code in trigger handler db12d9508536 iio: mma8452: Fix trigger reference couting 4e7852911084 iio: stk3310: Don't return error code in interrupt handler 5c4a0f307f2b iio: trigger: stm32-timer: fix MODULE_ALIAS 5de9c5b13062 iio: trigger: Fix reference counting cbc04c0c9a67 iio: gyro: adxrs290: fix data signedness fee8be5bde56 xhci: avoid race between disable slot command and host runtime suspend 1b43c9b65f6b usb: core: config: using bit mask instead of individual bits 74b6a6a239aa xhci: Remove CONFIG_USB_DEFAULT_PERSIST to prevent xHCI from runtime suspending ef284f086dd0 usb: core: config: fix validation of wMaxPacketValue entries e4de8ca013f0 USB: gadget: zero allocate endpoint 0 buffers 7193ad3e50e5 USB: gadget: detect too-big endpoint 0 requests 63fc70bffa16 selftests/fib_tests: Rework fib_rp_filter_test() 126d1897cbff net/qla3xxx: fix an error code in ql_adapter_up() 5e663bcd9a37 net, neigh: clear whole pneigh_entry at alloc time ae673832086e net: fec: only clear interrupt of handling queue in fec_enet_rx_queue() 83b16b9c441b net: altera: set a couple error code in probe() 385ffd31ebdb net: cdc_ncm: Allow for dwNtbOutMaxSize to be unset or zero 47322fddb41e tools build: Remove needless libpython-version feature check that breaks test-all fast path 42bea3a1b7f2 dt-bindings: net: Reintroduce PHY no lane swap binding 3f57215f748b Documentation/locking/locktypes: Update migrate_disable() bits. 77d255d28b34 perf tools: Fix SMT detection fast read path 391ca20ea16e Revert "PCI: aardvark: Fix support for PCI_ROM_ADDRESS1 on emulated bridge" e5b7fb2198ab i40e: Fix NULL pointer dereference in i40e_dbg_dump_desc 347cc9b4d966 mtd: rawnand: fsmc: Fix timing computation 0b2e1fccdf48 mtd: rawnand: fsmc: Take instruction delay into account 57f290572f45 i40e: Fix pre-set max number of queues for VF eb87117c27e7 i40e: Fix failed opcode appearing if handling messages from VF 82ed3829c937 clk: imx: use module_platform_driver 4d12546cf9e7 RDMA/hns: Do not destroy QP resources in the hw resetting phase 33f320c35d69 RDMA/hns: Do not halt commands during reset until later 4458938b297e ASoC: codecs: wcd934x: return correct value from mixer put 1089dac26c6b ASoC: codecs: wcd934x: handle channel mappping list correctly 83dae68fc00a ASoC: codecs: wsa881x: fix return values from kcontrol put 62e4dc5e130e ASoC: qdsp6: q6routing: Fix return value from msm_routing_put_audio_mixer 2f4764fe3692 ASoC: rt5682: Fix crash due to out of scope stack vars bdd8129c6605 PM: runtime: Fix pm_runtime_active() kerneldoc comment 661c4412c563 qede: validate non LSO skb length c4d2d7c935a4 scsi: scsi_debug: Fix buffer size of REPORT ZONES command 1e434d2687e8 scsi: pm80xx: Do not call scsi_remove_host() in pm8001_alloc() 5dfe61147442 block: fix ioprio_get(IOPRIO_WHO_PGRP) vs setuid(2) 5f1f94c26b0d tracefs: Set all files to the same group ownership as the mount option 2ba0738f7117 net: mvpp2: fix XDP rx queues registering 47ffefd88abf aio: fix use-after-free due to missing POLLFREE handling e4d19740bcca aio: keep poll requests on waitqueue until completed fc2f636ffc44 signalfd: use wake_up_pollfree() 9f3acee7eac8 binder: use wake_up_pollfree() 8e04c8397bf9 wait: add wake_up_pollfree() 2f8eb4c4c8f6 libata: add horkage for ASMedia 1092 f76580d82c62 can: m_can: Disable and ignore ELO interrupt 703dde112021 can: pch_can: pch_can_rx_normal: fix use after free 2737d0bc21b6 drm/syncobj: Deal with signalled fences in drm_syncobj_find_fence. 17edb38e76d6 clk: qcom: regmap-mux: fix parent clock lookup 172a98224418 mmc: renesas_sdhi: initialize variable properly when tuning 33204825cc2b tracefs: Have new files inherit the ownership of their parent c520943a00ad nfsd: Fix nsfd startup race (again) eeb0711801f5 nfsd: fix use-after-free due to delegation race 8b4264c27b82 md: fix update super 1.0 on rdev size change caf9b352dc58 btrfs: replace the BUG_ON in btrfs_del_root_ref with proper error handling 41b3cc57d626 btrfs: clear extent buffer uptodate when we fail to write it 75490bcbd076 scsi: qla2xxx: Format log strings only if needed 07977a3f3d55 ALSA: pcm: oss: Handle missing errors in snd_pcm_oss_change_params*() ad45babf7886 ALSA: pcm: oss: Limit the period size to 16MB 02b2b691b77c ALSA: pcm: oss: Fix negative period/buffer sizes 6760e6ddeb48 ALSA: hda/realtek: Fix quirk for TongFang PHxTxX1 7fe903d35492 ALSA: hda/realtek - Add headset Mic support for Lenovo ALC897 platform 3063ee5164e4 ALSA: ctl: Fix copy of updated id with element read/write c581090228e3 mm: bdi: initialize bdi_min_ratio when bdi is unregistered 06368922f38f KVM: x86: Wait for IPIs to be delivered when handling Hyper-V TLB flush hypercall 2a51edaf5cc5 net/sched: fq_pie: prevent dismantle issue 4b7e90672af8 devlink: fix netns refcount leak in devlink_nl_cmd_reload() 9d683d14f600 IB/hfi1: Correct guard on eager buffer deallocation 2e2edebb5dd6 iavf: Fix reporting when setting descriptor count aada0b3f3392 iavf: restore MSI state on reset 32a329b731a3 netfilter: conntrack: annotate data-races around ct->timeout 5e39de85b76e udp: using datalen to cap max gso segments 666521b3852d seg6: fix the iif in the IPv6 socket control block 484069b5de9d nfp: Fix memory leak in nfp_cpp_area_cache_add() b1830ede16f8 bonding: make tx_rebalance_counter an atomic a59df4ea7155 ice: ignore dropped packets during init 349e83c0cf67 bpf: Fix the off-by-two error in range markings f26951db84a4 bpf, x86: Fix "no previous prototype" warning 74685aaecef0 vrf: don't run conntrack on vrf with !dflt qdisc d5cf399a6dc3 selftests: netfilter: add a vrf+conntrack testcase 83ea620a1be8 nfc: fix potential NULL pointer deref in nfc_genl_dump_ses_done f3d9114ac99f drm/amdkfd: fix boot failure when iommu is disabled in Picasso. 7508a9aa65b9 drm/amdgpu: init iommu after amdkfd device init ac9db04ee32f drm/amdgpu: move iommu_resume before ip init/resume fe9dca7dda61 drm/amdgpu: add amdgpu_amdkfd_resume_iommu 5d191b0976b7 drm/amdkfd: separate kfd_iommu_resume from kfd_resume 46dcf66d6e7a drm/amd/amdkfd: adjust dummy functions' placement dded8d76a7dc x86/sme: Explicitly map new EFI memmap table as encrypted 923f4dc5df67 can: sja1000: fix use after free in ems_pcmcia_add_card() 819251da7178 can: kvaser_pciefd: kvaser_pciefd_rx_error_frame(): increase correct stats->{rx,tx}_errors counter 854a2bede1f0 can: kvaser_usb: get CAN clock frequency from device 2c08271f4ed0 IB/hfi1: Fix leak of rcvhdrtail_dummy_kvaddr d87c10607b5b IB/hfi1: Fix early init panic d60dd3685dc9 IB/hfi1: Insure use of smp_processor_id() is preempt disabled 05eb0e4a12b2 nft_set_pipapo: Fix bucket load in AVX2 lookup routine for six 8-bit groups 89f3edc98ffe HID: check for valid USB device for many HID drivers 889c39113f7e HID: wacom: fix problems when device is not a valid USB device 6272b17001e6 HID: bigbenff: prevent null pointer dereference d877651afd60 HID: add USB_HID dependancy on some USB HID drivers a7e9c5ddf562 HID: add USB_HID dependancy to hid-chicony 28989ed4d79e HID: add USB_HID dependancy to hid-prodikeys 61144329606c HID: add hid_is_usb() function to make it simpler for USB detection 2298d5edd837 HID: google: add eel USB id 12362cd3a409 HID: quirks: Add quirk for the Microsoft Surface 3 type-cover cc97d7321595 gcc-plugins: fix gcc 11 indigestion with plugins... 1eee36a5520b gcc-plugins: simplify GCC plugin-dev capability test 518c3f98e57a usb: gadget: uvc: fix multiple opens e2aed161fc26 ANDROID: GKI: fix up abi breakage in fib_rules.h 1b71a028a206 Merge 5.10.84 into android12-5.10-lts a0582e24d371 Linux 5.10.84 e6edaf267793 ipmi: msghandler: Make symbol 'remove_work_wq' static a8d18fb4d11b net/tls: Fix authentication failure in CCM mode dbe73dace94c parisc: Mark cr16 CPU clocksource unstable on all SMP machines 01300d21505d iwlwifi: mvm: retry init flow if failed a5d0a72b805e serial: 8250: Fix RTS modem control while in rs485 mode f9802d7049f5 serial: 8250_pci: rewrite pericom_do_set_divisor() 50b06889c86f serial: 8250_pci: Fix ACCES entries in pci_serial_quirks array e1722acf4f0d serial: core: fix transmit-buffer reset and memleak bda142bbeb31 serial: tegra: Change lower tolerance baud rate limit for tegra20 and tegra30 901f7e0aa4a6 serial: pl011: Add ACPI SBSA UART match id 946ded2287a0 tty: serial: msm_serial: Deactivate RX DMA for polling support 67d08450a08d x86/64/mm: Map all kernel memory into trampoline_pgd b3a519b5a580 x86/tsc: Disable clocksource watchdog for TSC on qualified platorms 1ed4a8fd363c x86/tsc: Add a timer to make sure TSC_adjust is always checked a92f044a9fcb usb: typec: tcpm: Wait in SNK_DEBOUNCED until disconnect 6d8c191bf464 USB: NO_LPM quirk Lenovo Powered USB-C Travel Hub 90c915051c3d xhci: Fix commad ring abort, write all 64 bits to CRCR register. 1235485c633e vgacon: Propagate console boot parameters before calling `vc_resize' 92b9113c6df0 parisc: Fix "make install" on newer debian releases c27a548d3f29 parisc: Fix KBUILD_IMAGE for self-extracting kernel 92f309c838fc x86/entry: Add a fence for kernel entry SWAPGS in paranoid_entry() 4bbbc9c4f313 x86/pv: Switch SWAPGS to ALTERNATIVE 4d42b7bcf09d sched/uclamp: Fix rq->uclamp_max not set on first enqueue 2015ffa3a4c2 x86/xen: Add xenpv_restore_regs_and_return_to_usermode() 8b9279cad291 x86/entry: Use the correct fence macro after swapgs in kernel CR3 c8e341191849 x86/sev: Fix SEV-ES INS/OUTS instructions for word, dword, and qword 64ca109bf875 KVM: VMX: Set failure code in prepare_vmcs02() 60ce9a754060 KVM: x86/pmu: Fix reserved bits for AMD PerfEvtSeln register cfebd5a277ad atlantic: Remove warn trace message. 95f6fae9a0db atlantic: Fix statistics logic for production hardware 695d9c6bc671 Remove Half duplex mode speed capabilities. 0c67e7b98fab atlantic: Add missing DIDs and fix 115c. ca350298bccb atlantic: Fix to display FW bundle version instead of FW mac version. 93a4f3f4fdb5 atlatnic: enable Nbase-t speeds with base-t 44812111a3b1 atlantic: Increase delay for fw transactions 13f290d5aa4a drm/msm: Do hw_init() before capturing GPU state d646856a600e drm/msm/a6xx: Allocate enough space for GMU registers a792b3d56438 net/smc: Keep smc_close_final rc during active close e226180acc49 net/rds: correct socket tunable error in rds_tcp_tune() 77731fede297 net/smc: fix wrong list_del in smc_lgr_cleanup_early 9a40a1e0eb50 ipv4: convert fib_num_tclassid_users to atomic_t fa973bf5fd0f net: annotate data-races on txq->xmit_lock_owner e26dab79e16b dpaa2-eth: destroy workqueue at the end of remove function dde240695d97 net: marvell: mvpp2: Fix the computation of shared CPUs 3260b8d12057 net: usb: lan78xx: lan78xx_phy_init(): use PHY_POLL instead of "0" if no IRQ is available acef1c2b1596 ALSA: intel-dsp-config: add quirk for CML devices based on ES8336 codec 60f0b9c42cb8 rxrpc: Fix rxrpc_local leak in rxrpc_lookup_peer() 35b40f724c4e rxrpc: Fix rxrpc_peer leak in rxrpc_look_up_bundle() 4afb32090a15 ASoC: tegra: Fix kcontrol put callback in AHUB fe4eb5297ac3 ASoC: tegra: Fix kcontrol put callback in DSPK 256aa15aac6d ASoC: tegra: Fix kcontrol put callback in DMIC 1cf1f9a1f3ed ASoC: tegra: Fix kcontrol put callback in I2S 0ee53a1d8889 ASoC: tegra: Fix kcontrol put callback in ADMAIF e6fb4c3fd35b ASoC: tegra: Fix wrong value type in DSPK 0265ef0dff5e ASoC: tegra: Fix wrong value type in DMIC e66e75fb2278 ASoC: tegra: Fix wrong value type in I2S 6b54c0d845e5 ASoC: tegra: Fix wrong value type in ADMAIF 932b338f4e5c mt76: mt7915: fix NULL pointer dereference in mt7915_get_phy_mode a0335cda6d92 selftests: net: Correct case name f1d43efa59f1 net/mlx4_en: Fix an use-after-free bug in mlx4_en_try_alloc_resources() 59d2dc771006 arm64: ftrace: add missing BTIs ef55f0f8af2b siphash: use _unaligned version by default fd52e1f8c093 net: mpls: Fix notifications when deleting a device 15fa12c119f8 net: qlogic: qlcnic: Fix a NULL pointer dereference in qlcnic_83xx_add_rings() c6f340a331fb tcp: fix page frag corruption on page fault aa6c393a3c3f natsemi: xtensa: fix section mismatch warnings 289ee320b5ed i2c: cbus-gpio: set atomic transfer callback 58d5c53f2589 i2c: stm32f7: stop dma transfer in case of NACK c22124491752 i2c: stm32f7: recover the bus on access timeout 8de6ea757c88 i2c: stm32f7: flush TX FIFO upon transfer errors 1c75779dd90c wireguard: ratelimiter: use kvcalloc() instead of kvzalloc() cb2d7c1992cb wireguard: receive: drop handshakes if queue lock is contended 8a29a50dbdb1 wireguard: receive: use ring buffer for incoming handshakes e3be118327a1 wireguard: device: reset peer src endpoint when netns exits f7b6672fab70 wireguard: selftests: rename DEBUG_PI_LIST to DEBUG_PLIST 0584bf51c315 wireguard: selftests: actually test for routing loops 3d1dc3c67773 wireguard: allowedips: add missing __rcu annotation to satisfy sparse 4caf965f6cbe wireguard: selftests: increase default dmesg log size 3d73021f8d74 tracing/histograms: String compares should not care about signed values d4af6d974951 KVM: X86: Use vcpu->arch.walk_mmu for kvm_mmu_invlpg() c71b5f37b5ff KVM: arm64: Avoid setting the upper 32 bits of TCR_EL2 and CPTR_EL2 to 1 5f33887a3682 KVM: x86: Use a stable condition around all VT-d PI paths 7722e8850522 KVM: nVMX: Flush current VPID (L1 vs. L2) for KVM_REQ_TLB_FLUSH_GUEST 6a44f200f1f1 KVM: Disallow user memslot with size that exceeds "unsigned long" 775191dd4c1b drm/amd/display: Allow DSC on supported MST branch devices 209d35ee34e2 ipv6: fix memory leak in fib6_rule_suppress 16c242b09106 sata_fsl: fix warning in remove_proc_entry when rmmod sata_fsl 4a46b2f5dce0 sata_fsl: fix UAF in sata_fsl_port_stop when rmmod sata_fsl 4baba6ba56eb fget: check that the fd still exists after getting a ref to it 80bfed369be9 s390/pci: move pseudo-MMIO to prevent MIO overlap 92283c2728a9 cpufreq: Fix get_cpu_device() failure in add_cpu_dev_symlink() f717f29e8468 ipmi: Move remove_work to dedicated workqueue de4f5eb02cfe rt2x00: do not mark device gone on EPROTO errors during start c200721f8eda kprobes: Limit max data_size of the kretprobe instances 2a74c13dfe83 vrf: Reset IPCB/IP6CB when processing outbound pkts in vrf dev xmit 136cabf15779 ACPI: Add stubs for wakeup handler functions cc443ac5bb31 net/smc: Avoid warning of possible recursive locking ff061b5bda73 perf report: Fix memory leaks around perf_tip() a4c17ebdd624 perf hist: Fix memory leak of a perf_hpp_fmt d9b72274f32a perf inject: Fix ARM SPE handling 2c15d2a6ba27 net: ethernet: dec: tulip: de4x5: fix possible array overflows in type3_infoblock() f059fa40f0fc net: tulip: de4x5: fix the problem that the array 'lp->phy[8]' may be out of bound 4d5968ea06fb ipv6: check return value of ipv6_skip_exthdr 22519eff7df2 ethernet: hisilicon: hns: hns_dsaf_misc: fix a possible array overflow in hns_dsaf_ge_srst_by_port() 9a32d3c08d8e ata: ahci: Add Green Sardine vendor ID as board_ahci_mobile c746945fb6bc drm/amd/amdgpu: fix potential memleak 74aafe99efb6 drm/amd/amdkfd: Fix kernel panic when reset failed and been triggered again f0c9f49b0caf scsi: iscsi: Unblock session then wake up error handler bc8c423a286a thermal: core: Reset previous low and high trip during thermal zone init 8e4d2ac4348a btrfs: check-integrity: fix a warning on write caching disabled disk 039572290531 s390/setup: avoid using memblock_enforce_memory_limit fd1e70ef65ee platform/x86: thinkpad_acpi: Fix WWAN device disabled issue after S3 deep 226b21ad01ae platform/x86: thinkpad_acpi: Add support for dual fan control 3fc88660ede6 net: return correct error code 2c514d25003a atlantic: Fix OOB read and write in hw_atl_utils_fw_rpc_wait ff6eeb627898 net/smc: Transfer remaining wait queue entries during fallback e1a165599aad mac80211: do not access the IV when it was stripped c386d7aa59f5 drm/sun4i: fix unmet dependency on RESET_CONTROLLER for PHY_SUN6I_MIPI_DPHY 57e36973fadb powerpc/pseries/ddw: Revert "Extend upper limit for huge DMA window for persistent memory" 7b2b7e03e8ea gfs2: Fix length of holes reported at end-of-file 664cceab6f70 gfs2: release iopen glock early in evict bcce010f9230 ovl: fix deadlock in splice write dca4f9a58196 ovl: simplify file splice 7774dd934a65 can: j1939: j1939_tp_cmd_recv(): check the dst address of TP.CM_BAM 60ae63ef194a NFSv42: Fix pagecache invalidation after COPY/CLONE 6e6898e23cab ANDROID: GKI: update abi_gki_aarch64.xml due to bpf changes in 5.10.83 cd1062d64ea1 Revert "net: ipv6: add fib6_nh_release_dsts stub" 0bf59ac0b200 Revert "net: nexthop: release IPv6 per-cpu dsts when replacing a nexthop group" 65836a68d96d Revert "mmc: sdhci: Fix ADMA for PAGE_SIZE >= 64KiB" 249dae115ad0 Merge 5.10.83 into android-5.10 bc8ae0e2afaf Merge branch 'android12-5.10' into `android12-5.10-lts` a324ad794566 Linux 5.10.83 45b42cd05391 drm/amdgpu/gfx9: switch to golden tsc registers for renoir+ 98b02755d544 net: stmmac: platform: fix build warning when with !CONFIG_PM_SLEEP a15261d2a121 shm: extend forced shm destroy to support objects from several IPC nses aa20e966d8a1 s390/mm: validate VMA in PGSTE manipulation functions a94e4a7b77ed tty: hvc: replace BUG_ON() with negative return value 1c5f722a8fdf xen/netfront: don't trust the backend response data blindly 334b0f278761 xen/netfront: disentangle tx_skb_freelist e17ee047eea7 xen/netfront: don't read data from request on the ring page f5e493709800 xen/netfront: read response from backend only once 1ffb20f0527d xen/blkfront: don't trust the backend response data blindly 8e147855fcf2 xen/blkfront: don't take local copy of a request from the ring page 273f04d5d135 xen/blkfront: read response from backend only once b98284aa3fc5 xen: sync include/xen/interface/io/ring.h with Xen's newest version 406f2d5fe368 tracing: Check pid filtering when creating events 4fd0ad08ee33 vhost/vsock: fix incorrect used length reported to the guest fbc0514e1a34 iommu/amd: Clarify AMD IOMMUv2 initialization messages 5655b8bccb8a smb3: do not error on fsync when readonly c380062d0850 ceph: properly handle statfs on multifs setups 22423c966e02 f2fs: set SBI_NEED_FSCK flag when inconsistent node block found e6ee7abd6bfe sched/scs: Reset task stack state in bringup_cpu() 71e38a0c7cf8 tcp: correctly handle increased zerocopy args struct size 72f2117e450b net: mscc: ocelot: correctly report the timestamping RX filters in ethtool 73115a2b38dd net: mscc: ocelot: don't downgrade timestamping RX filters in SIOCSHWTSTAMP 62343dadbb96 net: hns3: fix VF RSS failed problem after PF enable multi-TCs 215167df4512 net/smc: Don't call clcsock shutdown twice when smc shutdown 6e800ee43218 net: vlan: fix underflow for the real_dev refcnt ae2659d2c670 net/sched: sch_ets: don't peek at classes beyond 'nbands' e3509feb46fa tls: fix replacing proto_ops 22156242b104 tls: splice_read: fix record type check 3b6c71c097da MIPS: use 3-level pgtable for 64KB page size on MIPS_VA_BITS_48 a6a5d853f1e6 MIPS: loongson64: fix FTLB configuration 5e823dbee23c igb: fix netpoll exit with traffic f2a58ff3e3ad nvmet: use IOCB_NOWAIT only if the filesystem supports it 12ceb52f2cc4 net/smc: Fix loop in smc_listen c94cbd262b6a net/smc: Fix NULL pointer dereferencing in smc_vlan_by_tcpsk() 3d4937c6a328 net: phylink: Force retrigger in case of latched link-fail indicator 50162ff3c80f net: phylink: Force link down and retrigger resolve on interface change 95ba8f0d57ce lan743x: fix deadlock in lan743x_phy_link_status_change() c5e4316d9c02 tcp_cubic: fix spurious Hystart ACK train detections for not-cwnd-limited flows 318762309609 drm/amd/display: Set plane update flags for all planes in reset f634c755a0ee PM: hibernate: use correct mode for swsusp_close() 440bd9faad29 net/ncsi : Add payload to be 32-bit aligned to fix dropped packets ac88cb3c44b6 nvmet-tcp: fix incomplete data digest send 8889ff80fde3 net: marvell: mvpp2: increase MTU limit when XDP enabled 90d0736876c5 mlxsw: spectrum: Protect driver from buggy firmware 33d89128a960 mlxsw: Verify the accessed index doesn't exceed the array length 29e1b5734795 net/smc: Ensure the active closing peer first closes clcsock 77d9c2efa870 erofs: fix deadlock when shrink erofs slab 9f540c7ffb1e scsi: scsi_debug: Zero clear zones at reset write pointer 725ba1289508 scsi: core: sysfs: Fix setting device state to SDEV_RUNNING e65a8707b4cd ice: avoid bpf_prog refcount underflow 1eb5395add78 ice: fix vsi->txq_map sizing 26ed13d06422 net: nexthop: release IPv6 per-cpu dsts when replacing a nexthop group 3c40584595f8 net: ipv6: add fib6_nh_release_dsts stub dc2f7e9d8d20 net: stmmac: retain PTP clock time during SIOCSHWTSTAMP ioctls 79068e6b1cfb net: stmmac: fix system hang caused by eee_ctrl_timer during suspend/resume cc301ad31207 nfp: checking parameter process for rx-usecs/tx-usecs is invalid 9b44cb67d387 ipv6: fix typos in __ip6_finish_output() 6d9e8dabd46f firmware: smccc: Fix check for ARCH_SOC_ID not implemented bbd1683e795c mptcp: fix delack timer 061542815af1 ALSA: intel-dsp-config: add quirk for JSL devices based on ES8336 codec f5af2def7e05 iavf: Prevent changing static ITR values if adaptive moderation is on 5dca8eff4627 net: marvell: prestera: fix double free issue on err path b33c5c828144 drm/vc4: fix error code in vc4_create_object() 2bf9c5a5039c scsi: mpt3sas: Fix kernel panic during drive powercycle test 29ecb4c0f0d7 drm/nouveau/acr: fix a couple NULL vs IS_ERR() checks 0effb7f51b65 ARM: socfpga: Fix crash with CONFIG_FORTIRY_SOURCE 86c5adc78083 NFSv42: Don't fail clone() unless the OP_CLONE operation failed c9ba7864d3a2 firmware: arm_scmi: pm: Propagate return value to caller 8730a679c3cb net: ieee802154: handle iftypes as u32 2925aadd1f32 ASoC: codecs: wcd934x: return error code correctly from hw_params 3a25def06de8 ASoC: topology: Add missing rwsem around snd_ctl_remove() calls 4a4f900e0415 ASoC: qdsp6: q6asm: fix q6asm_dai_prepare error handling 9196a6858150 ASoC: qdsp6: q6routing: Conditionally reset FrontEnd Mixer 2be17eca48ae ARM: dts: bcm2711: Fix PCIe interrupts 9db1d4a3c270 ARM: dts: BCM5301X: Add interrupt properties to GPIO node b2cd6fdcbe0a ARM: dts: BCM5301X: Fix I2C controller interrupt b7ef25e8c271 netfilter: flowtable: fix IPv6 tunnel addr match d689176e0e18 netfilter: ipvs: Fix reuse connection if RS weight is 0 994065f6efdc netfilter: ctnetlink: do not erase error code with EINVAL a3d829e5f375 netfilter: ctnetlink: fix filtering with CTA_TUPLE_REPLY a8a917058faf proc/vmcore: fix clearing user buffer by properly using clear_user() 1f520a0d78fc PCI: aardvark: Fix link training aec0751f61f5 PCI: aardvark: Simplify initialization of rootcap on virtual bridge df5748098878 PCI: aardvark: Implement re-issuing config requests on CRS response e7f2e2c758ea PCI: aardvark: Update comment about disabling link training 2b7bc1c4b2c8 PCI: aardvark: Deduplicate code in advk_pcie_rd_conf() dfe906da9a1a powerpc/32: Fix hardlockup on vmap stack overflow bf00edd9e6c9 mdio: aspeed: Fix "Link is Down" issue 14c3ce30ddbd mmc: sdhci: Fix ADMA for PAGE_SIZE >= 64KiB 63195705b334 mmc: sdhci-esdhc-imx: disable CMDQ support 092a58f0d9ef tracing: Fix pid filtering when triggers are attached 68fa6bf7f179 tracing/uprobe: Fix uprobe_perf_open probes iteration b777c866aafc KVM: PPC: Book3S HV: Prevent POWER7/8 TLB flush flushing SLB bfed9c2f2f2e xen: detect uninitialized xenbus in xenbus_init e1d492c27519 xen: don't continue xenstore initialization in case of errors 8f4d0719f323 fuse: release pipe buf after last use 8d0163cec7de staging: rtl8192e: Fix use after free in _rtl92e_pci_disconnect() 0bfed81b2ccd staging: greybus: Add missing rwsem around snd_ctl_remove() calls 146283f16b7e staging/fbtft: Fix backlight 8fc5e3c7cacc HID: wacom: Use "Confidence" flag to prevent reporting invalid contacts 6ca32e2e776e Revert "parisc: Fix backtrace to always include init funtion names" 3a4aeb37a7a6 media: cec: copy sequence field for the reply 3798218a1af4 ALSA: hda/realtek: Fix LED on HP ProBook 435 G7 60274e248e3d ALSA: hda/realtek: Add quirk for ASRock NUC Box 1100 172167bc8dac ALSA: ctxfi: Fix out-of-range access 4402cf040252 binder: fix test regression due to sender_euid change aea184ae6408 usb: hub: Fix locking issues with address0_mutex 5bf3a0c7789e usb: hub: Fix usb enumeration issue due to address0 race 00f1038c72f8 usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts 56fbab4937e0 usb: chipidea: ci_hdrc_imx: fix potential error pointer dereference in probe b70ff391deee net: nexthop: fix null pointer dereference when IPv6 is not enabled 0755f3f32277 usb: dwc3: gadget: Fix null pointer exception 140e2df472ba usb: dwc3: gadget: Check for L1/L2/U3 for Start Transfer 3abf746e800b usb: dwc3: gadget: Ignore NoStream after End Transfer 2b7ab82f5173 usb: dwc2: hcd_queue: Fix use of floating point literal 4b18ccad9671 usb: dwc2: gadget: Fix ISOC flow for elapsed frames 16f1cac8f702 USB: serial: option: add Fibocom FM101-GL variants ff721286369e USB: serial: option: add Telit LE910S1 0x9200 composition 854c14b2a15c ACPI: Get acpi_device's parent from the parent field 33fe044f6a9e bpf: Fix toctou on read-only map's constant scalar tracking 8d21bcc704ea Merge 5.10.82 into android12-5.10-lts d5259a9ba699 Linux 5.10.82 d35250ec5a23 Revert "perf: Rework perf_event_exit_event()" 6718f79c40fd ALSA: hda: hdac_stream: fix potential locking issue in snd_hdac_stream_assign() f751fb54f2bc ALSA: hda: hdac_ext_stream: fix potential locking issues b3ef5051a758 x86/Kconfig: Fix an unused variable error in dell-smm-hwmon 2ec78af152e9 btrfs: update device path inode time instead of bd_inode 9febc9d8d2b4 fs: export an inode_update_time helper cade5d7a2803 ice: Delete always true check of PF pointer fe65cecd2758 usb: max-3421: Use driver data instead of maintaining a list of bound devices 6186c7b9bdfc ASoC: DAPM: Cover regression by kctl change notification fix b17dd53cac76 selinux: fix NULL-pointer dereference when hashtab allocation fails 1ae0d59c4f5e RDMA/netlink: Add __maybe_unused to static inline in C file 40bc831ab5f6 hugetlbfs: flush TLBs correctly after huge_pmd_unshare 86ab0f8ff008 scsi: ufs: core: Fix task management completion timeout race ddd4e46cff40 scsi: ufs: core: Fix task management completion 04c586a601dc drm/amdgpu: fix set scaling mode Full/Full aspect/Center not works on vga and dvi connectors 47901b77bf7d drm/i915/dp: Ensure sink rate values are always valid 82de15ca6b55 drm/nouveau: clean up all clients on device removal c81c90fbf577 drm/nouveau: use drm_dev_unplug() during device removal 9221aff33edb drm/nouveau: Add a dedicated mutex for the clients list 65517975cb19 drm/udl: fix control-message timeout 3d68d6ee8314 drm/amd/display: Update swizzle mode enums 7b97b5776daa cfg80211: call cfg80211_stop_ap when switch from P2P_GO type 1ab297809de8 parisc/sticon: fix reverse colors 6adbc07ebcaf btrfs: fix memory ordering between normal and ordered work functions 6289b494b38e net: stmmac: socfpga: add runtime suspend/resume callback for stratix10 platform 5875f87e2fc9 udf: Fix crash after seekdir 6b43cf113a38 KVM: nVMX: don't use vcpu->arch.efer when checking host state on nested state load cc73242889b5 block: Check ADMIN before NICE for IOPRIO_CLASS_RT 63e2f34abc22 s390/kexec: fix memory leak of ipl report buffer b1cf0d2fc4e4 scsi: qla2xxx: Fix mailbox direction flags in qla2xxx_get_adapter_id() 08fd6df8eaaf powerpc/8xx: Fix pinned TLBs with CONFIG_STRICT_KERNEL_RWX 9c177eee116c x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails b2e2fb64071a mm: kmemleak: slob: respect SLAB_NOLEAKTRACE flag 99032adf7d4b ipc: WARN if trying to remove ipc object which is absent a7d91625863d tipc: check for null after calling kmemdup f5995fcb75eb hexagon: clean up timer-regs.h 0854c9ff2151 hexagon: export raw I/O routines for modules 528971af64fc tun: fix bonding active backup with arp monitoring af1d3c437eb5 arm64: vdso32: suppress error message for 'make mrproper' 97653ba562b9 net: stmmac: dwmac-rk: Fix ethernet on rk3399 based devices 4cebe23c032b s390/kexec: fix return code handling d4fb80ae9830 perf/x86/intel/uncore: Fix IIO event constraints for Skylake Server 175135a5eacf perf/x86/intel/uncore: Fix filter_tid mask for CHA events on Skylake Server 84f64c7c52d6 pinctrl: qcom: sdm845: Enable dual edge errata a8230fb74b54 KVM: PPC: Book3S HV: Use GLOBAL_TOC for kvmppc_h_set_dabr/xdabr() 4e6cce20fbc0 e100: fix device suspend/resume 34e54703fb0f NFC: add NCI_UNREG flag to eliminate the race b2a60b4a0195 net: nfc: nci: Change the NCI close sequence 73a0d12114b4 NFC: reorder the logic in nfc_{un,}register_device cb14b196d991 NFC: reorganize the functions in nci_request 41dc8dcb49d5 i40e: Fix display error code in dmesg 028ea7b090ec i40e: Fix creation of first queue by omitting it if is not power of two 69868d7a8853 i40e: Fix warning message and call stack during rmmod i40e driver 20645482d159 i40e: Fix ping is lost after configuring ADq on VF 6d64743045ca i40e: Fix changing previously set num_queue_pairs for PFs f866513ead43 i40e: Fix NULL ptr dereference on VSI filter sync 071948856587 i40e: Fix correct max_pkt_size on VF RX queue 8e6bae950da9 net: virtio_net_hdr_to_skb: count transport header in UFO 1c4099dc0d6a net: dpaa2-eth: fix use-after-free in dpaa2_eth_remove 381a30f7e31c net: sched: act_mirred: drop dst for the direction from egress to ingress a792e0128d23 scsi: core: sysfs: Fix hang when device state is set via sysfs 4b4302a02b7f net/mlx5: E-Switch, return error if encap isn't supported 68748ea4d122 net/mlx5: E-Switch, Change mode lock from mutex to rw semaphore 6190e1a2d41a net/mlx5: Lag, update tracker when state change event received 471c49289055 net/mlx5e: nullify cq->dbg pointer in mlx5_debug_cq_remove() d1f8f1e04a61 platform/x86: hp_accel: Fix an error handling path in 'lis3lv02d_probe()' da16f907cb30 mips: lantiq: add support for clk_get_parent() 17dfbe1b2f4e mips: bcm63xx: add support for clk_get_parent() 34284b3a2f86 MIPS: generic/yamon-dt: fix uninitialized variable error a61f90b2162d iavf: Fix for setting queues to 0 a8a1e601c2ea iavf: Fix for the false positive ASQ/ARQ errors while issuing VF reset 77f5ae5441f0 iavf: validate pointers ddcc185baa2b iavf: prevent accidental free of filter structure a420b2612825 iavf: Fix failure to exit out from last all-multicast mode 78638b471322 iavf: free q_vectors before queues in iavf_disable_vf 84a13bfe2714 iavf: check for null in iavf_fix_features 1555d83ddbb7 iavf: Fix return of set the new channel count 09decd0a102a net/smc: Make sure the link_id is unique 437e21e2c9ae sock: fix /proc/net/sockstat underflow in sk_clone_lock() 4da14ddad19f net: reduce indentation level in sk_clone_lock() 9c3c2ef6ca26 tipc: only accept encrypted MSG_CRYPTO msgs 3d5941664786 bnxt_en: reject indirect blk offload when hw-tc-offload is off 4fc060abaa26 net: bnx2x: fix variable dereferenced before check 3ae75cc38a84 net: ipa: disable HOLB drop when updating timer 3984876f91a3 tracing: Add length protection to histogram string copies 900ea2f6287f tcp: Fix uninitialized access in skb frags array for Rx 0cp. d1a6150ca616 net-zerocopy: Refactor skb frag fast-forward op. 5f7aadf03f98 net-zerocopy: Copy straggler unaligned data for TCP Rx. zerocopy. 8da80ec6d4f7 drm/nouveau: hdmigv100.c: fix corrupted HDMI Vendor InfoFrame aa31e3fda68f perf tests: Remove bash construct from record+zstd_comp_decomp.sh 2ada5c0877f4 perf bench futex: Fix memory leak of perf_cpu_map__new() 11589d3144bc perf bpf: Avoid memory leak from perf_env__insert_btf() 5b2f2cbbc925 tracing/histogram: Do not copy the fixed-size char array field over the field size 1d6125532755 blkcg: Remove extra blkcg_bio_issue_init dadcc935f440 perf/x86/vlbr: Add c->flags to vlbr event constraints 68fcb52b610c sched/core: Mitigate race cpus_share_cache()/update_top_cache_domain() 91191d47af55 mips: BCM63XX: ensure that CPU_SUPPORTS_32BIT_KERNEL is set fbe27d0e1dcf clk: qcom: gcc-msm8996: Drop (again) gcc_aggre1_pnoc_ahb_clk 9b3d3b72be84 clk/ast2600: Fix soc revision for AHB 03bc8ea0ae95 clk: ingenic: Fix bugs with divided dividers 7a5439474e69 f2fs: fix incorrect return value in f2fs_sanity_check_ckpt() 0a17fff6f045 f2fs: compress: disallow disabling compress on non-empty compressed file 4ce685cc9a0b sh: define __BIG_ENDIAN for math-emu 73383f670d8f sh: math-emu: drop unused functions f44defd5694b sh: fix kconfig unmet dependency warning for FRAME_POINTER 3d7c5d08a483 f2fs: fix to use WHINT_MODE e8bd5e33057c f2fs: fix up f2fs_lookup tracepoints 5d5bf899e57a maple: fix wrong return value of maple_bus_init(). 8748f08a2fc0 sh: check return code of request_irq 29b742690a09 powerpc/8xx: Fix Oops with STRICT_KERNEL_RWX without DEBUG_RODATA_TEST bc4bc07fb44c powerpc/dcr: Use cmplwi instead of 3-argument cmpli 1ac6cd87d8dd ALSA: gus: fix null pointer dereference on pointer block 850416beadef ARM: dts: qcom: fix memory and mdio nodes naming for RB3011 8c4d9764e74d powerpc/5200: dts: fix memory node unit name 833ad2792733 iio: imu: st_lsm6dsx: Avoid potential array overflow in st_lsm6dsx_set_odr() e0fef1c8cd61 scsi: target: Fix alua_tg_pt_gps_count tracking 8176441373dd scsi: target: Fix ordered tag handling 8440377e1a56 scsi: scsi_debug: Fix out-of-bound read in resp_report_tgtpgs() 3e20cb072679 scsi: scsi_debug: Fix out-of-bound read in resp_readcap16() 9635581aa999 MIPS: sni: Fix the build 77e9fed33056 tty: tty_buffer: Fix the softlockup issue in flush_to_ldisc da82a207c4dc ALSA: ISA: not for M68K c788ac47502e ARM: dts: ls1021a-tsn: use generic "jedec,spi-nor" compatible for flash cbba09f86976 ARM: dts: ls1021a: move thermal-zones node out of soc/ 2474eb7fc3bf usb: host: ohci-tmio: check return value after calling platform_get_resource() 02d9ebe0ccfa ARM: dts: omap: fix gpmc,mux-add-data type c6c9bbe7facb firmware_loader: fix pre-allocated buf built-in firmware use 02a22911ed87 ALSA: intel-dsp-config: add quirk for APL/GLK/TGL devices based on ES8336 codec 055eced3edf5 scsi: advansys: Fix kernel pointer leak 97f3cbb57b16 ASoC: nau8824: Add DMI quirk mechanism for active-high jack-detect ae2207a078cf clk: imx: imx6ul: Move csi_sel mux to correct base register 0c6daf479961 ASoC: SOF: Intel: hda-dai: fix potential locking issue 19d193c5761a arm64: dts: freescale: fix arm,sp805 compatible string 36446a094a45 arm64: dts: qcom: ipq6018: Fix qcom,controlled-remotely property e52fecdd0c14 arm64: dts: qcom: msm8998: Fix CPU/L2 idle state latency and residency 568d94c5c9f0 ARM: BCM53016: Specify switch ports for Meraki MR32 3a53d9ad9bc3 staging: rtl8723bs: remove possible deadlock when disconnect (v2) 3544c338794b ARM: dts: ux500: Skomer regulator fixes eff8b7628410 usb: typec: tipd: Remove WARN_ON in tps6598x_block_read 679eee466d0f usb: musb: tusb6010: check return value after calling platform_get_resource() 2492de6f5edb bus: ti-sysc: Use context lost quirk for otg 5eca1c8412f4 bus: ti-sysc: Add quirk handling for reinit on context lost dcd6eefceeb0 RDMA/bnxt_re: Check if the vlan is valid before reporting 4e5bc9fb23a7 arm64: dts: hisilicon: fix arm,sp805 compatible string 109a63bb07f0 arm64: dts: rockchip: Disable CDN DP on Pinebook Pro c097bd5a5916 scsi: lpfc: Fix list_add() corruption in lpfc_drain_txq() db90c507832a ARM: dts: NSP: Fix mpcore, mmc node names 5010df76ab1f staging: wfx: ensure IRQ is ready before enabling it 2651d06e461f arm64: dts: allwinner: a100: Fix thermal zone node name fa98ac472e88 arm64: dts: allwinner: h5: Fix GPU thermal zone node name aed195558f94 ARM: dts: sunxi: Fix OPPs node name e2e105631265 arm64: zynqmp: Fix serial compatible string 48f154e8b94a arm64: zynqmp: Do not duplicate flash partition label property Some minor ABI signatures have changed due to internal structures changing. All of these have been pre-approved already: Leaf changes summary: 3 artifacts changed Changed leaf types summary: 3 leaf types changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 0 Added function Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable 'struct bpf_map at bpf.h:146:1' changed: type size hasn't changed there are data member changes: type 'typedef u64' of 'bpf_map::writecnt' changed: typedef name changed from u64 to atomic64_t at types.h:175:1 underlying type 'typedef __u64' at int-ll64.h:31:1 changed: entity changed from 'typedef __u64' to 'struct {s64 counter;}' at types.h:173:1 type size hasn't changed 4790 impacted interfaces 'struct bpf_offloaded_map at bpf.h:229:1' changed (indirectly): type size hasn't changed there are data member changes: type 'struct bpf_map' of 'bpf_offloaded_map::map' changed, as reported earlier 4790 impacted interfaces 'struct fib_rules_ops at fib_rules.h:60:1' changed: type size hasn't changed there are data member changes: type 'typedef bool (fib_rule*, fib_lookup_arg*)*' of 'fib_rules_ops::suppress' changed: pointer type changed from: 'typedef bool (fib_rule*, fib_lookup_arg*)*' to: 'typedef bool (fib_rule*, int, fib_lookup_arg*)*' 4790 impacted interfaces Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Id7f25c9e0edb30698178b138cc1b15a82ca5ef48
4755 lines
122 KiB
C
4755 lines
122 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* linux/fs/namei.c
|
|
*
|
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
|
*/
|
|
|
|
/*
|
|
* Some corrections by tytso.
|
|
*/
|
|
|
|
/* [Feb 1997 T. Schoebel-Theuer] Complete rewrite of the pathname
|
|
* lookup logic.
|
|
*/
|
|
/* [Feb-Apr 2000, AV] Rewrite to the new namespace architecture.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/export.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/namei.h>
|
|
#include <linux/pagemap.h>
|
|
#include <linux/fsnotify.h>
|
|
#include <linux/personality.h>
|
|
#include <linux/security.h>
|
|
#include <linux/ima.h>
|
|
#include <linux/syscalls.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/audit.h>
|
|
#include <linux/capability.h>
|
|
#include <linux/file.h>
|
|
#include <linux/fcntl.h>
|
|
#include <linux/device_cgroup.h>
|
|
#include <linux/fs_struct.h>
|
|
#include <linux/posix_acl.h>
|
|
#include <linux/hash.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/init_task.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#include "internal.h"
|
|
#include "mount.h"
|
|
|
|
#define CREATE_TRACE_POINTS
|
|
#include <trace/events/namei.h>
|
|
|
|
/* [Feb-1997 T. Schoebel-Theuer]
|
|
* Fundamental changes in the pathname lookup mechanisms (namei)
|
|
* were necessary because of omirr. The reason is that omirr needs
|
|
* to know the _real_ pathname, not the user-supplied one, in case
|
|
* of symlinks (and also when transname replacements occur).
|
|
*
|
|
* The new code replaces the old recursive symlink resolution with
|
|
* an iterative one (in case of non-nested symlink chains). It does
|
|
* this with calls to <fs>_follow_link().
|
|
* As a side effect, dir_namei(), _namei() and follow_link() are now
|
|
* replaced with a single function lookup_dentry() that can handle all
|
|
* the special cases of the former code.
|
|
*
|
|
* With the new dcache, the pathname is stored at each inode, at least as
|
|
* long as the refcount of the inode is positive. As a side effect, the
|
|
* size of the dcache depends on the inode cache and thus is dynamic.
|
|
*
|
|
* [29-Apr-1998 C. Scott Ananian] Updated above description of symlink
|
|
* resolution to correspond with current state of the code.
|
|
*
|
|
* Note that the symlink resolution is not *completely* iterative.
|
|
* There is still a significant amount of tail- and mid- recursion in
|
|
* the algorithm. Also, note that <fs>_readlink() is not used in
|
|
* lookup_dentry(): lookup_dentry() on the result of <fs>_readlink()
|
|
* may return different results than <fs>_follow_link(). Many virtual
|
|
* filesystems (including /proc) exhibit this behavior.
|
|
*/
|
|
|
|
/* [24-Feb-97 T. Schoebel-Theuer] Side effects caused by new implementation:
|
|
* New symlink semantics: when open() is called with flags O_CREAT | O_EXCL
|
|
* and the name already exists in form of a symlink, try to create the new
|
|
* name indicated by the symlink. The old code always complained that the
|
|
* name already exists, due to not following the symlink even if its target
|
|
* is nonexistent. The new semantics affects also mknod() and link() when
|
|
* the name is a symlink pointing to a non-existent name.
|
|
*
|
|
* I don't know which semantics is the right one, since I have no access
|
|
* to standards. But I found by trial that HP-UX 9.0 has the full "new"
|
|
* semantics implemented, while SunOS 4.1.1 and Solaris (SunOS 5.4) have the
|
|
* "old" one. Personally, I think the new semantics is much more logical.
|
|
* Note that "ln old new" where "new" is a symlink pointing to a non-existing
|
|
* file does succeed in both HP-UX and SunOs, but not in Solaris
|
|
* and in the old Linux semantics.
|
|
*/
|
|
|
|
/* [16-Dec-97 Kevin Buhr] For security reasons, we change some symlink
|
|
* semantics. See the comments in "open_namei" and "do_link" below.
|
|
*
|
|
* [10-Sep-98 Alan Modra] Another symlink change.
|
|
*/
|
|
|
|
/* [Feb-Apr 2000 AV] Complete rewrite. Rules for symlinks:
|
|
* inside the path - always follow.
|
|
* in the last component in creation/removal/renaming - never follow.
|
|
* if LOOKUP_FOLLOW passed - follow.
|
|
* if the pathname has trailing slashes - follow.
|
|
* otherwise - don't follow.
|
|
* (applied in that order).
|
|
*
|
|
* [Jun 2000 AV] Inconsistent behaviour of open() in case if flags==O_CREAT
|
|
* restored for 2.4. This is the last surviving part of old 4.2BSD bug.
|
|
* During the 2.4 we need to fix the userland stuff depending on it -
|
|
* hopefully we will be able to get rid of that wart in 2.5. So far only
|
|
* XEmacs seems to be relying on it...
|
|
*/
|
|
/*
|
|
* [Sep 2001 AV] Single-semaphore locking scheme (kudos to David Holland)
|
|
* implemented. Let's see if raised priority of ->s_vfs_rename_mutex gives
|
|
* any extra contention...
|
|
*/
|
|
|
|
/* In order to reduce some races, while at the same time doing additional
|
|
* checking and hopefully speeding things up, we copy filenames to the
|
|
* kernel data space before using them..
|
|
*
|
|
* POSIX.1 2.4: an empty pathname is invalid (ENOENT).
|
|
* PATH_MAX includes the nul terminator --RR.
|
|
*/
|
|
|
|
#define EMBEDDED_NAME_MAX (PATH_MAX - offsetof(struct filename, iname))
|
|
|
|
struct filename *
|
|
getname_flags(const char __user *filename, int flags, int *empty)
|
|
{
|
|
struct filename *result;
|
|
char *kname;
|
|
int len;
|
|
|
|
result = audit_reusename(filename);
|
|
if (result)
|
|
return result;
|
|
|
|
result = __getname();
|
|
if (unlikely(!result))
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
/*
|
|
* First, try to embed the struct filename inside the names_cache
|
|
* allocation
|
|
*/
|
|
kname = (char *)result->iname;
|
|
result->name = kname;
|
|
|
|
len = strncpy_from_user(kname, filename, EMBEDDED_NAME_MAX);
|
|
if (unlikely(len < 0)) {
|
|
__putname(result);
|
|
return ERR_PTR(len);
|
|
}
|
|
|
|
/*
|
|
* Uh-oh. We have a name that's approaching PATH_MAX. Allocate a
|
|
* separate struct filename so we can dedicate the entire
|
|
* names_cache allocation for the pathname, and re-do the copy from
|
|
* userland.
|
|
*/
|
|
if (unlikely(len == EMBEDDED_NAME_MAX)) {
|
|
const size_t size = offsetof(struct filename, iname[1]);
|
|
kname = (char *)result;
|
|
|
|
/*
|
|
* size is chosen that way we to guarantee that
|
|
* result->iname[0] is within the same object and that
|
|
* kname can't be equal to result->iname, no matter what.
|
|
*/
|
|
result = kzalloc(size, GFP_KERNEL);
|
|
if (unlikely(!result)) {
|
|
__putname(kname);
|
|
return ERR_PTR(-ENOMEM);
|
|
}
|
|
result->name = kname;
|
|
len = strncpy_from_user(kname, filename, PATH_MAX);
|
|
if (unlikely(len < 0)) {
|
|
__putname(kname);
|
|
kfree(result);
|
|
return ERR_PTR(len);
|
|
}
|
|
if (unlikely(len == PATH_MAX)) {
|
|
__putname(kname);
|
|
kfree(result);
|
|
return ERR_PTR(-ENAMETOOLONG);
|
|
}
|
|
}
|
|
|
|
result->refcnt = 1;
|
|
/* The empty path is special. */
|
|
if (unlikely(!len)) {
|
|
if (empty)
|
|
*empty = 1;
|
|
if (!(flags & LOOKUP_EMPTY)) {
|
|
putname(result);
|
|
return ERR_PTR(-ENOENT);
|
|
}
|
|
}
|
|
|
|
result->uptr = filename;
|
|
result->aname = NULL;
|
|
audit_getname(result);
|
|
return result;
|
|
}
|
|
|
|
struct filename *
|
|
getname(const char __user * filename)
|
|
{
|
|
return getname_flags(filename, 0, NULL);
|
|
}
|
|
|
|
struct filename *
|
|
getname_kernel(const char * filename)
|
|
{
|
|
struct filename *result;
|
|
int len = strlen(filename) + 1;
|
|
|
|
result = __getname();
|
|
if (unlikely(!result))
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
if (len <= EMBEDDED_NAME_MAX) {
|
|
result->name = (char *)result->iname;
|
|
} else if (len <= PATH_MAX) {
|
|
const size_t size = offsetof(struct filename, iname[1]);
|
|
struct filename *tmp;
|
|
|
|
tmp = kmalloc(size, GFP_KERNEL);
|
|
if (unlikely(!tmp)) {
|
|
__putname(result);
|
|
return ERR_PTR(-ENOMEM);
|
|
}
|
|
tmp->name = (char *)result;
|
|
result = tmp;
|
|
} else {
|
|
__putname(result);
|
|
return ERR_PTR(-ENAMETOOLONG);
|
|
}
|
|
memcpy((char *)result->name, filename, len);
|
|
result->uptr = NULL;
|
|
result->aname = NULL;
|
|
result->refcnt = 1;
|
|
audit_getname(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
void putname(struct filename *name)
|
|
{
|
|
BUG_ON(name->refcnt <= 0);
|
|
|
|
if (--name->refcnt > 0)
|
|
return;
|
|
|
|
if (name->name != name->iname) {
|
|
__putname(name->name);
|
|
kfree(name);
|
|
} else
|
|
__putname(name);
|
|
}
|
|
|
|
static int check_acl(struct inode *inode, int mask)
|
|
{
|
|
#ifdef CONFIG_FS_POSIX_ACL
|
|
struct posix_acl *acl;
|
|
|
|
if (mask & MAY_NOT_BLOCK) {
|
|
acl = get_cached_acl_rcu(inode, ACL_TYPE_ACCESS);
|
|
if (!acl)
|
|
return -EAGAIN;
|
|
/* no ->get_acl() calls in RCU mode... */
|
|
if (is_uncached_acl(acl))
|
|
return -ECHILD;
|
|
return posix_acl_permission(inode, acl, mask);
|
|
}
|
|
|
|
acl = get_acl(inode, ACL_TYPE_ACCESS);
|
|
if (IS_ERR(acl))
|
|
return PTR_ERR(acl);
|
|
if (acl) {
|
|
int error = posix_acl_permission(inode, acl, mask);
|
|
posix_acl_release(acl);
|
|
return error;
|
|
}
|
|
#endif
|
|
|
|
return -EAGAIN;
|
|
}
|
|
|
|
/*
|
|
* This does the basic UNIX permission checking.
|
|
*
|
|
* Note that the POSIX ACL check cares about the MAY_NOT_BLOCK bit,
|
|
* for RCU walking.
|
|
*/
|
|
static int acl_permission_check(struct inode *inode, int mask)
|
|
{
|
|
unsigned int mode = inode->i_mode;
|
|
|
|
/* Are we the owner? If so, ACL's don't matter */
|
|
if (likely(uid_eq(current_fsuid(), inode->i_uid))) {
|
|
mask &= 7;
|
|
mode >>= 6;
|
|
return (mask & ~mode) ? -EACCES : 0;
|
|
}
|
|
|
|
/* Do we have ACL's? */
|
|
if (IS_POSIXACL(inode) && (mode & S_IRWXG)) {
|
|
int error = check_acl(inode, mask);
|
|
if (error != -EAGAIN)
|
|
return error;
|
|
}
|
|
|
|
/* Only RWX matters for group/other mode bits */
|
|
mask &= 7;
|
|
|
|
/*
|
|
* Are the group permissions different from
|
|
* the other permissions in the bits we care
|
|
* about? Need to check group ownership if so.
|
|
*/
|
|
if (mask & (mode ^ (mode >> 3))) {
|
|
if (in_group_p(inode->i_gid))
|
|
mode >>= 3;
|
|
}
|
|
|
|
/* Bits in 'mode' clear that we require? */
|
|
return (mask & ~mode) ? -EACCES : 0;
|
|
}
|
|
|
|
/**
|
|
* generic_permission - check for access rights on a Posix-like filesystem
|
|
* @inode: inode to check access rights for
|
|
* @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC,
|
|
* %MAY_NOT_BLOCK ...)
|
|
*
|
|
* Used to check for read/write/execute permissions on a file.
|
|
* We use "fsuid" for this, letting us set arbitrary permissions
|
|
* for filesystem access without changing the "normal" uids which
|
|
* are used for other things.
|
|
*
|
|
* generic_permission is rcu-walk aware. It returns -ECHILD in case an rcu-walk
|
|
* request cannot be satisfied (eg. requires blocking or too much complexity).
|
|
* It would then be called again in ref-walk mode.
|
|
*/
|
|
int generic_permission(struct inode *inode, int mask)
|
|
{
|
|
int ret;
|
|
|
|
/*
|
|
* Do the basic permission checks.
|
|
*/
|
|
ret = acl_permission_check(inode, mask);
|
|
if (ret != -EACCES)
|
|
return ret;
|
|
|
|
if (S_ISDIR(inode->i_mode)) {
|
|
/* DACs are overridable for directories */
|
|
if (!(mask & MAY_WRITE))
|
|
if (capable_wrt_inode_uidgid(inode,
|
|
CAP_DAC_READ_SEARCH))
|
|
return 0;
|
|
if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
|
|
return 0;
|
|
return -EACCES;
|
|
}
|
|
|
|
/*
|
|
* Searching includes executable on directories, else just read.
|
|
*/
|
|
mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
|
|
if (mask == MAY_READ)
|
|
if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH))
|
|
return 0;
|
|
/*
|
|
* Read/write DACs are always overridable.
|
|
* Executable DACs are overridable when there is
|
|
* at least one exec bit set.
|
|
*/
|
|
if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
|
|
if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
|
|
return 0;
|
|
|
|
return -EACCES;
|
|
}
|
|
EXPORT_SYMBOL(generic_permission);
|
|
|
|
/*
|
|
* We _really_ want to just do "generic_permission()" without
|
|
* even looking at the inode->i_op values. So we keep a cache
|
|
* flag in inode->i_opflags, that says "this has not special
|
|
* permission function, use the fast case".
|
|
*/
|
|
static inline int do_inode_permission(struct inode *inode, int mask)
|
|
{
|
|
if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) {
|
|
if (likely(inode->i_op->permission))
|
|
return inode->i_op->permission(inode, mask);
|
|
|
|
/* This gets set once for the inode lifetime */
|
|
spin_lock(&inode->i_lock);
|
|
inode->i_opflags |= IOP_FASTPERM;
|
|
spin_unlock(&inode->i_lock);
|
|
}
|
|
return generic_permission(inode, mask);
|
|
}
|
|
|
|
/**
|
|
* sb_permission - Check superblock-level permissions
|
|
* @sb: Superblock of inode to check permission on
|
|
* @inode: Inode to check permission on
|
|
* @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
|
|
*
|
|
* Separate out file-system wide checks from inode-specific permission checks.
|
|
*/
|
|
static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
|
|
{
|
|
if (unlikely(mask & MAY_WRITE)) {
|
|
umode_t mode = inode->i_mode;
|
|
|
|
/* Nobody gets write access to a read-only fs. */
|
|
if (sb_rdonly(sb) && (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
|
|
return -EROFS;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* inode_permission - Check for access rights to a given inode
|
|
* @inode: Inode to check permission on
|
|
* @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
|
|
*
|
|
* Check for read/write/execute permissions on an inode. We use fs[ug]id for
|
|
* this, letting us set arbitrary permissions for filesystem access without
|
|
* changing the "normal" UIDs which are used for other things.
|
|
*
|
|
* When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
|
|
*/
|
|
int inode_permission(struct inode *inode, int mask)
|
|
{
|
|
int retval;
|
|
|
|
retval = sb_permission(inode->i_sb, inode, mask);
|
|
if (retval)
|
|
return retval;
|
|
|
|
if (unlikely(mask & MAY_WRITE)) {
|
|
/*
|
|
* Nobody gets write access to an immutable file.
|
|
*/
|
|
if (IS_IMMUTABLE(inode))
|
|
return -EPERM;
|
|
|
|
/*
|
|
* Updating mtime will likely cause i_uid and i_gid to be
|
|
* written back improperly if their true value is unknown
|
|
* to the vfs.
|
|
*/
|
|
if (HAS_UNMAPPED_ID(inode))
|
|
return -EACCES;
|
|
}
|
|
|
|
retval = do_inode_permission(inode, mask);
|
|
if (retval)
|
|
return retval;
|
|
|
|
retval = devcgroup_inode_permission(inode, mask);
|
|
if (retval)
|
|
return retval;
|
|
|
|
return security_inode_permission(inode, mask);
|
|
}
|
|
EXPORT_SYMBOL(inode_permission);
|
|
|
|
/**
|
|
* path_get - get a reference to a path
|
|
* @path: path to get the reference to
|
|
*
|
|
* Given a path increment the reference count to the dentry and the vfsmount.
|
|
*/
|
|
void path_get(const struct path *path)
|
|
{
|
|
mntget(path->mnt);
|
|
dget(path->dentry);
|
|
}
|
|
EXPORT_SYMBOL(path_get);
|
|
|
|
/**
|
|
* path_put - put a reference to a path
|
|
* @path: path to put the reference to
|
|
*
|
|
* Given a path decrement the reference count to the dentry and the vfsmount.
|
|
*/
|
|
void path_put(const struct path *path)
|
|
{
|
|
dput(path->dentry);
|
|
mntput(path->mnt);
|
|
}
|
|
EXPORT_SYMBOL(path_put);
|
|
|
|
#define EMBEDDED_LEVELS 2
|
|
struct nameidata {
|
|
struct path path;
|
|
struct qstr last;
|
|
struct path root;
|
|
struct inode *inode; /* path.dentry.d_inode */
|
|
unsigned int flags;
|
|
unsigned seq, m_seq, r_seq;
|
|
int last_type;
|
|
unsigned depth;
|
|
int total_link_count;
|
|
struct saved {
|
|
struct path link;
|
|
struct delayed_call done;
|
|
const char *name;
|
|
unsigned seq;
|
|
} *stack, internal[EMBEDDED_LEVELS];
|
|
struct filename *name;
|
|
struct nameidata *saved;
|
|
unsigned root_seq;
|
|
int dfd;
|
|
kuid_t dir_uid;
|
|
umode_t dir_mode;
|
|
} __randomize_layout;
|
|
|
|
static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
|
|
{
|
|
struct nameidata *old = current->nameidata;
|
|
p->stack = p->internal;
|
|
p->dfd = dfd;
|
|
p->name = name;
|
|
p->total_link_count = old ? old->total_link_count : 0;
|
|
p->saved = old;
|
|
current->nameidata = p;
|
|
}
|
|
|
|
static void restore_nameidata(void)
|
|
{
|
|
struct nameidata *now = current->nameidata, *old = now->saved;
|
|
|
|
current->nameidata = old;
|
|
if (old)
|
|
old->total_link_count = now->total_link_count;
|
|
if (now->stack != now->internal)
|
|
kfree(now->stack);
|
|
}
|
|
|
|
static bool nd_alloc_stack(struct nameidata *nd)
|
|
{
|
|
struct saved *p;
|
|
|
|
p= kmalloc_array(MAXSYMLINKS, sizeof(struct saved),
|
|
nd->flags & LOOKUP_RCU ? GFP_ATOMIC : GFP_KERNEL);
|
|
if (unlikely(!p))
|
|
return false;
|
|
memcpy(p, nd->internal, sizeof(nd->internal));
|
|
nd->stack = p;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* path_connected - Verify that a dentry is below mnt.mnt_root
|
|
*
|
|
* Rename can sometimes move a file or directory outside of a bind
|
|
* mount, path_connected allows those cases to be detected.
|
|
*/
|
|
static bool path_connected(struct vfsmount *mnt, struct dentry *dentry)
|
|
{
|
|
struct super_block *sb = mnt->mnt_sb;
|
|
|
|
/* Bind mounts can have disconnected paths */
|
|
if (mnt->mnt_root == sb->s_root)
|
|
return true;
|
|
|
|
return is_subdir(dentry, mnt->mnt_root);
|
|
}
|
|
|
|
static void drop_links(struct nameidata *nd)
|
|
{
|
|
int i = nd->depth;
|
|
while (i--) {
|
|
struct saved *last = nd->stack + i;
|
|
do_delayed_call(&last->done);
|
|
clear_delayed_call(&last->done);
|
|
}
|
|
}
|
|
|
|
static void terminate_walk(struct nameidata *nd)
|
|
{
|
|
drop_links(nd);
|
|
if (!(nd->flags & LOOKUP_RCU)) {
|
|
int i;
|
|
path_put(&nd->path);
|
|
for (i = 0; i < nd->depth; i++)
|
|
path_put(&nd->stack[i].link);
|
|
if (nd->flags & LOOKUP_ROOT_GRABBED) {
|
|
path_put(&nd->root);
|
|
nd->flags &= ~LOOKUP_ROOT_GRABBED;
|
|
}
|
|
} else {
|
|
nd->flags &= ~LOOKUP_RCU;
|
|
rcu_read_unlock();
|
|
}
|
|
nd->depth = 0;
|
|
}
|
|
|
|
/* path_put is needed afterwards regardless of success or failure */
|
|
static bool __legitimize_path(struct path *path, unsigned seq, unsigned mseq)
|
|
{
|
|
int res = __legitimize_mnt(path->mnt, mseq);
|
|
if (unlikely(res)) {
|
|
if (res > 0)
|
|
path->mnt = NULL;
|
|
path->dentry = NULL;
|
|
return false;
|
|
}
|
|
if (unlikely(!lockref_get_not_dead(&path->dentry->d_lockref))) {
|
|
path->dentry = NULL;
|
|
return false;
|
|
}
|
|
return !read_seqcount_retry(&path->dentry->d_seq, seq);
|
|
}
|
|
|
|
static inline bool legitimize_path(struct nameidata *nd,
|
|
struct path *path, unsigned seq)
|
|
{
|
|
return __legitimize_path(path, seq, nd->m_seq);
|
|
}
|
|
|
|
static bool legitimize_links(struct nameidata *nd)
|
|
{
|
|
int i;
|
|
for (i = 0; i < nd->depth; i++) {
|
|
struct saved *last = nd->stack + i;
|
|
if (unlikely(!legitimize_path(nd, &last->link, last->seq))) {
|
|
drop_links(nd);
|
|
nd->depth = i + 1;
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool legitimize_root(struct nameidata *nd)
|
|
{
|
|
/*
|
|
* For scoped-lookups (where nd->root has been zeroed), we need to
|
|
* restart the whole lookup from scratch -- because set_root() is wrong
|
|
* for these lookups (nd->dfd is the root, not the filesystem root).
|
|
*/
|
|
if (!nd->root.mnt && (nd->flags & LOOKUP_IS_SCOPED))
|
|
return false;
|
|
/* Nothing to do if nd->root is zero or is managed by the VFS user. */
|
|
if (!nd->root.mnt || (nd->flags & LOOKUP_ROOT))
|
|
return true;
|
|
nd->flags |= LOOKUP_ROOT_GRABBED;
|
|
return legitimize_path(nd, &nd->root, nd->root_seq);
|
|
}
|
|
|
|
/*
|
|
* Path walking has 2 modes, rcu-walk and ref-walk (see
|
|
* Documentation/filesystems/path-lookup.txt). In situations when we can't
|
|
* continue in RCU mode, we attempt to drop out of rcu-walk mode and grab
|
|
* normal reference counts on dentries and vfsmounts to transition to ref-walk
|
|
* mode. Refcounts are grabbed at the last known good point before rcu-walk
|
|
* got stuck, so ref-walk may continue from there. If this is not successful
|
|
* (eg. a seqcount has changed), then failure is returned and it's up to caller
|
|
* to restart the path walk from the beginning in ref-walk mode.
|
|
*/
|
|
|
|
/**
|
|
* try_to_unlazy - try to switch to ref-walk mode.
|
|
* @nd: nameidata pathwalk data
|
|
* Returns: true on success, false on failure
|
|
*
|
|
* try_to_unlazy attempts to legitimize the current nd->path and nd->root
|
|
* for ref-walk mode.
|
|
* Must be called from rcu-walk context.
|
|
* Nothing should touch nameidata between try_to_unlazy() failure and
|
|
* terminate_walk().
|
|
*/
|
|
static bool try_to_unlazy(struct nameidata *nd)
|
|
{
|
|
struct dentry *parent = nd->path.dentry;
|
|
|
|
BUG_ON(!(nd->flags & LOOKUP_RCU));
|
|
|
|
nd->flags &= ~LOOKUP_RCU;
|
|
if (unlikely(!legitimize_links(nd)))
|
|
goto out1;
|
|
if (unlikely(!legitimize_path(nd, &nd->path, nd->seq)))
|
|
goto out;
|
|
if (unlikely(!legitimize_root(nd)))
|
|
goto out;
|
|
rcu_read_unlock();
|
|
BUG_ON(nd->inode != parent->d_inode);
|
|
return true;
|
|
|
|
out1:
|
|
nd->path.mnt = NULL;
|
|
nd->path.dentry = NULL;
|
|
out:
|
|
rcu_read_unlock();
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* unlazy_child - try to switch to ref-walk mode.
|
|
* @nd: nameidata pathwalk data
|
|
* @dentry: child of nd->path.dentry
|
|
* @seq: seq number to check dentry against
|
|
* Returns: 0 on success, -ECHILD on failure
|
|
*
|
|
* unlazy_child attempts to legitimize the current nd->path, nd->root and dentry
|
|
* for ref-walk mode. @dentry must be a path found by a do_lookup call on
|
|
* @nd. Must be called from rcu-walk context.
|
|
* Nothing should touch nameidata between unlazy_child() failure and
|
|
* terminate_walk().
|
|
*/
|
|
static int unlazy_child(struct nameidata *nd, struct dentry *dentry, unsigned seq)
|
|
{
|
|
BUG_ON(!(nd->flags & LOOKUP_RCU));
|
|
|
|
nd->flags &= ~LOOKUP_RCU;
|
|
if (unlikely(!legitimize_links(nd)))
|
|
goto out2;
|
|
if (unlikely(!legitimize_mnt(nd->path.mnt, nd->m_seq)))
|
|
goto out2;
|
|
if (unlikely(!lockref_get_not_dead(&nd->path.dentry->d_lockref)))
|
|
goto out1;
|
|
|
|
/*
|
|
* We need to move both the parent and the dentry from the RCU domain
|
|
* to be properly refcounted. And the sequence number in the dentry
|
|
* validates *both* dentry counters, since we checked the sequence
|
|
* number of the parent after we got the child sequence number. So we
|
|
* know the parent must still be valid if the child sequence number is
|
|
*/
|
|
if (unlikely(!lockref_get_not_dead(&dentry->d_lockref)))
|
|
goto out;
|
|
if (unlikely(read_seqcount_retry(&dentry->d_seq, seq)))
|
|
goto out_dput;
|
|
/*
|
|
* Sequence counts matched. Now make sure that the root is
|
|
* still valid and get it if required.
|
|
*/
|
|
if (unlikely(!legitimize_root(nd)))
|
|
goto out_dput;
|
|
rcu_read_unlock();
|
|
return 0;
|
|
|
|
out2:
|
|
nd->path.mnt = NULL;
|
|
out1:
|
|
nd->path.dentry = NULL;
|
|
out:
|
|
rcu_read_unlock();
|
|
return -ECHILD;
|
|
out_dput:
|
|
rcu_read_unlock();
|
|
dput(dentry);
|
|
return -ECHILD;
|
|
}
|
|
|
|
static inline int d_revalidate(struct dentry *dentry, unsigned int flags)
|
|
{
|
|
if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE))
|
|
return dentry->d_op->d_revalidate(dentry, flags);
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
#define INIT_PATH_SIZE 64
|
|
|
|
static void success_walk_trace(struct nameidata *nd)
|
|
{
|
|
struct path *pt = &nd->path;
|
|
struct inode *i = nd->inode;
|
|
char buf[INIT_PATH_SIZE], *try_buf;
|
|
int cur_path_size;
|
|
char *p;
|
|
|
|
/* When eBPF/ tracepoint is disabled, keep overhead low. */
|
|
if (!trace_inodepath_enabled())
|
|
return;
|
|
|
|
/* First try stack allocated buffer. */
|
|
try_buf = buf;
|
|
cur_path_size = INIT_PATH_SIZE;
|
|
|
|
while (cur_path_size <= PATH_MAX) {
|
|
/* Free previous heap allocation if we are now trying
|
|
* a second or later heap allocation.
|
|
*/
|
|
if (try_buf != buf)
|
|
kfree(try_buf);
|
|
|
|
/* All but the first alloc are on the heap. */
|
|
if (cur_path_size != INIT_PATH_SIZE) {
|
|
try_buf = kmalloc(cur_path_size, GFP_KERNEL);
|
|
if (!try_buf) {
|
|
try_buf = buf;
|
|
sprintf(try_buf, "error:buf_alloc_failed");
|
|
break;
|
|
}
|
|
}
|
|
|
|
p = d_path(pt, try_buf, cur_path_size);
|
|
|
|
if (!IS_ERR(p)) {
|
|
char *end = mangle_path(try_buf, p, "\n");
|
|
|
|
if (end) {
|
|
try_buf[end - try_buf] = 0;
|
|
break;
|
|
} else {
|
|
/* On mangle errors, double path size
|
|
* till PATH_MAX.
|
|
*/
|
|
cur_path_size = cur_path_size << 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (PTR_ERR(p) == -ENAMETOOLONG) {
|
|
/* If d_path complains that name is too long,
|
|
* then double path size till PATH_MAX.
|
|
*/
|
|
cur_path_size = cur_path_size << 1;
|
|
continue;
|
|
}
|
|
|
|
sprintf(try_buf, "error:d_path_failed_%lu",
|
|
-1 * PTR_ERR(p));
|
|
break;
|
|
}
|
|
|
|
if (cur_path_size > PATH_MAX)
|
|
sprintf(try_buf, "error:d_path_name_too_long");
|
|
|
|
trace_inodepath(i, try_buf);
|
|
|
|
if (try_buf != buf)
|
|
kfree(try_buf);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* complete_walk - successful completion of path walk
|
|
* @nd: pointer nameidata
|
|
*
|
|
* If we had been in RCU mode, drop out of it and legitimize nd->path.
|
|
* Revalidate the final result, unless we'd already done that during
|
|
* the path walk or the filesystem doesn't ask for it. Return 0 on
|
|
* success, -error on failure. In case of failure caller does not
|
|
* need to drop nd->path.
|
|
*/
|
|
static int complete_walk(struct nameidata *nd)
|
|
{
|
|
struct dentry *dentry = nd->path.dentry;
|
|
int status;
|
|
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
/*
|
|
* We don't want to zero nd->root for scoped-lookups or
|
|
* externally-managed nd->root.
|
|
*/
|
|
if (!(nd->flags & (LOOKUP_ROOT | LOOKUP_IS_SCOPED)))
|
|
nd->root.mnt = NULL;
|
|
if (!try_to_unlazy(nd))
|
|
return -ECHILD;
|
|
}
|
|
|
|
if (unlikely(nd->flags & LOOKUP_IS_SCOPED)) {
|
|
/*
|
|
* While the guarantee of LOOKUP_IS_SCOPED is (roughly) "don't
|
|
* ever step outside the root during lookup" and should already
|
|
* be guaranteed by the rest of namei, we want to avoid a namei
|
|
* BUG resulting in userspace being given a path that was not
|
|
* scoped within the root at some point during the lookup.
|
|
*
|
|
* So, do a final sanity-check to make sure that in the
|
|
* worst-case scenario (a complete bypass of LOOKUP_IS_SCOPED)
|
|
* we won't silently return an fd completely outside of the
|
|
* requested root to userspace.
|
|
*
|
|
* Userspace could move the path outside the root after this
|
|
* check, but as discussed elsewhere this is not a concern (the
|
|
* resolved file was inside the root at some point).
|
|
*/
|
|
if (!path_is_under(&nd->path, &nd->root))
|
|
return -EXDEV;
|
|
}
|
|
|
|
if (likely(!(nd->flags & LOOKUP_JUMPED))) {
|
|
success_walk_trace(nd);
|
|
return 0;
|
|
}
|
|
|
|
if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE))) {
|
|
success_walk_trace(nd);
|
|
return 0;
|
|
}
|
|
|
|
status = dentry->d_op->d_weak_revalidate(dentry, nd->flags);
|
|
if (status > 0) {
|
|
success_walk_trace(nd);
|
|
return 0;
|
|
}
|
|
|
|
if (!status)
|
|
status = -ESTALE;
|
|
|
|
return status;
|
|
}
|
|
|
|
static int set_root(struct nameidata *nd)
|
|
{
|
|
struct fs_struct *fs = current->fs;
|
|
|
|
/*
|
|
* Jumping to the real root in a scoped-lookup is a BUG in namei, but we
|
|
* still have to ensure it doesn't happen because it will cause a breakout
|
|
* from the dirfd.
|
|
*/
|
|
if (WARN_ON(nd->flags & LOOKUP_IS_SCOPED))
|
|
return -ENOTRECOVERABLE;
|
|
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
unsigned seq;
|
|
|
|
do {
|
|
seq = read_seqcount_begin(&fs->seq);
|
|
nd->root = fs->root;
|
|
nd->root_seq = __read_seqcount_begin(&nd->root.dentry->d_seq);
|
|
} while (read_seqcount_retry(&fs->seq, seq));
|
|
} else {
|
|
get_fs_root(fs, &nd->root);
|
|
nd->flags |= LOOKUP_ROOT_GRABBED;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int nd_jump_root(struct nameidata *nd)
|
|
{
|
|
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
|
return -EXDEV;
|
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV)) {
|
|
/* Absolute path arguments to path_init() are allowed. */
|
|
if (nd->path.mnt != NULL && nd->path.mnt != nd->root.mnt)
|
|
return -EXDEV;
|
|
}
|
|
if (!nd->root.mnt) {
|
|
int error = set_root(nd);
|
|
if (error)
|
|
return error;
|
|
}
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
struct dentry *d;
|
|
nd->path = nd->root;
|
|
d = nd->path.dentry;
|
|
nd->inode = d->d_inode;
|
|
nd->seq = nd->root_seq;
|
|
if (unlikely(read_seqcount_retry(&d->d_seq, nd->seq)))
|
|
return -ECHILD;
|
|
} else {
|
|
path_put(&nd->path);
|
|
nd->path = nd->root;
|
|
path_get(&nd->path);
|
|
nd->inode = nd->path.dentry->d_inode;
|
|
}
|
|
nd->flags |= LOOKUP_JUMPED;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Helper to directly jump to a known parsed path from ->get_link,
|
|
* caller must have taken a reference to path beforehand.
|
|
*/
|
|
int nd_jump_link(struct path *path)
|
|
{
|
|
int error = -ELOOP;
|
|
struct nameidata *nd = current->nameidata;
|
|
|
|
if (unlikely(nd->flags & LOOKUP_NO_MAGICLINKS))
|
|
goto err;
|
|
|
|
error = -EXDEV;
|
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV)) {
|
|
if (nd->path.mnt != path->mnt)
|
|
goto err;
|
|
}
|
|
/* Not currently safe for scoped-lookups. */
|
|
if (unlikely(nd->flags & LOOKUP_IS_SCOPED))
|
|
goto err;
|
|
|
|
path_put(&nd->path);
|
|
nd->path = *path;
|
|
nd->inode = nd->path.dentry->d_inode;
|
|
nd->flags |= LOOKUP_JUMPED;
|
|
return 0;
|
|
|
|
err:
|
|
path_put(path);
|
|
return error;
|
|
}
|
|
|
|
static inline void put_link(struct nameidata *nd)
|
|
{
|
|
struct saved *last = nd->stack + --nd->depth;
|
|
do_delayed_call(&last->done);
|
|
if (!(nd->flags & LOOKUP_RCU))
|
|
path_put(&last->link);
|
|
}
|
|
|
|
int sysctl_protected_symlinks __read_mostly = 0;
|
|
int sysctl_protected_hardlinks __read_mostly = 0;
|
|
int sysctl_protected_fifos __read_mostly;
|
|
int sysctl_protected_regular __read_mostly;
|
|
|
|
/**
|
|
* may_follow_link - Check symlink following for unsafe situations
|
|
* @nd: nameidata pathwalk data
|
|
*
|
|
* In the case of the sysctl_protected_symlinks sysctl being enabled,
|
|
* CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is
|
|
* in a sticky world-writable directory. This is to protect privileged
|
|
* processes from failing races against path names that may change out
|
|
* from under them by way of other users creating malicious symlinks.
|
|
* It will permit symlinks to be followed only when outside a sticky
|
|
* world-writable directory, or when the uid of the symlink and follower
|
|
* match, or when the directory owner matches the symlink's owner.
|
|
*
|
|
* Returns 0 if following the symlink is allowed, -ve on error.
|
|
*/
|
|
static inline int may_follow_link(struct nameidata *nd, const struct inode *inode)
|
|
{
|
|
if (!sysctl_protected_symlinks)
|
|
return 0;
|
|
|
|
/* Allowed if owner and follower match. */
|
|
if (uid_eq(current_cred()->fsuid, inode->i_uid))
|
|
return 0;
|
|
|
|
/* Allowed if parent directory not sticky and world-writable. */
|
|
if ((nd->dir_mode & (S_ISVTX|S_IWOTH)) != (S_ISVTX|S_IWOTH))
|
|
return 0;
|
|
|
|
/* Allowed if parent directory and link owner match. */
|
|
if (uid_valid(nd->dir_uid) && uid_eq(nd->dir_uid, inode->i_uid))
|
|
return 0;
|
|
|
|
if (nd->flags & LOOKUP_RCU)
|
|
return -ECHILD;
|
|
|
|
audit_inode(nd->name, nd->stack[0].link.dentry, 0);
|
|
audit_log_path_denied(AUDIT_ANOM_LINK, "follow_link");
|
|
return -EACCES;
|
|
}
|
|
|
|
/**
|
|
* safe_hardlink_source - Check for safe hardlink conditions
|
|
* @inode: the source inode to hardlink from
|
|
*
|
|
* Return false if at least one of the following conditions:
|
|
* - inode is not a regular file
|
|
* - inode is setuid
|
|
* - inode is setgid and group-exec
|
|
* - access failure for read and write
|
|
*
|
|
* Otherwise returns true.
|
|
*/
|
|
static bool safe_hardlink_source(struct inode *inode)
|
|
{
|
|
umode_t mode = inode->i_mode;
|
|
|
|
/* Special files should not get pinned to the filesystem. */
|
|
if (!S_ISREG(mode))
|
|
return false;
|
|
|
|
/* Setuid files should not get pinned to the filesystem. */
|
|
if (mode & S_ISUID)
|
|
return false;
|
|
|
|
/* Executable setgid files should not get pinned to the filesystem. */
|
|
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
|
|
return false;
|
|
|
|
/* Hardlinking to unreadable or unwritable sources is dangerous. */
|
|
if (inode_permission(inode, MAY_READ | MAY_WRITE))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* may_linkat - Check permissions for creating a hardlink
|
|
* @link: the source to hardlink from
|
|
*
|
|
* Block hardlink when all of:
|
|
* - sysctl_protected_hardlinks enabled
|
|
* - fsuid does not match inode
|
|
* - hardlink source is unsafe (see safe_hardlink_source() above)
|
|
* - not CAP_FOWNER in a namespace with the inode owner uid mapped
|
|
*
|
|
* Returns 0 if successful, -ve on error.
|
|
*/
|
|
int may_linkat(struct path *link)
|
|
{
|
|
struct inode *inode = link->dentry->d_inode;
|
|
|
|
/* Inode writeback is not safe when the uid or gid are invalid. */
|
|
if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
|
|
return -EOVERFLOW;
|
|
|
|
if (!sysctl_protected_hardlinks)
|
|
return 0;
|
|
|
|
/* Source inode owner (or CAP_FOWNER) can hardlink all they like,
|
|
* otherwise, it must be a safe source.
|
|
*/
|
|
if (safe_hardlink_source(inode) || inode_owner_or_capable(inode))
|
|
return 0;
|
|
|
|
audit_log_path_denied(AUDIT_ANOM_LINK, "linkat");
|
|
return -EPERM;
|
|
}
|
|
|
|
/**
|
|
* may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
|
|
* should be allowed, or not, on files that already
|
|
* exist.
|
|
* @dir_mode: mode bits of directory
|
|
* @dir_uid: owner of directory
|
|
* @inode: the inode of the file to open
|
|
*
|
|
* Block an O_CREAT open of a FIFO (or a regular file) when:
|
|
* - sysctl_protected_fifos (or sysctl_protected_regular) is enabled
|
|
* - the file already exists
|
|
* - we are in a sticky directory
|
|
* - we don't own the file
|
|
* - the owner of the directory doesn't own the file
|
|
* - the directory is world writable
|
|
* If the sysctl_protected_fifos (or sysctl_protected_regular) is set to 2
|
|
* the directory doesn't have to be world writable: being group writable will
|
|
* be enough.
|
|
*
|
|
* Returns 0 if the open is allowed, -ve on error.
|
|
*/
|
|
static int may_create_in_sticky(umode_t dir_mode, kuid_t dir_uid,
|
|
struct inode * const inode)
|
|
{
|
|
if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
|
|
(!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
|
|
likely(!(dir_mode & S_ISVTX)) ||
|
|
uid_eq(inode->i_uid, dir_uid) ||
|
|
uid_eq(current_fsuid(), inode->i_uid))
|
|
return 0;
|
|
|
|
if (likely(dir_mode & 0002) ||
|
|
(dir_mode & 0020 &&
|
|
((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
|
|
(sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
|
|
const char *operation = S_ISFIFO(inode->i_mode) ?
|
|
"sticky_create_fifo" :
|
|
"sticky_create_regular";
|
|
audit_log_path_denied(AUDIT_ANOM_CREAT, operation);
|
|
return -EACCES;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* follow_up - Find the mountpoint of path's vfsmount
|
|
*
|
|
* Given a path, find the mountpoint of its source file system.
|
|
* Replace @path with the path of the mountpoint in the parent mount.
|
|
* Up is towards /.
|
|
*
|
|
* Return 1 if we went up a level and 0 if we were already at the
|
|
* root.
|
|
*/
|
|
int follow_up(struct path *path)
|
|
{
|
|
struct mount *mnt = real_mount(path->mnt);
|
|
struct mount *parent;
|
|
struct dentry *mountpoint;
|
|
|
|
read_seqlock_excl(&mount_lock);
|
|
parent = mnt->mnt_parent;
|
|
if (parent == mnt) {
|
|
read_sequnlock_excl(&mount_lock);
|
|
return 0;
|
|
}
|
|
mntget(&parent->mnt);
|
|
mountpoint = dget(mnt->mnt_mountpoint);
|
|
read_sequnlock_excl(&mount_lock);
|
|
dput(path->dentry);
|
|
path->dentry = mountpoint;
|
|
mntput(path->mnt);
|
|
path->mnt = &parent->mnt;
|
|
return 1;
|
|
}
|
|
EXPORT_SYMBOL(follow_up);
|
|
|
|
static bool choose_mountpoint_rcu(struct mount *m, const struct path *root,
|
|
struct path *path, unsigned *seqp)
|
|
{
|
|
while (mnt_has_parent(m)) {
|
|
struct dentry *mountpoint = m->mnt_mountpoint;
|
|
|
|
m = m->mnt_parent;
|
|
if (unlikely(root->dentry == mountpoint &&
|
|
root->mnt == &m->mnt))
|
|
break;
|
|
if (mountpoint != m->mnt.mnt_root) {
|
|
path->mnt = &m->mnt;
|
|
path->dentry = mountpoint;
|
|
*seqp = read_seqcount_begin(&mountpoint->d_seq);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool choose_mountpoint(struct mount *m, const struct path *root,
|
|
struct path *path)
|
|
{
|
|
bool found;
|
|
|
|
rcu_read_lock();
|
|
while (1) {
|
|
unsigned seq, mseq = read_seqbegin(&mount_lock);
|
|
|
|
found = choose_mountpoint_rcu(m, root, path, &seq);
|
|
if (unlikely(!found)) {
|
|
if (!read_seqretry(&mount_lock, mseq))
|
|
break;
|
|
} else {
|
|
if (likely(__legitimize_path(path, seq, mseq)))
|
|
break;
|
|
rcu_read_unlock();
|
|
path_put(path);
|
|
rcu_read_lock();
|
|
}
|
|
}
|
|
rcu_read_unlock();
|
|
return found;
|
|
}
|
|
|
|
/*
|
|
* Perform an automount
|
|
* - return -EISDIR to tell follow_managed() to stop and return the path we
|
|
* were called with.
|
|
*/
|
|
static int follow_automount(struct path *path, int *count, unsigned lookup_flags)
|
|
{
|
|
struct dentry *dentry = path->dentry;
|
|
|
|
/* We don't want to mount if someone's just doing a stat -
|
|
* unless they're stat'ing a directory and appended a '/' to
|
|
* the name.
|
|
*
|
|
* We do, however, want to mount if someone wants to open or
|
|
* create a file of any type under the mountpoint, wants to
|
|
* traverse through the mountpoint or wants to open the
|
|
* mounted directory. Also, autofs may mark negative dentries
|
|
* as being automount points. These will need the attentions
|
|
* of the daemon to instantiate them before they can be used.
|
|
*/
|
|
if (!(lookup_flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
|
|
LOOKUP_OPEN | LOOKUP_CREATE | LOOKUP_AUTOMOUNT)) &&
|
|
dentry->d_inode)
|
|
return -EISDIR;
|
|
|
|
if (count && (*count)++ >= MAXSYMLINKS)
|
|
return -ELOOP;
|
|
|
|
return finish_automount(dentry->d_op->d_automount(path), path);
|
|
}
|
|
|
|
/*
|
|
* mount traversal - out-of-line part. One note on ->d_flags accesses -
|
|
* dentries are pinned but not locked here, so negative dentry can go
|
|
* positive right under us. Use of smp_load_acquire() provides a barrier
|
|
* sufficient for ->d_inode and ->d_flags consistency.
|
|
*/
|
|
static int __traverse_mounts(struct path *path, unsigned flags, bool *jumped,
|
|
int *count, unsigned lookup_flags)
|
|
{
|
|
struct vfsmount *mnt = path->mnt;
|
|
bool need_mntput = false;
|
|
int ret = 0;
|
|
|
|
while (flags & DCACHE_MANAGED_DENTRY) {
|
|
/* Allow the filesystem to manage the transit without i_mutex
|
|
* being held. */
|
|
if (flags & DCACHE_MANAGE_TRANSIT) {
|
|
ret = path->dentry->d_op->d_manage(path, false);
|
|
flags = smp_load_acquire(&path->dentry->d_flags);
|
|
if (ret < 0)
|
|
break;
|
|
}
|
|
|
|
if (flags & DCACHE_MOUNTED) { // something's mounted on it..
|
|
struct vfsmount *mounted = lookup_mnt(path);
|
|
if (mounted) { // ... in our namespace
|
|
dput(path->dentry);
|
|
if (need_mntput)
|
|
mntput(path->mnt);
|
|
path->mnt = mounted;
|
|
path->dentry = dget(mounted->mnt_root);
|
|
// here we know it's positive
|
|
flags = path->dentry->d_flags;
|
|
need_mntput = true;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!(flags & DCACHE_NEED_AUTOMOUNT))
|
|
break;
|
|
|
|
// uncovered automount point
|
|
ret = follow_automount(path, count, lookup_flags);
|
|
flags = smp_load_acquire(&path->dentry->d_flags);
|
|
if (ret < 0)
|
|
break;
|
|
}
|
|
|
|
if (ret == -EISDIR)
|
|
ret = 0;
|
|
// possible if you race with several mount --move
|
|
if (need_mntput && path->mnt == mnt)
|
|
mntput(path->mnt);
|
|
if (!ret && unlikely(d_flags_negative(flags)))
|
|
ret = -ENOENT;
|
|
*jumped = need_mntput;
|
|
return ret;
|
|
}
|
|
|
|
static inline int traverse_mounts(struct path *path, bool *jumped,
|
|
int *count, unsigned lookup_flags)
|
|
{
|
|
unsigned flags = smp_load_acquire(&path->dentry->d_flags);
|
|
|
|
/* fastpath */
|
|
if (likely(!(flags & DCACHE_MANAGED_DENTRY))) {
|
|
*jumped = false;
|
|
if (unlikely(d_flags_negative(flags)))
|
|
return -ENOENT;
|
|
return 0;
|
|
}
|
|
return __traverse_mounts(path, flags, jumped, count, lookup_flags);
|
|
}
|
|
|
|
int follow_down_one(struct path *path)
|
|
{
|
|
struct vfsmount *mounted;
|
|
|
|
mounted = lookup_mnt(path);
|
|
if (mounted) {
|
|
dput(path->dentry);
|
|
mntput(path->mnt);
|
|
path->mnt = mounted;
|
|
path->dentry = dget(mounted->mnt_root);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(follow_down_one);
|
|
|
|
/*
|
|
* Follow down to the covering mount currently visible to userspace. At each
|
|
* point, the filesystem owning that dentry may be queried as to whether the
|
|
* caller is permitted to proceed or not.
|
|
*/
|
|
int follow_down(struct path *path)
|
|
{
|
|
struct vfsmount *mnt = path->mnt;
|
|
bool jumped;
|
|
int ret = traverse_mounts(path, &jumped, NULL, 0);
|
|
|
|
if (path->mnt != mnt)
|
|
mntput(mnt);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(follow_down);
|
|
|
|
/*
|
|
* Try to skip to top of mountpoint pile in rcuwalk mode. Fail if
|
|
* we meet a managed dentry that would need blocking.
|
|
*/
|
|
static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
|
|
struct inode **inode, unsigned *seqp)
|
|
{
|
|
struct dentry *dentry = path->dentry;
|
|
unsigned int flags = dentry->d_flags;
|
|
|
|
if (likely(!(flags & DCACHE_MANAGED_DENTRY)))
|
|
return true;
|
|
|
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
|
return false;
|
|
|
|
for (;;) {
|
|
/*
|
|
* Don't forget we might have a non-mountpoint managed dentry
|
|
* that wants to block transit.
|
|
*/
|
|
if (unlikely(flags & DCACHE_MANAGE_TRANSIT)) {
|
|
int res = dentry->d_op->d_manage(path, true);
|
|
if (res)
|
|
return res == -EISDIR;
|
|
flags = dentry->d_flags;
|
|
}
|
|
|
|
if (flags & DCACHE_MOUNTED) {
|
|
struct mount *mounted = __lookup_mnt(path->mnt, dentry);
|
|
if (mounted) {
|
|
path->mnt = &mounted->mnt;
|
|
dentry = path->dentry = mounted->mnt.mnt_root;
|
|
nd->flags |= LOOKUP_JUMPED;
|
|
*seqp = read_seqcount_begin(&dentry->d_seq);
|
|
*inode = dentry->d_inode;
|
|
/*
|
|
* We don't need to re-check ->d_seq after this
|
|
* ->d_inode read - there will be an RCU delay
|
|
* between mount hash removal and ->mnt_root
|
|
* becoming unpinned.
|
|
*/
|
|
flags = dentry->d_flags;
|
|
continue;
|
|
}
|
|
if (read_seqretry(&mount_lock, nd->m_seq))
|
|
return false;
|
|
}
|
|
return !(flags & DCACHE_NEED_AUTOMOUNT);
|
|
}
|
|
}
|
|
|
|
static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
|
|
struct path *path, struct inode **inode,
|
|
unsigned int *seqp)
|
|
{
|
|
bool jumped;
|
|
int ret;
|
|
|
|
path->mnt = nd->path.mnt;
|
|
path->dentry = dentry;
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
unsigned int seq = *seqp;
|
|
if (unlikely(!*inode))
|
|
return -ENOENT;
|
|
if (likely(__follow_mount_rcu(nd, path, inode, seqp)))
|
|
return 0;
|
|
if (unlazy_child(nd, dentry, seq))
|
|
return -ECHILD;
|
|
// *path might've been clobbered by __follow_mount_rcu()
|
|
path->mnt = nd->path.mnt;
|
|
path->dentry = dentry;
|
|
}
|
|
ret = traverse_mounts(path, &jumped, &nd->total_link_count, nd->flags);
|
|
if (jumped) {
|
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
|
ret = -EXDEV;
|
|
else
|
|
nd->flags |= LOOKUP_JUMPED;
|
|
}
|
|
if (unlikely(ret)) {
|
|
dput(path->dentry);
|
|
if (path->mnt != nd->path.mnt)
|
|
mntput(path->mnt);
|
|
} else {
|
|
*inode = d_backing_inode(path->dentry);
|
|
*seqp = 0; /* out of RCU mode, so the value doesn't matter */
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* This looks up the name in dcache and possibly revalidates the found dentry.
|
|
* NULL is returned if the dentry does not exist in the cache.
|
|
*/
|
|
static struct dentry *lookup_dcache(const struct qstr *name,
|
|
struct dentry *dir,
|
|
unsigned int flags)
|
|
{
|
|
struct dentry *dentry = d_lookup(dir, name);
|
|
if (dentry) {
|
|
int error = d_revalidate(dentry, flags);
|
|
if (unlikely(error <= 0)) {
|
|
if (!error)
|
|
d_invalidate(dentry);
|
|
dput(dentry);
|
|
return ERR_PTR(error);
|
|
}
|
|
}
|
|
return dentry;
|
|
}
|
|
|
|
/*
|
|
* Parent directory has inode locked exclusive. This is one
|
|
* and only case when ->lookup() gets called on non in-lookup
|
|
* dentries - as the matter of fact, this only gets called
|
|
* when directory is guaranteed to have no in-lookup children
|
|
* at all.
|
|
*/
|
|
static struct dentry *__lookup_hash(const struct qstr *name,
|
|
struct dentry *base, unsigned int flags)
|
|
{
|
|
struct dentry *dentry = lookup_dcache(name, base, flags);
|
|
struct dentry *old;
|
|
struct inode *dir = base->d_inode;
|
|
|
|
if (dentry)
|
|
return dentry;
|
|
|
|
/* Don't create child dentry for a dead directory. */
|
|
if (unlikely(IS_DEADDIR(dir)))
|
|
return ERR_PTR(-ENOENT);
|
|
|
|
dentry = d_alloc(base, name);
|
|
if (unlikely(!dentry))
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
old = dir->i_op->lookup(dir, dentry, flags);
|
|
if (unlikely(old)) {
|
|
dput(dentry);
|
|
dentry = old;
|
|
}
|
|
return dentry;
|
|
}
|
|
|
|
static struct dentry *lookup_fast(struct nameidata *nd,
|
|
struct inode **inode,
|
|
unsigned *seqp)
|
|
{
|
|
struct dentry *dentry, *parent = nd->path.dentry;
|
|
int status = 1;
|
|
|
|
/*
|
|
* Rename seqlock is not required here because in the off chance
|
|
* of a false negative due to a concurrent rename, the caller is
|
|
* going to fall back to non-racy lookup.
|
|
*/
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
unsigned seq;
|
|
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
|
|
if (unlikely(!dentry)) {
|
|
if (!try_to_unlazy(nd))
|
|
return ERR_PTR(-ECHILD);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* This sequence count validates that the inode matches
|
|
* the dentry name information from lookup.
|
|
*/
|
|
*inode = d_backing_inode(dentry);
|
|
if (unlikely(read_seqcount_retry(&dentry->d_seq, seq)))
|
|
return ERR_PTR(-ECHILD);
|
|
|
|
/*
|
|
* This sequence count validates that the parent had no
|
|
* changes while we did the lookup of the dentry above.
|
|
*
|
|
* The memory barrier in read_seqcount_begin of child is
|
|
* enough, we can use __read_seqcount_retry here.
|
|
*/
|
|
if (unlikely(__read_seqcount_retry(&parent->d_seq, nd->seq)))
|
|
return ERR_PTR(-ECHILD);
|
|
|
|
*seqp = seq;
|
|
status = d_revalidate(dentry, nd->flags);
|
|
if (likely(status > 0))
|
|
return dentry;
|
|
if (unlazy_child(nd, dentry, seq))
|
|
return ERR_PTR(-ECHILD);
|
|
if (unlikely(status == -ECHILD))
|
|
/* we'd been told to redo it in non-rcu mode */
|
|
status = d_revalidate(dentry, nd->flags);
|
|
} else {
|
|
dentry = __d_lookup(parent, &nd->last);
|
|
if (unlikely(!dentry))
|
|
return NULL;
|
|
status = d_revalidate(dentry, nd->flags);
|
|
}
|
|
if (unlikely(status <= 0)) {
|
|
if (!status)
|
|
d_invalidate(dentry);
|
|
dput(dentry);
|
|
return ERR_PTR(status);
|
|
}
|
|
return dentry;
|
|
}
|
|
|
|
/* Fast lookup failed, do it the slow way */
|
|
static struct dentry *__lookup_slow(const struct qstr *name,
|
|
struct dentry *dir,
|
|
unsigned int flags)
|
|
{
|
|
struct dentry *dentry, *old;
|
|
struct inode *inode = dir->d_inode;
|
|
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
|
|
|
|
/* Don't go there if it's already dead */
|
|
if (unlikely(IS_DEADDIR(inode)))
|
|
return ERR_PTR(-ENOENT);
|
|
again:
|
|
dentry = d_alloc_parallel(dir, name, &wq);
|
|
if (IS_ERR(dentry))
|
|
return dentry;
|
|
if (unlikely(!d_in_lookup(dentry))) {
|
|
int error = d_revalidate(dentry, flags);
|
|
if (unlikely(error <= 0)) {
|
|
if (!error) {
|
|
d_invalidate(dentry);
|
|
dput(dentry);
|
|
goto again;
|
|
}
|
|
dput(dentry);
|
|
dentry = ERR_PTR(error);
|
|
}
|
|
} else {
|
|
old = inode->i_op->lookup(inode, dentry, flags);
|
|
d_lookup_done(dentry);
|
|
if (unlikely(old)) {
|
|
dput(dentry);
|
|
dentry = old;
|
|
}
|
|
}
|
|
return dentry;
|
|
}
|
|
|
|
static struct dentry *lookup_slow(const struct qstr *name,
|
|
struct dentry *dir,
|
|
unsigned int flags)
|
|
{
|
|
struct inode *inode = dir->d_inode;
|
|
struct dentry *res;
|
|
inode_lock_shared(inode);
|
|
res = __lookup_slow(name, dir, flags);
|
|
inode_unlock_shared(inode);
|
|
return res;
|
|
}
|
|
|
|
static inline int may_lookup(struct nameidata *nd)
|
|
{
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
|
|
if (err != -ECHILD || !try_to_unlazy(nd))
|
|
return err;
|
|
}
|
|
return inode_permission(nd->inode, MAY_EXEC);
|
|
}
|
|
|
|
static int reserve_stack(struct nameidata *nd, struct path *link, unsigned seq)
|
|
{
|
|
if (unlikely(nd->total_link_count++ >= MAXSYMLINKS))
|
|
return -ELOOP;
|
|
|
|
if (likely(nd->depth != EMBEDDED_LEVELS))
|
|
return 0;
|
|
if (likely(nd->stack != nd->internal))
|
|
return 0;
|
|
if (likely(nd_alloc_stack(nd)))
|
|
return 0;
|
|
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
// we need to grab link before we do unlazy. And we can't skip
|
|
// unlazy even if we fail to grab the link - cleanup needs it
|
|
bool grabbed_link = legitimize_path(nd, link, seq);
|
|
|
|
if (!try_to_unlazy(nd) != 0 || !grabbed_link)
|
|
return -ECHILD;
|
|
|
|
if (nd_alloc_stack(nd))
|
|
return 0;
|
|
}
|
|
return -ENOMEM;
|
|
}
|
|
|
|
enum {WALK_TRAILING = 1, WALK_MORE = 2, WALK_NOFOLLOW = 4};
|
|
|
|
static const char *pick_link(struct nameidata *nd, struct path *link,
|
|
struct inode *inode, unsigned seq, int flags)
|
|
{
|
|
struct saved *last;
|
|
const char *res;
|
|
int error = reserve_stack(nd, link, seq);
|
|
|
|
if (unlikely(error)) {
|
|
if (!(nd->flags & LOOKUP_RCU))
|
|
path_put(link);
|
|
return ERR_PTR(error);
|
|
}
|
|
last = nd->stack + nd->depth++;
|
|
last->link = *link;
|
|
clear_delayed_call(&last->done);
|
|
last->seq = seq;
|
|
|
|
if (flags & WALK_TRAILING) {
|
|
error = may_follow_link(nd, inode);
|
|
if (unlikely(error))
|
|
return ERR_PTR(error);
|
|
}
|
|
|
|
if (unlikely(nd->flags & LOOKUP_NO_SYMLINKS) ||
|
|
unlikely(link->mnt->mnt_flags & MNT_NOSYMFOLLOW))
|
|
return ERR_PTR(-ELOOP);
|
|
|
|
if (!(nd->flags & LOOKUP_RCU)) {
|
|
touch_atime(&last->link);
|
|
cond_resched();
|
|
} else if (atime_needs_update(&last->link, inode)) {
|
|
if (!try_to_unlazy(nd))
|
|
return ERR_PTR(-ECHILD);
|
|
touch_atime(&last->link);
|
|
}
|
|
|
|
error = security_inode_follow_link(link->dentry, inode,
|
|
nd->flags & LOOKUP_RCU);
|
|
if (unlikely(error))
|
|
return ERR_PTR(error);
|
|
|
|
res = READ_ONCE(inode->i_link);
|
|
if (!res) {
|
|
const char * (*get)(struct dentry *, struct inode *,
|
|
struct delayed_call *);
|
|
get = inode->i_op->get_link;
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
res = get(NULL, inode, &last->done);
|
|
if (res == ERR_PTR(-ECHILD) && try_to_unlazy(nd))
|
|
res = get(link->dentry, inode, &last->done);
|
|
} else {
|
|
res = get(link->dentry, inode, &last->done);
|
|
}
|
|
if (!res)
|
|
goto all_done;
|
|
if (IS_ERR(res))
|
|
return res;
|
|
}
|
|
if (*res == '/') {
|
|
error = nd_jump_root(nd);
|
|
if (unlikely(error))
|
|
return ERR_PTR(error);
|
|
while (unlikely(*++res == '/'))
|
|
;
|
|
}
|
|
if (*res)
|
|
return res;
|
|
all_done: // pure jump
|
|
put_link(nd);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Do we need to follow links? We _really_ want to be able
|
|
* to do this check without having to look at inode->i_op,
|
|
* so we keep a cache of "no, this doesn't need follow_link"
|
|
* for the common case.
|
|
*/
|
|
static const char *step_into(struct nameidata *nd, int flags,
|
|
struct dentry *dentry, struct inode *inode, unsigned seq)
|
|
{
|
|
struct path path;
|
|
int err = handle_mounts(nd, dentry, &path, &inode, &seq);
|
|
|
|
if (err < 0)
|
|
return ERR_PTR(err);
|
|
if (likely(!d_is_symlink(path.dentry)) ||
|
|
((flags & WALK_TRAILING) && !(nd->flags & LOOKUP_FOLLOW)) ||
|
|
(flags & WALK_NOFOLLOW)) {
|
|
/* not a symlink or should not follow */
|
|
if (!(nd->flags & LOOKUP_RCU)) {
|
|
dput(nd->path.dentry);
|
|
if (nd->path.mnt != path.mnt)
|
|
mntput(nd->path.mnt);
|
|
}
|
|
nd->path = path;
|
|
nd->inode = inode;
|
|
nd->seq = seq;
|
|
return NULL;
|
|
}
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
/* make sure that d_is_symlink above matches inode */
|
|
if (read_seqcount_retry(&path.dentry->d_seq, seq))
|
|
return ERR_PTR(-ECHILD);
|
|
} else {
|
|
if (path.mnt == nd->path.mnt)
|
|
mntget(path.mnt);
|
|
}
|
|
return pick_link(nd, &path, inode, seq, flags);
|
|
}
|
|
|
|
static struct dentry *follow_dotdot_rcu(struct nameidata *nd,
|
|
struct inode **inodep,
|
|
unsigned *seqp)
|
|
{
|
|
struct dentry *parent, *old;
|
|
|
|
if (path_equal(&nd->path, &nd->root))
|
|
goto in_root;
|
|
if (unlikely(nd->path.dentry == nd->path.mnt->mnt_root)) {
|
|
struct path path;
|
|
unsigned seq;
|
|
if (!choose_mountpoint_rcu(real_mount(nd->path.mnt),
|
|
&nd->root, &path, &seq))
|
|
goto in_root;
|
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
|
return ERR_PTR(-ECHILD);
|
|
nd->path = path;
|
|
nd->inode = path.dentry->d_inode;
|
|
nd->seq = seq;
|
|
if (unlikely(read_seqretry(&mount_lock, nd->m_seq)))
|
|
return ERR_PTR(-ECHILD);
|
|
/* we know that mountpoint was pinned */
|
|
}
|
|
old = nd->path.dentry;
|
|
parent = old->d_parent;
|
|
*inodep = parent->d_inode;
|
|
*seqp = read_seqcount_begin(&parent->d_seq);
|
|
if (unlikely(read_seqcount_retry(&old->d_seq, nd->seq)))
|
|
return ERR_PTR(-ECHILD);
|
|
if (unlikely(!path_connected(nd->path.mnt, parent)))
|
|
return ERR_PTR(-ECHILD);
|
|
return parent;
|
|
in_root:
|
|
if (unlikely(read_seqretry(&mount_lock, nd->m_seq)))
|
|
return ERR_PTR(-ECHILD);
|
|
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
|
return ERR_PTR(-ECHILD);
|
|
return NULL;
|
|
}
|
|
|
|
static struct dentry *follow_dotdot(struct nameidata *nd,
|
|
struct inode **inodep,
|
|
unsigned *seqp)
|
|
{
|
|
struct dentry *parent;
|
|
|
|
if (path_equal(&nd->path, &nd->root))
|
|
goto in_root;
|
|
if (unlikely(nd->path.dentry == nd->path.mnt->mnt_root)) {
|
|
struct path path;
|
|
|
|
if (!choose_mountpoint(real_mount(nd->path.mnt),
|
|
&nd->root, &path))
|
|
goto in_root;
|
|
path_put(&nd->path);
|
|
nd->path = path;
|
|
nd->inode = path.dentry->d_inode;
|
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
|
return ERR_PTR(-EXDEV);
|
|
}
|
|
/* rare case of legitimate dget_parent()... */
|
|
parent = dget_parent(nd->path.dentry);
|
|
if (unlikely(!path_connected(nd->path.mnt, parent))) {
|
|
dput(parent);
|
|
return ERR_PTR(-ENOENT);
|
|
}
|
|
*seqp = 0;
|
|
*inodep = parent->d_inode;
|
|
return parent;
|
|
|
|
in_root:
|
|
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
|
return ERR_PTR(-EXDEV);
|
|
dget(nd->path.dentry);
|
|
return NULL;
|
|
}
|
|
|
|
static const char *handle_dots(struct nameidata *nd, int type)
|
|
{
|
|
if (type == LAST_DOTDOT) {
|
|
const char *error = NULL;
|
|
struct dentry *parent;
|
|
struct inode *inode;
|
|
unsigned seq;
|
|
|
|
if (!nd->root.mnt) {
|
|
error = ERR_PTR(set_root(nd));
|
|
if (error)
|
|
return error;
|
|
}
|
|
if (nd->flags & LOOKUP_RCU)
|
|
parent = follow_dotdot_rcu(nd, &inode, &seq);
|
|
else
|
|
parent = follow_dotdot(nd, &inode, &seq);
|
|
if (IS_ERR(parent))
|
|
return ERR_CAST(parent);
|
|
if (unlikely(!parent))
|
|
error = step_into(nd, WALK_NOFOLLOW,
|
|
nd->path.dentry, nd->inode, nd->seq);
|
|
else
|
|
error = step_into(nd, WALK_NOFOLLOW,
|
|
parent, inode, seq);
|
|
if (unlikely(error))
|
|
return error;
|
|
|
|
if (unlikely(nd->flags & LOOKUP_IS_SCOPED)) {
|
|
/*
|
|
* If there was a racing rename or mount along our
|
|
* path, then we can't be sure that ".." hasn't jumped
|
|
* above nd->root (and so userspace should retry or use
|
|
* some fallback).
|
|
*/
|
|
smp_rmb();
|
|
if (unlikely(__read_seqcount_retry(&mount_lock.seqcount, nd->m_seq)))
|
|
return ERR_PTR(-EAGAIN);
|
|
if (unlikely(__read_seqcount_retry(&rename_lock.seqcount, nd->r_seq)))
|
|
return ERR_PTR(-EAGAIN);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static const char *walk_component(struct nameidata *nd, int flags)
|
|
{
|
|
struct dentry *dentry;
|
|
struct inode *inode;
|
|
unsigned seq;
|
|
/*
|
|
* "." and ".." are special - ".." especially so because it has
|
|
* to be able to know about the current root directory and
|
|
* parent relationships.
|
|
*/
|
|
if (unlikely(nd->last_type != LAST_NORM)) {
|
|
if (!(flags & WALK_MORE) && nd->depth)
|
|
put_link(nd);
|
|
return handle_dots(nd, nd->last_type);
|
|
}
|
|
dentry = lookup_fast(nd, &inode, &seq);
|
|
if (IS_ERR(dentry))
|
|
return ERR_CAST(dentry);
|
|
if (unlikely(!dentry)) {
|
|
dentry = lookup_slow(&nd->last, nd->path.dentry, nd->flags);
|
|
if (IS_ERR(dentry))
|
|
return ERR_CAST(dentry);
|
|
}
|
|
if (!(flags & WALK_MORE) && nd->depth)
|
|
put_link(nd);
|
|
return step_into(nd, flags, dentry, inode, seq);
|
|
}
|
|
|
|
/*
|
|
* We can do the critical dentry name comparison and hashing
|
|
* operations one word at a time, but we are limited to:
|
|
*
|
|
* - Architectures with fast unaligned word accesses. We could
|
|
* do a "get_unaligned()" if this helps and is sufficiently
|
|
* fast.
|
|
*
|
|
* - non-CONFIG_DEBUG_PAGEALLOC configurations (so that we
|
|
* do not trap on the (extremely unlikely) case of a page
|
|
* crossing operation.
|
|
*
|
|
* - Furthermore, we need an efficient 64-bit compile for the
|
|
* 64-bit case in order to generate the "number of bytes in
|
|
* the final mask". Again, that could be replaced with a
|
|
* efficient population count instruction or similar.
|
|
*/
|
|
#ifdef CONFIG_DCACHE_WORD_ACCESS
|
|
|
|
#include <asm/word-at-a-time.h>
|
|
|
|
#ifdef HASH_MIX
|
|
|
|
/* Architecture provides HASH_MIX and fold_hash() in <asm/hash.h> */
|
|
|
|
#elif defined(CONFIG_64BIT)
|
|
/*
|
|
* Register pressure in the mixing function is an issue, particularly
|
|
* on 32-bit x86, but almost any function requires one state value and
|
|
* one temporary. Instead, use a function designed for two state values
|
|
* and no temporaries.
|
|
*
|
|
* This function cannot create a collision in only two iterations, so
|
|
* we have two iterations to achieve avalanche. In those two iterations,
|
|
* we have six layers of mixing, which is enough to spread one bit's
|
|
* influence out to 2^6 = 64 state bits.
|
|
*
|
|
* Rotate constants are scored by considering either 64 one-bit input
|
|
* deltas or 64*63/2 = 2016 two-bit input deltas, and finding the
|
|
* probability of that delta causing a change to each of the 128 output
|
|
* bits, using a sample of random initial states.
|
|
*
|
|
* The Shannon entropy of the computed probabilities is then summed
|
|
* to produce a score. Ideally, any input change has a 50% chance of
|
|
* toggling any given output bit.
|
|
*
|
|
* Mixing scores (in bits) for (12,45):
|
|
* Input delta: 1-bit 2-bit
|
|
* 1 round: 713.3 42542.6
|
|
* 2 rounds: 2753.7 140389.8
|
|
* 3 rounds: 5954.1 233458.2
|
|
* 4 rounds: 7862.6 256672.2
|
|
* Perfect: 8192 258048
|
|
* (64*128) (64*63/2 * 128)
|
|
*/
|
|
#define HASH_MIX(x, y, a) \
|
|
( x ^= (a), \
|
|
y ^= x, x = rol64(x,12),\
|
|
x += y, y = rol64(y,45),\
|
|
y *= 9 )
|
|
|
|
/*
|
|
* Fold two longs into one 32-bit hash value. This must be fast, but
|
|
* latency isn't quite as critical, as there is a fair bit of additional
|
|
* work done before the hash value is used.
|
|
*/
|
|
static inline unsigned int fold_hash(unsigned long x, unsigned long y)
|
|
{
|
|
y ^= x * GOLDEN_RATIO_64;
|
|
y *= GOLDEN_RATIO_64;
|
|
return y >> 32;
|
|
}
|
|
|
|
#else /* 32-bit case */
|
|
|
|
/*
|
|
* Mixing scores (in bits) for (7,20):
|
|
* Input delta: 1-bit 2-bit
|
|
* 1 round: 330.3 9201.6
|
|
* 2 rounds: 1246.4 25475.4
|
|
* 3 rounds: 1907.1 31295.1
|
|
* 4 rounds: 2042.3 31718.6
|
|
* Perfect: 2048 31744
|
|
* (32*64) (32*31/2 * 64)
|
|
*/
|
|
#define HASH_MIX(x, y, a) \
|
|
( x ^= (a), \
|
|
y ^= x, x = rol32(x, 7),\
|
|
x += y, y = rol32(y,20),\
|
|
y *= 9 )
|
|
|
|
static inline unsigned int fold_hash(unsigned long x, unsigned long y)
|
|
{
|
|
/* Use arch-optimized multiply if one exists */
|
|
return __hash_32(y ^ __hash_32(x));
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Return the hash of a string of known length. This is carfully
|
|
* designed to match hash_name(), which is the more critical function.
|
|
* In particular, we must end by hashing a final word containing 0..7
|
|
* payload bytes, to match the way that hash_name() iterates until it
|
|
* finds the delimiter after the name.
|
|
*/
|
|
unsigned int full_name_hash(const void *salt, const char *name, unsigned int len)
|
|
{
|
|
unsigned long a, x = 0, y = (unsigned long)salt;
|
|
|
|
for (;;) {
|
|
if (!len)
|
|
goto done;
|
|
a = load_unaligned_zeropad(name);
|
|
if (len < sizeof(unsigned long))
|
|
break;
|
|
HASH_MIX(x, y, a);
|
|
name += sizeof(unsigned long);
|
|
len -= sizeof(unsigned long);
|
|
}
|
|
x ^= a & bytemask_from_count(len);
|
|
done:
|
|
return fold_hash(x, y);
|
|
}
|
|
EXPORT_SYMBOL(full_name_hash);
|
|
|
|
/* Return the "hash_len" (hash and length) of a null-terminated string */
|
|
u64 hashlen_string(const void *salt, const char *name)
|
|
{
|
|
unsigned long a = 0, x = 0, y = (unsigned long)salt;
|
|
unsigned long adata, mask, len;
|
|
const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
|
|
|
|
len = 0;
|
|
goto inside;
|
|
|
|
do {
|
|
HASH_MIX(x, y, a);
|
|
len += sizeof(unsigned long);
|
|
inside:
|
|
a = load_unaligned_zeropad(name+len);
|
|
} while (!has_zero(a, &adata, &constants));
|
|
|
|
adata = prep_zero_mask(a, adata, &constants);
|
|
mask = create_zero_mask(adata);
|
|
x ^= a & zero_bytemask(mask);
|
|
|
|
return hashlen_create(fold_hash(x, y), len + find_zero(mask));
|
|
}
|
|
EXPORT_SYMBOL(hashlen_string);
|
|
|
|
/*
|
|
* Calculate the length and hash of the path component, and
|
|
* return the "hash_len" as the result.
|
|
*/
|
|
static inline u64 hash_name(const void *salt, const char *name)
|
|
{
|
|
unsigned long a = 0, b, x = 0, y = (unsigned long)salt;
|
|
unsigned long adata, bdata, mask, len;
|
|
const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
|
|
|
|
len = 0;
|
|
goto inside;
|
|
|
|
do {
|
|
HASH_MIX(x, y, a);
|
|
len += sizeof(unsigned long);
|
|
inside:
|
|
a = load_unaligned_zeropad(name+len);
|
|
b = a ^ REPEAT_BYTE('/');
|
|
} while (!(has_zero(a, &adata, &constants) | has_zero(b, &bdata, &constants)));
|
|
|
|
adata = prep_zero_mask(a, adata, &constants);
|
|
bdata = prep_zero_mask(b, bdata, &constants);
|
|
mask = create_zero_mask(adata | bdata);
|
|
x ^= a & zero_bytemask(mask);
|
|
|
|
return hashlen_create(fold_hash(x, y), len + find_zero(mask));
|
|
}
|
|
|
|
#else /* !CONFIG_DCACHE_WORD_ACCESS: Slow, byte-at-a-time version */
|
|
|
|
/* Return the hash of a string of known length */
|
|
unsigned int full_name_hash(const void *salt, const char *name, unsigned int len)
|
|
{
|
|
unsigned long hash = init_name_hash(salt);
|
|
while (len--)
|
|
hash = partial_name_hash((unsigned char)*name++, hash);
|
|
return end_name_hash(hash);
|
|
}
|
|
EXPORT_SYMBOL(full_name_hash);
|
|
|
|
/* Return the "hash_len" (hash and length) of a null-terminated string */
|
|
u64 hashlen_string(const void *salt, const char *name)
|
|
{
|
|
unsigned long hash = init_name_hash(salt);
|
|
unsigned long len = 0, c;
|
|
|
|
c = (unsigned char)*name;
|
|
while (c) {
|
|
len++;
|
|
hash = partial_name_hash(c, hash);
|
|
c = (unsigned char)name[len];
|
|
}
|
|
return hashlen_create(end_name_hash(hash), len);
|
|
}
|
|
EXPORT_SYMBOL(hashlen_string);
|
|
|
|
/*
|
|
* We know there's a real path component here of at least
|
|
* one character.
|
|
*/
|
|
static inline u64 hash_name(const void *salt, const char *name)
|
|
{
|
|
unsigned long hash = init_name_hash(salt);
|
|
unsigned long len = 0, c;
|
|
|
|
c = (unsigned char)*name;
|
|
do {
|
|
len++;
|
|
hash = partial_name_hash(c, hash);
|
|
c = (unsigned char)name[len];
|
|
} while (c && c != '/');
|
|
return hashlen_create(end_name_hash(hash), len);
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Name resolution.
|
|
* This is the basic name resolution function, turning a pathname into
|
|
* the final dentry. We expect 'base' to be positive and a directory.
|
|
*
|
|
* Returns 0 and nd will have valid dentry and mnt on success.
|
|
* Returns error and drops reference to input namei data on failure.
|
|
*/
|
|
static int link_path_walk(const char *name, struct nameidata *nd)
|
|
{
|
|
int depth = 0; // depth <= nd->depth
|
|
int err;
|
|
|
|
nd->last_type = LAST_ROOT;
|
|
nd->flags |= LOOKUP_PARENT;
|
|
if (IS_ERR(name))
|
|
return PTR_ERR(name);
|
|
while (*name=='/')
|
|
name++;
|
|
if (!*name)
|
|
return 0;
|
|
|
|
/* At this point we know we have a real path component. */
|
|
for(;;) {
|
|
const char *link;
|
|
u64 hash_len;
|
|
int type;
|
|
|
|
err = may_lookup(nd);
|
|
if (err)
|
|
return err;
|
|
|
|
hash_len = hash_name(nd->path.dentry, name);
|
|
|
|
type = LAST_NORM;
|
|
if (name[0] == '.') switch (hashlen_len(hash_len)) {
|
|
case 2:
|
|
if (name[1] == '.') {
|
|
type = LAST_DOTDOT;
|
|
nd->flags |= LOOKUP_JUMPED;
|
|
}
|
|
break;
|
|
case 1:
|
|
type = LAST_DOT;
|
|
}
|
|
if (likely(type == LAST_NORM)) {
|
|
struct dentry *parent = nd->path.dentry;
|
|
nd->flags &= ~LOOKUP_JUMPED;
|
|
if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
|
|
struct qstr this = { { .hash_len = hash_len }, .name = name };
|
|
err = parent->d_op->d_hash(parent, &this);
|
|
if (err < 0)
|
|
return err;
|
|
hash_len = this.hash_len;
|
|
name = this.name;
|
|
}
|
|
}
|
|
|
|
nd->last.hash_len = hash_len;
|
|
nd->last.name = name;
|
|
nd->last_type = type;
|
|
|
|
name += hashlen_len(hash_len);
|
|
if (!*name)
|
|
goto OK;
|
|
/*
|
|
* If it wasn't NUL, we know it was '/'. Skip that
|
|
* slash, and continue until no more slashes.
|
|
*/
|
|
do {
|
|
name++;
|
|
} while (unlikely(*name == '/'));
|
|
if (unlikely(!*name)) {
|
|
OK:
|
|
/* pathname or trailing symlink, done */
|
|
if (!depth) {
|
|
nd->dir_uid = nd->inode->i_uid;
|
|
nd->dir_mode = nd->inode->i_mode;
|
|
nd->flags &= ~LOOKUP_PARENT;
|
|
return 0;
|
|
}
|
|
/* last component of nested symlink */
|
|
name = nd->stack[--depth].name;
|
|
link = walk_component(nd, 0);
|
|
} else {
|
|
/* not the last component */
|
|
link = walk_component(nd, WALK_MORE);
|
|
}
|
|
if (unlikely(link)) {
|
|
if (IS_ERR(link))
|
|
return PTR_ERR(link);
|
|
/* a symlink to follow */
|
|
nd->stack[depth++].name = name;
|
|
name = link;
|
|
continue;
|
|
}
|
|
if (unlikely(!d_can_lookup(nd->path.dentry))) {
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
if (!try_to_unlazy(nd))
|
|
return -ECHILD;
|
|
}
|
|
return -ENOTDIR;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* must be paired with terminate_walk() */
|
|
static const char *path_init(struct nameidata *nd, unsigned flags)
|
|
{
|
|
int error;
|
|
const char *s = nd->name->name;
|
|
|
|
if (!*s)
|
|
flags &= ~LOOKUP_RCU;
|
|
if (flags & LOOKUP_RCU)
|
|
rcu_read_lock();
|
|
|
|
nd->flags = flags | LOOKUP_JUMPED;
|
|
nd->depth = 0;
|
|
|
|
nd->m_seq = __read_seqcount_begin(&mount_lock.seqcount);
|
|
nd->r_seq = __read_seqcount_begin(&rename_lock.seqcount);
|
|
smp_rmb();
|
|
|
|
if (flags & LOOKUP_ROOT) {
|
|
struct dentry *root = nd->root.dentry;
|
|
struct inode *inode = root->d_inode;
|
|
if (*s && unlikely(!d_can_lookup(root)))
|
|
return ERR_PTR(-ENOTDIR);
|
|
nd->path = nd->root;
|
|
nd->inode = inode;
|
|
if (flags & LOOKUP_RCU) {
|
|
nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
|
|
nd->root_seq = nd->seq;
|
|
} else {
|
|
path_get(&nd->path);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
nd->root.mnt = NULL;
|
|
nd->path.mnt = NULL;
|
|
nd->path.dentry = NULL;
|
|
|
|
/* Absolute pathname -- fetch the root (LOOKUP_IN_ROOT uses nd->dfd). */
|
|
if (*s == '/' && !(flags & LOOKUP_IN_ROOT)) {
|
|
error = nd_jump_root(nd);
|
|
if (unlikely(error))
|
|
return ERR_PTR(error);
|
|
return s;
|
|
}
|
|
|
|
/* Relative pathname -- get the starting-point it is relative to. */
|
|
if (nd->dfd == AT_FDCWD) {
|
|
if (flags & LOOKUP_RCU) {
|
|
struct fs_struct *fs = current->fs;
|
|
unsigned seq;
|
|
|
|
do {
|
|
seq = read_seqcount_begin(&fs->seq);
|
|
nd->path = fs->pwd;
|
|
nd->inode = nd->path.dentry->d_inode;
|
|
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
|
|
} while (read_seqcount_retry(&fs->seq, seq));
|
|
} else {
|
|
get_fs_pwd(current->fs, &nd->path);
|
|
nd->inode = nd->path.dentry->d_inode;
|
|
}
|
|
} else {
|
|
/* Caller must check execute permissions on the starting path component */
|
|
struct fd f = fdget_raw(nd->dfd);
|
|
struct dentry *dentry;
|
|
|
|
if (!f.file)
|
|
return ERR_PTR(-EBADF);
|
|
|
|
dentry = f.file->f_path.dentry;
|
|
|
|
if (*s && unlikely(!d_can_lookup(dentry))) {
|
|
fdput(f);
|
|
return ERR_PTR(-ENOTDIR);
|
|
}
|
|
|
|
nd->path = f.file->f_path;
|
|
if (flags & LOOKUP_RCU) {
|
|
nd->inode = nd->path.dentry->d_inode;
|
|
nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
|
|
} else {
|
|
path_get(&nd->path);
|
|
nd->inode = nd->path.dentry->d_inode;
|
|
}
|
|
fdput(f);
|
|
}
|
|
|
|
/* For scoped-lookups we need to set the root to the dirfd as well. */
|
|
if (flags & LOOKUP_IS_SCOPED) {
|
|
nd->root = nd->path;
|
|
if (flags & LOOKUP_RCU) {
|
|
nd->root_seq = nd->seq;
|
|
} else {
|
|
path_get(&nd->root);
|
|
nd->flags |= LOOKUP_ROOT_GRABBED;
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
|
|
static inline const char *lookup_last(struct nameidata *nd)
|
|
{
|
|
if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
|
|
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
|
|
|
|
return walk_component(nd, WALK_TRAILING);
|
|
}
|
|
|
|
static int handle_lookup_down(struct nameidata *nd)
|
|
{
|
|
if (!(nd->flags & LOOKUP_RCU))
|
|
dget(nd->path.dentry);
|
|
return PTR_ERR(step_into(nd, WALK_NOFOLLOW,
|
|
nd->path.dentry, nd->inode, nd->seq));
|
|
}
|
|
|
|
/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
|
|
static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path)
|
|
{
|
|
const char *s = path_init(nd, flags);
|
|
int err;
|
|
|
|
if (unlikely(flags & LOOKUP_DOWN) && !IS_ERR(s)) {
|
|
err = handle_lookup_down(nd);
|
|
if (unlikely(err < 0))
|
|
s = ERR_PTR(err);
|
|
}
|
|
|
|
while (!(err = link_path_walk(s, nd)) &&
|
|
(s = lookup_last(nd)) != NULL)
|
|
;
|
|
if (!err && unlikely(nd->flags & LOOKUP_MOUNTPOINT)) {
|
|
err = handle_lookup_down(nd);
|
|
nd->flags &= ~LOOKUP_JUMPED; // no d_weak_revalidate(), please...
|
|
}
|
|
if (!err)
|
|
err = complete_walk(nd);
|
|
|
|
if (!err && nd->flags & LOOKUP_DIRECTORY)
|
|
if (!d_can_lookup(nd->path.dentry))
|
|
err = -ENOTDIR;
|
|
if (!err) {
|
|
*path = nd->path;
|
|
nd->path.mnt = NULL;
|
|
nd->path.dentry = NULL;
|
|
}
|
|
terminate_walk(nd);
|
|
return err;
|
|
}
|
|
|
|
int filename_lookup(int dfd, struct filename *name, unsigned flags,
|
|
struct path *path, struct path *root)
|
|
{
|
|
int retval;
|
|
struct nameidata nd;
|
|
if (IS_ERR(name))
|
|
return PTR_ERR(name);
|
|
if (unlikely(root)) {
|
|
nd.root = *root;
|
|
flags |= LOOKUP_ROOT;
|
|
}
|
|
set_nameidata(&nd, dfd, name);
|
|
retval = path_lookupat(&nd, flags | LOOKUP_RCU, path);
|
|
if (unlikely(retval == -ECHILD))
|
|
retval = path_lookupat(&nd, flags, path);
|
|
if (unlikely(retval == -ESTALE))
|
|
retval = path_lookupat(&nd, flags | LOOKUP_REVAL, path);
|
|
|
|
if (likely(!retval))
|
|
audit_inode(name, path->dentry,
|
|
flags & LOOKUP_MOUNTPOINT ? AUDIT_INODE_NOEVAL : 0);
|
|
restore_nameidata();
|
|
putname(name);
|
|
return retval;
|
|
}
|
|
|
|
/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
|
|
static int path_parentat(struct nameidata *nd, unsigned flags,
|
|
struct path *parent)
|
|
{
|
|
const char *s = path_init(nd, flags);
|
|
int err = link_path_walk(s, nd);
|
|
if (!err)
|
|
err = complete_walk(nd);
|
|
if (!err) {
|
|
*parent = nd->path;
|
|
nd->path.mnt = NULL;
|
|
nd->path.dentry = NULL;
|
|
}
|
|
terminate_walk(nd);
|
|
return err;
|
|
}
|
|
|
|
static struct filename *filename_parentat(int dfd, struct filename *name,
|
|
unsigned int flags, struct path *parent,
|
|
struct qstr *last, int *type)
|
|
{
|
|
int retval;
|
|
struct nameidata nd;
|
|
|
|
if (IS_ERR(name))
|
|
return name;
|
|
set_nameidata(&nd, dfd, name);
|
|
retval = path_parentat(&nd, flags | LOOKUP_RCU, parent);
|
|
if (unlikely(retval == -ECHILD))
|
|
retval = path_parentat(&nd, flags, parent);
|
|
if (unlikely(retval == -ESTALE))
|
|
retval = path_parentat(&nd, flags | LOOKUP_REVAL, parent);
|
|
if (likely(!retval)) {
|
|
*last = nd.last;
|
|
*type = nd.last_type;
|
|
audit_inode(name, parent->dentry, AUDIT_INODE_PARENT);
|
|
} else {
|
|
putname(name);
|
|
name = ERR_PTR(retval);
|
|
}
|
|
restore_nameidata();
|
|
return name;
|
|
}
|
|
|
|
/* does lookup, returns the object with parent locked */
|
|
struct dentry *kern_path_locked(const char *name, struct path *path)
|
|
{
|
|
struct filename *filename;
|
|
struct dentry *d;
|
|
struct qstr last;
|
|
int type;
|
|
|
|
filename = filename_parentat(AT_FDCWD, getname_kernel(name), 0, path,
|
|
&last, &type);
|
|
if (IS_ERR(filename))
|
|
return ERR_CAST(filename);
|
|
if (unlikely(type != LAST_NORM)) {
|
|
path_put(path);
|
|
putname(filename);
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
|
|
d = __lookup_hash(&last, path->dentry, 0);
|
|
if (IS_ERR(d)) {
|
|
inode_unlock(path->dentry->d_inode);
|
|
path_put(path);
|
|
}
|
|
putname(filename);
|
|
return d;
|
|
}
|
|
|
|
int kern_path(const char *name, unsigned int flags, struct path *path)
|
|
{
|
|
return filename_lookup(AT_FDCWD, getname_kernel(name),
|
|
flags, path, NULL);
|
|
}
|
|
EXPORT_SYMBOL(kern_path);
|
|
|
|
/**
|
|
* vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair
|
|
* @dentry: pointer to dentry of the base directory
|
|
* @mnt: pointer to vfs mount of the base directory
|
|
* @name: pointer to file name
|
|
* @flags: lookup flags
|
|
* @path: pointer to struct path to fill
|
|
*/
|
|
int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
|
|
const char *name, unsigned int flags,
|
|
struct path *path)
|
|
{
|
|
struct path root = {.mnt = mnt, .dentry = dentry};
|
|
/* the first argument of filename_lookup() is ignored with root */
|
|
return filename_lookup(AT_FDCWD, getname_kernel(name),
|
|
flags , path, &root);
|
|
}
|
|
EXPORT_SYMBOL(vfs_path_lookup);
|
|
|
|
static int lookup_one_len_common(const char *name, struct dentry *base,
|
|
int len, struct qstr *this)
|
|
{
|
|
this->name = name;
|
|
this->len = len;
|
|
this->hash = full_name_hash(base, name, len);
|
|
if (!len)
|
|
return -EACCES;
|
|
|
|
if (unlikely(name[0] == '.')) {
|
|
if (len < 2 || (len == 2 && name[1] == '.'))
|
|
return -EACCES;
|
|
}
|
|
|
|
while (len--) {
|
|
unsigned int c = *(const unsigned char *)name++;
|
|
if (c == '/' || c == '\0')
|
|
return -EACCES;
|
|
}
|
|
/*
|
|
* See if the low-level filesystem might want
|
|
* to use its own hash..
|
|
*/
|
|
if (base->d_flags & DCACHE_OP_HASH) {
|
|
int err = base->d_op->d_hash(base, this);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return inode_permission(base->d_inode, MAY_EXEC);
|
|
}
|
|
|
|
/**
|
|
* try_lookup_one_len - filesystem helper to lookup single pathname component
|
|
* @name: pathname component to lookup
|
|
* @base: base directory to lookup from
|
|
* @len: maximum length @len should be interpreted to
|
|
*
|
|
* Look up a dentry by name in the dcache, returning NULL if it does not
|
|
* currently exist. The function does not try to create a dentry.
|
|
*
|
|
* Note that this routine is purely a helper for filesystem usage and should
|
|
* not be called by generic code.
|
|
*
|
|
* The caller must hold base->i_mutex.
|
|
*/
|
|
struct dentry *try_lookup_one_len(const char *name, struct dentry *base, int len)
|
|
{
|
|
struct qstr this;
|
|
int err;
|
|
|
|
WARN_ON_ONCE(!inode_is_locked(base->d_inode));
|
|
|
|
err = lookup_one_len_common(name, base, len, &this);
|
|
if (err)
|
|
return ERR_PTR(err);
|
|
|
|
return lookup_dcache(&this, base, 0);
|
|
}
|
|
EXPORT_SYMBOL(try_lookup_one_len);
|
|
|
|
/**
|
|
* lookup_one_len - filesystem helper to lookup single pathname component
|
|
* @name: pathname component to lookup
|
|
* @base: base directory to lookup from
|
|
* @len: maximum length @len should be interpreted to
|
|
*
|
|
* Note that this routine is purely a helper for filesystem usage and should
|
|
* not be called by generic code.
|
|
*
|
|
* The caller must hold base->i_mutex.
|
|
*/
|
|
struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
|
|
{
|
|
struct dentry *dentry;
|
|
struct qstr this;
|
|
int err;
|
|
|
|
WARN_ON_ONCE(!inode_is_locked(base->d_inode));
|
|
|
|
err = lookup_one_len_common(name, base, len, &this);
|
|
if (err)
|
|
return ERR_PTR(err);
|
|
|
|
dentry = lookup_dcache(&this, base, 0);
|
|
return dentry ? dentry : __lookup_slow(&this, base, 0);
|
|
}
|
|
EXPORT_SYMBOL(lookup_one_len);
|
|
|
|
/**
|
|
* lookup_one_len_unlocked - filesystem helper to lookup single pathname component
|
|
* @name: pathname component to lookup
|
|
* @base: base directory to lookup from
|
|
* @len: maximum length @len should be interpreted to
|
|
*
|
|
* Note that this routine is purely a helper for filesystem usage and should
|
|
* not be called by generic code.
|
|
*
|
|
* Unlike lookup_one_len, it should be called without the parent
|
|
* i_mutex held, and will take the i_mutex itself if necessary.
|
|
*/
|
|
struct dentry *lookup_one_len_unlocked(const char *name,
|
|
struct dentry *base, int len)
|
|
{
|
|
struct qstr this;
|
|
int err;
|
|
struct dentry *ret;
|
|
|
|
err = lookup_one_len_common(name, base, len, &this);
|
|
if (err)
|
|
return ERR_PTR(err);
|
|
|
|
ret = lookup_dcache(&this, base, 0);
|
|
if (!ret)
|
|
ret = lookup_slow(&this, base, 0);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(lookup_one_len_unlocked);
|
|
|
|
/*
|
|
* Like lookup_one_len_unlocked(), except that it yields ERR_PTR(-ENOENT)
|
|
* on negatives. Returns known positive or ERR_PTR(); that's what
|
|
* most of the users want. Note that pinned negative with unlocked parent
|
|
* _can_ become positive at any time, so callers of lookup_one_len_unlocked()
|
|
* need to be very careful; pinned positives have ->d_inode stable, so
|
|
* this one avoids such problems.
|
|
*/
|
|
struct dentry *lookup_positive_unlocked(const char *name,
|
|
struct dentry *base, int len)
|
|
{
|
|
struct dentry *ret = lookup_one_len_unlocked(name, base, len);
|
|
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
|
|
dput(ret);
|
|
ret = ERR_PTR(-ENOENT);
|
|
}
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(lookup_positive_unlocked);
|
|
|
|
#ifdef CONFIG_UNIX98_PTYS
|
|
int path_pts(struct path *path)
|
|
{
|
|
/* Find something mounted on "pts" in the same directory as
|
|
* the input path.
|
|
*/
|
|
struct dentry *parent = dget_parent(path->dentry);
|
|
struct dentry *child;
|
|
struct qstr this = QSTR_INIT("pts", 3);
|
|
|
|
if (unlikely(!path_connected(path->mnt, parent))) {
|
|
dput(parent);
|
|
return -ENOENT;
|
|
}
|
|
dput(path->dentry);
|
|
path->dentry = parent;
|
|
child = d_hash_and_lookup(parent, &this);
|
|
if (!child)
|
|
return -ENOENT;
|
|
|
|
path->dentry = child;
|
|
dput(parent);
|
|
follow_down(path);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
|
|
struct path *path, int *empty)
|
|
{
|
|
return filename_lookup(dfd, getname_flags(name, flags, empty),
|
|
flags, path, NULL);
|
|
}
|
|
EXPORT_SYMBOL(user_path_at_empty);
|
|
|
|
int __check_sticky(struct inode *dir, struct inode *inode)
|
|
{
|
|
kuid_t fsuid = current_fsuid();
|
|
|
|
if (uid_eq(inode->i_uid, fsuid))
|
|
return 0;
|
|
if (uid_eq(dir->i_uid, fsuid))
|
|
return 0;
|
|
return !capable_wrt_inode_uidgid(inode, CAP_FOWNER);
|
|
}
|
|
EXPORT_SYMBOL(__check_sticky);
|
|
|
|
/*
|
|
* Check whether we can remove a link victim from directory dir, check
|
|
* whether the type of victim is right.
|
|
* 1. We can't do it if dir is read-only (done in permission())
|
|
* 2. We should have write and exec permissions on dir
|
|
* 3. We can't remove anything from append-only dir
|
|
* 4. We can't do anything with immutable dir (done in permission())
|
|
* 5. If the sticky bit on dir is set we should either
|
|
* a. be owner of dir, or
|
|
* b. be owner of victim, or
|
|
* c. have CAP_FOWNER capability
|
|
* 6. If the victim is append-only or immutable we can't do antyhing with
|
|
* links pointing to it.
|
|
* 7. If the victim has an unknown uid or gid we can't change the inode.
|
|
* 8. If we were asked to remove a directory and victim isn't one - ENOTDIR.
|
|
* 9. If we were asked to remove a non-directory and victim isn't one - EISDIR.
|
|
* 10. We can't remove a root or mountpoint.
|
|
* 11. We don't allow removal of NFS sillyrenamed files; it's handled by
|
|
* nfs_async_unlink().
|
|
*/
|
|
static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
|
|
{
|
|
struct inode *inode = d_backing_inode(victim);
|
|
int error;
|
|
|
|
if (d_is_negative(victim))
|
|
return -ENOENT;
|
|
BUG_ON(!inode);
|
|
|
|
BUG_ON(victim->d_parent->d_inode != dir);
|
|
|
|
/* Inode writeback is not safe when the uid or gid are invalid. */
|
|
if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
|
|
return -EOVERFLOW;
|
|
|
|
audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
|
|
|
|
error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
|
|
if (error)
|
|
return error;
|
|
if (IS_APPEND(dir))
|
|
return -EPERM;
|
|
|
|
if (check_sticky(dir, inode) || IS_APPEND(inode) ||
|
|
IS_IMMUTABLE(inode) || IS_SWAPFILE(inode) || HAS_UNMAPPED_ID(inode))
|
|
return -EPERM;
|
|
if (isdir) {
|
|
if (!d_is_dir(victim))
|
|
return -ENOTDIR;
|
|
if (IS_ROOT(victim))
|
|
return -EBUSY;
|
|
} else if (d_is_dir(victim))
|
|
return -EISDIR;
|
|
if (IS_DEADDIR(dir))
|
|
return -ENOENT;
|
|
if (victim->d_flags & DCACHE_NFSFS_RENAMED)
|
|
return -EBUSY;
|
|
return 0;
|
|
}
|
|
|
|
/* Check whether we can create an object with dentry child in directory
|
|
* dir.
|
|
* 1. We can't do it if child already exists (open has special treatment for
|
|
* this case, but since we are inlined it's OK)
|
|
* 2. We can't do it if dir is read-only (done in permission())
|
|
* 3. We can't do it if the fs can't represent the fsuid or fsgid.
|
|
* 4. We should have write and exec permissions on dir
|
|
* 5. We can't do it if dir is immutable (done in permission())
|
|
*/
|
|
static inline int may_create(struct inode *dir, struct dentry *child)
|
|
{
|
|
struct user_namespace *s_user_ns;
|
|
audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
|
|
if (child->d_inode)
|
|
return -EEXIST;
|
|
if (IS_DEADDIR(dir))
|
|
return -ENOENT;
|
|
s_user_ns = dir->i_sb->s_user_ns;
|
|
if (!kuid_has_mapping(s_user_ns, current_fsuid()) ||
|
|
!kgid_has_mapping(s_user_ns, current_fsgid()))
|
|
return -EOVERFLOW;
|
|
return inode_permission(dir, MAY_WRITE | MAY_EXEC);
|
|
}
|
|
|
|
/*
|
|
* p1 and p2 should be directories on the same fs.
|
|
*/
|
|
struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
|
|
{
|
|
struct dentry *p;
|
|
|
|
if (p1 == p2) {
|
|
inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
|
|
return NULL;
|
|
}
|
|
|
|
mutex_lock(&p1->d_sb->s_vfs_rename_mutex);
|
|
|
|
p = d_ancestor(p2, p1);
|
|
if (p) {
|
|
inode_lock_nested(p2->d_inode, I_MUTEX_PARENT);
|
|
inode_lock_nested(p1->d_inode, I_MUTEX_CHILD);
|
|
return p;
|
|
}
|
|
|
|
p = d_ancestor(p1, p2);
|
|
if (p) {
|
|
inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
|
|
inode_lock_nested(p2->d_inode, I_MUTEX_CHILD);
|
|
return p;
|
|
}
|
|
|
|
inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
|
|
inode_lock_nested(p2->d_inode, I_MUTEX_PARENT2);
|
|
return NULL;
|
|
}
|
|
EXPORT_SYMBOL(lock_rename);
|
|
|
|
void unlock_rename(struct dentry *p1, struct dentry *p2)
|
|
{
|
|
inode_unlock(p1->d_inode);
|
|
if (p1 != p2) {
|
|
inode_unlock(p2->d_inode);
|
|
mutex_unlock(&p1->d_sb->s_vfs_rename_mutex);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(unlock_rename);
|
|
|
|
int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|
bool want_excl)
|
|
{
|
|
int error = may_create(dir, dentry);
|
|
if (error)
|
|
return error;
|
|
|
|
if (!dir->i_op->create)
|
|
return -EACCES; /* shouldn't it be ENOSYS? */
|
|
mode &= S_IALLUGO;
|
|
mode |= S_IFREG;
|
|
error = security_inode_create(dir, dentry, mode);
|
|
if (error)
|
|
return error;
|
|
error = dir->i_op->create(dir, dentry, mode, want_excl);
|
|
if (!error)
|
|
fsnotify_create(dir, dentry);
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL_NS(vfs_create, ANDROID_GKI_VFS_EXPORT_ONLY);
|
|
|
|
int vfs_mkobj(struct dentry *dentry, umode_t mode,
|
|
int (*f)(struct dentry *, umode_t, void *),
|
|
void *arg)
|
|
{
|
|
struct inode *dir = dentry->d_parent->d_inode;
|
|
int error = may_create(dir, dentry);
|
|
if (error)
|
|
return error;
|
|
|
|
mode &= S_IALLUGO;
|
|
mode |= S_IFREG;
|
|
error = security_inode_create(dir, dentry, mode);
|
|
if (error)
|
|
return error;
|
|
error = f(dentry, mode, arg);
|
|
if (!error)
|
|
fsnotify_create(dir, dentry);
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL(vfs_mkobj);
|
|
|
|
bool may_open_dev(const struct path *path)
|
|
{
|
|
return !(path->mnt->mnt_flags & MNT_NODEV) &&
|
|
!(path->mnt->mnt_sb->s_iflags & SB_I_NODEV);
|
|
}
|
|
|
|
static int may_open(const struct path *path, int acc_mode, int flag)
|
|
{
|
|
struct dentry *dentry = path->dentry;
|
|
struct inode *inode = dentry->d_inode;
|
|
int error;
|
|
|
|
if (!inode)
|
|
return -ENOENT;
|
|
|
|
switch (inode->i_mode & S_IFMT) {
|
|
case S_IFLNK:
|
|
return -ELOOP;
|
|
case S_IFDIR:
|
|
if (acc_mode & MAY_WRITE)
|
|
return -EISDIR;
|
|
if (acc_mode & MAY_EXEC)
|
|
return -EACCES;
|
|
break;
|
|
case S_IFBLK:
|
|
case S_IFCHR:
|
|
if (!may_open_dev(path))
|
|
return -EACCES;
|
|
fallthrough;
|
|
case S_IFIFO:
|
|
case S_IFSOCK:
|
|
if (acc_mode & MAY_EXEC)
|
|
return -EACCES;
|
|
flag &= ~O_TRUNC;
|
|
break;
|
|
case S_IFREG:
|
|
if ((acc_mode & MAY_EXEC) && path_noexec(path))
|
|
return -EACCES;
|
|
break;
|
|
}
|
|
|
|
error = inode_permission(inode, MAY_OPEN | acc_mode);
|
|
if (error)
|
|
return error;
|
|
|
|
/*
|
|
* An append-only file must be opened in append mode for writing.
|
|
*/
|
|
if (IS_APPEND(inode)) {
|
|
if ((flag & O_ACCMODE) != O_RDONLY && !(flag & O_APPEND))
|
|
return -EPERM;
|
|
if (flag & O_TRUNC)
|
|
return -EPERM;
|
|
}
|
|
|
|
/* O_NOATIME can only be set by the owner or superuser */
|
|
if (flag & O_NOATIME && !inode_owner_or_capable(inode))
|
|
return -EPERM;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int handle_truncate(struct file *filp)
|
|
{
|
|
const struct path *path = &filp->f_path;
|
|
struct inode *inode = path->dentry->d_inode;
|
|
int error = get_write_access(inode);
|
|
if (error)
|
|
return error;
|
|
/*
|
|
* Refuse to truncate files with mandatory locks held on them.
|
|
*/
|
|
error = locks_verify_locked(filp);
|
|
if (!error)
|
|
error = security_path_truncate(path);
|
|
if (!error) {
|
|
error = do_truncate(path->dentry, 0,
|
|
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
|
|
filp);
|
|
}
|
|
put_write_access(inode);
|
|
return error;
|
|
}
|
|
|
|
static inline int open_to_namei_flags(int flag)
|
|
{
|
|
if ((flag & O_ACCMODE) == 3)
|
|
flag--;
|
|
return flag;
|
|
}
|
|
|
|
static int may_o_create(const struct path *dir, struct dentry *dentry, umode_t mode)
|
|
{
|
|
struct user_namespace *s_user_ns;
|
|
int error = security_path_mknod(dir, dentry, mode, 0);
|
|
if (error)
|
|
return error;
|
|
|
|
s_user_ns = dir->dentry->d_sb->s_user_ns;
|
|
if (!kuid_has_mapping(s_user_ns, current_fsuid()) ||
|
|
!kgid_has_mapping(s_user_ns, current_fsgid()))
|
|
return -EOVERFLOW;
|
|
|
|
error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
|
|
if (error)
|
|
return error;
|
|
|
|
return security_inode_create(dir->dentry->d_inode, dentry, mode);
|
|
}
|
|
|
|
/*
|
|
* Attempt to atomically look up, create and open a file from a negative
|
|
* dentry.
|
|
*
|
|
* Returns 0 if successful. The file will have been created and attached to
|
|
* @file by the filesystem calling finish_open().
|
|
*
|
|
* If the file was looked up only or didn't need creating, FMODE_OPENED won't
|
|
* be set. The caller will need to perform the open themselves. @path will
|
|
* have been updated to point to the new dentry. This may be negative.
|
|
*
|
|
* Returns an error code otherwise.
|
|
*/
|
|
static struct dentry *atomic_open(struct nameidata *nd, struct dentry *dentry,
|
|
struct file *file,
|
|
int open_flag, umode_t mode)
|
|
{
|
|
struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
|
|
struct inode *dir = nd->path.dentry->d_inode;
|
|
int error;
|
|
|
|
if (nd->flags & LOOKUP_DIRECTORY)
|
|
open_flag |= O_DIRECTORY;
|
|
|
|
file->f_path.dentry = DENTRY_NOT_SET;
|
|
file->f_path.mnt = nd->path.mnt;
|
|
error = dir->i_op->atomic_open(dir, dentry, file,
|
|
open_to_namei_flags(open_flag), mode);
|
|
d_lookup_done(dentry);
|
|
if (!error) {
|
|
if (file->f_mode & FMODE_OPENED) {
|
|
if (unlikely(dentry != file->f_path.dentry)) {
|
|
dput(dentry);
|
|
dentry = dget(file->f_path.dentry);
|
|
}
|
|
} else if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
|
|
error = -EIO;
|
|
} else {
|
|
if (file->f_path.dentry) {
|
|
dput(dentry);
|
|
dentry = file->f_path.dentry;
|
|
}
|
|
if (unlikely(d_is_negative(dentry)))
|
|
error = -ENOENT;
|
|
}
|
|
}
|
|
if (error) {
|
|
dput(dentry);
|
|
dentry = ERR_PTR(error);
|
|
}
|
|
return dentry;
|
|
}
|
|
|
|
/*
|
|
* Look up and maybe create and open the last component.
|
|
*
|
|
* Must be called with parent locked (exclusive in O_CREAT case).
|
|
*
|
|
* Returns 0 on success, that is, if
|
|
* the file was successfully atomically created (if necessary) and opened, or
|
|
* the file was not completely opened at this time, though lookups and
|
|
* creations were performed.
|
|
* These case are distinguished by presence of FMODE_OPENED on file->f_mode.
|
|
* In the latter case dentry returned in @path might be negative if O_CREAT
|
|
* hadn't been specified.
|
|
*
|
|
* An error code is returned on failure.
|
|
*/
|
|
static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
|
|
const struct open_flags *op,
|
|
bool got_write)
|
|
{
|
|
struct dentry *dir = nd->path.dentry;
|
|
struct inode *dir_inode = dir->d_inode;
|
|
int open_flag = op->open_flag;
|
|
struct dentry *dentry;
|
|
int error, create_error = 0;
|
|
umode_t mode = op->mode;
|
|
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
|
|
|
|
if (unlikely(IS_DEADDIR(dir_inode)))
|
|
return ERR_PTR(-ENOENT);
|
|
|
|
file->f_mode &= ~FMODE_CREATED;
|
|
dentry = d_lookup(dir, &nd->last);
|
|
for (;;) {
|
|
if (!dentry) {
|
|
dentry = d_alloc_parallel(dir, &nd->last, &wq);
|
|
if (IS_ERR(dentry))
|
|
return dentry;
|
|
}
|
|
if (d_in_lookup(dentry))
|
|
break;
|
|
|
|
error = d_revalidate(dentry, nd->flags);
|
|
if (likely(error > 0))
|
|
break;
|
|
if (error)
|
|
goto out_dput;
|
|
d_invalidate(dentry);
|
|
dput(dentry);
|
|
dentry = NULL;
|
|
}
|
|
if (dentry->d_inode) {
|
|
/* Cached positive dentry: will open in f_op->open */
|
|
return dentry;
|
|
}
|
|
|
|
/*
|
|
* Checking write permission is tricky, bacuse we don't know if we are
|
|
* going to actually need it: O_CREAT opens should work as long as the
|
|
* file exists. But checking existence breaks atomicity. The trick is
|
|
* to check access and if not granted clear O_CREAT from the flags.
|
|
*
|
|
* Another problem is returing the "right" error value (e.g. for an
|
|
* O_EXCL open we want to return EEXIST not EROFS).
|
|
*/
|
|
if (unlikely(!got_write))
|
|
open_flag &= ~O_TRUNC;
|
|
if (open_flag & O_CREAT) {
|
|
if (open_flag & O_EXCL)
|
|
open_flag &= ~O_TRUNC;
|
|
if (!IS_POSIXACL(dir->d_inode))
|
|
mode &= ~current_umask();
|
|
if (likely(got_write))
|
|
create_error = may_o_create(&nd->path, dentry, mode);
|
|
else
|
|
create_error = -EROFS;
|
|
}
|
|
if (create_error)
|
|
open_flag &= ~O_CREAT;
|
|
if (dir_inode->i_op->atomic_open) {
|
|
dentry = atomic_open(nd, dentry, file, open_flag, mode);
|
|
if (unlikely(create_error) && dentry == ERR_PTR(-ENOENT))
|
|
dentry = ERR_PTR(create_error);
|
|
return dentry;
|
|
}
|
|
|
|
if (d_in_lookup(dentry)) {
|
|
struct dentry *res = dir_inode->i_op->lookup(dir_inode, dentry,
|
|
nd->flags);
|
|
d_lookup_done(dentry);
|
|
if (unlikely(res)) {
|
|
if (IS_ERR(res)) {
|
|
error = PTR_ERR(res);
|
|
goto out_dput;
|
|
}
|
|
dput(dentry);
|
|
dentry = res;
|
|
}
|
|
}
|
|
|
|
/* Negative dentry, just create the file */
|
|
if (!dentry->d_inode && (open_flag & O_CREAT)) {
|
|
file->f_mode |= FMODE_CREATED;
|
|
audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE);
|
|
if (!dir_inode->i_op->create) {
|
|
error = -EACCES;
|
|
goto out_dput;
|
|
}
|
|
error = dir_inode->i_op->create(dir_inode, dentry, mode,
|
|
open_flag & O_EXCL);
|
|
if (error)
|
|
goto out_dput;
|
|
}
|
|
if (unlikely(create_error) && !dentry->d_inode) {
|
|
error = create_error;
|
|
goto out_dput;
|
|
}
|
|
return dentry;
|
|
|
|
out_dput:
|
|
dput(dentry);
|
|
return ERR_PTR(error);
|
|
}
|
|
|
|
static const char *open_last_lookups(struct nameidata *nd,
|
|
struct file *file, const struct open_flags *op)
|
|
{
|
|
struct dentry *dir = nd->path.dentry;
|
|
int open_flag = op->open_flag;
|
|
bool got_write = false;
|
|
unsigned seq;
|
|
struct inode *inode;
|
|
struct dentry *dentry;
|
|
const char *res;
|
|
|
|
nd->flags |= op->intent;
|
|
|
|
if (nd->last_type != LAST_NORM) {
|
|
if (nd->depth)
|
|
put_link(nd);
|
|
return handle_dots(nd, nd->last_type);
|
|
}
|
|
|
|
if (!(open_flag & O_CREAT)) {
|
|
if (nd->last.name[nd->last.len])
|
|
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
|
|
/* we _can_ be in RCU mode here */
|
|
dentry = lookup_fast(nd, &inode, &seq);
|
|
if (IS_ERR(dentry))
|
|
return ERR_CAST(dentry);
|
|
if (likely(dentry))
|
|
goto finish_lookup;
|
|
|
|
BUG_ON(nd->flags & LOOKUP_RCU);
|
|
} else {
|
|
/* create side of things */
|
|
if (nd->flags & LOOKUP_RCU) {
|
|
if (!try_to_unlazy(nd))
|
|
return ERR_PTR(-ECHILD);
|
|
}
|
|
audit_inode(nd->name, dir, AUDIT_INODE_PARENT);
|
|
/* trailing slashes? */
|
|
if (unlikely(nd->last.name[nd->last.len]))
|
|
return ERR_PTR(-EISDIR);
|
|
}
|
|
|
|
if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
|
|
got_write = !mnt_want_write(nd->path.mnt);
|
|
/*
|
|
* do _not_ fail yet - we might not need that or fail with
|
|
* a different error; let lookup_open() decide; we'll be
|
|
* dropping this one anyway.
|
|
*/
|
|
}
|
|
if (open_flag & O_CREAT)
|
|
inode_lock(dir->d_inode);
|
|
else
|
|
inode_lock_shared(dir->d_inode);
|
|
dentry = lookup_open(nd, file, op, got_write);
|
|
if (!IS_ERR(dentry) && (file->f_mode & FMODE_CREATED))
|
|
fsnotify_create(dir->d_inode, dentry);
|
|
if (open_flag & O_CREAT)
|
|
inode_unlock(dir->d_inode);
|
|
else
|
|
inode_unlock_shared(dir->d_inode);
|
|
|
|
if (got_write)
|
|
mnt_drop_write(nd->path.mnt);
|
|
|
|
if (IS_ERR(dentry))
|
|
return ERR_CAST(dentry);
|
|
|
|
if (file->f_mode & (FMODE_OPENED | FMODE_CREATED)) {
|
|
dput(nd->path.dentry);
|
|
nd->path.dentry = dentry;
|
|
return NULL;
|
|
}
|
|
|
|
finish_lookup:
|
|
if (nd->depth)
|
|
put_link(nd);
|
|
res = step_into(nd, WALK_TRAILING, dentry, inode, seq);
|
|
if (unlikely(res))
|
|
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
* Handle the last step of open()
|
|
*/
|
|
static int do_open(struct nameidata *nd,
|
|
struct file *file, const struct open_flags *op)
|
|
{
|
|
int open_flag = op->open_flag;
|
|
bool do_truncate;
|
|
int acc_mode;
|
|
int error;
|
|
|
|
if (!(file->f_mode & (FMODE_OPENED | FMODE_CREATED))) {
|
|
error = complete_walk(nd);
|
|
if (error)
|
|
return error;
|
|
}
|
|
if (!(file->f_mode & FMODE_CREATED))
|
|
audit_inode(nd->name, nd->path.dentry, 0);
|
|
if (open_flag & O_CREAT) {
|
|
if ((open_flag & O_EXCL) && !(file->f_mode & FMODE_CREATED))
|
|
return -EEXIST;
|
|
if (d_is_dir(nd->path.dentry))
|
|
return -EISDIR;
|
|
error = may_create_in_sticky(nd->dir_mode, nd->dir_uid,
|
|
d_backing_inode(nd->path.dentry));
|
|
if (unlikely(error))
|
|
return error;
|
|
}
|
|
if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
|
|
return -ENOTDIR;
|
|
|
|
do_truncate = false;
|
|
acc_mode = op->acc_mode;
|
|
if (file->f_mode & FMODE_CREATED) {
|
|
/* Don't check for write permission, don't truncate */
|
|
open_flag &= ~O_TRUNC;
|
|
acc_mode = 0;
|
|
} else if (d_is_reg(nd->path.dentry) && open_flag & O_TRUNC) {
|
|
error = mnt_want_write(nd->path.mnt);
|
|
if (error)
|
|
return error;
|
|
do_truncate = true;
|
|
}
|
|
error = may_open(&nd->path, acc_mode, open_flag);
|
|
if (!error && !(file->f_mode & FMODE_OPENED))
|
|
error = vfs_open(&nd->path, file);
|
|
if (!error)
|
|
error = ima_file_check(file, op->acc_mode);
|
|
if (!error && do_truncate)
|
|
error = handle_truncate(file);
|
|
if (unlikely(error > 0)) {
|
|
WARN_ON(1);
|
|
error = -EINVAL;
|
|
}
|
|
if (do_truncate)
|
|
mnt_drop_write(nd->path.mnt);
|
|
return error;
|
|
}
|
|
|
|
struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag)
|
|
{
|
|
struct dentry *child = NULL;
|
|
struct inode *dir = dentry->d_inode;
|
|
struct inode *inode;
|
|
int error;
|
|
|
|
/* we want directory to be writable */
|
|
error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
|
|
if (error)
|
|
goto out_err;
|
|
error = -EOPNOTSUPP;
|
|
if (!dir->i_op->tmpfile)
|
|
goto out_err;
|
|
error = -ENOMEM;
|
|
child = d_alloc(dentry, &slash_name);
|
|
if (unlikely(!child))
|
|
goto out_err;
|
|
error = dir->i_op->tmpfile(dir, child, mode);
|
|
if (error)
|
|
goto out_err;
|
|
error = -ENOENT;
|
|
inode = child->d_inode;
|
|
if (unlikely(!inode))
|
|
goto out_err;
|
|
if (!(open_flag & O_EXCL)) {
|
|
spin_lock(&inode->i_lock);
|
|
inode->i_state |= I_LINKABLE;
|
|
spin_unlock(&inode->i_lock);
|
|
}
|
|
ima_post_create_tmpfile(inode);
|
|
return child;
|
|
|
|
out_err:
|
|
dput(child);
|
|
return ERR_PTR(error);
|
|
}
|
|
EXPORT_SYMBOL(vfs_tmpfile);
|
|
|
|
static int do_tmpfile(struct nameidata *nd, unsigned flags,
|
|
const struct open_flags *op,
|
|
struct file *file)
|
|
{
|
|
struct dentry *child;
|
|
struct path path;
|
|
int error = path_lookupat(nd, flags | LOOKUP_DIRECTORY, &path);
|
|
if (unlikely(error))
|
|
return error;
|
|
error = mnt_want_write(path.mnt);
|
|
if (unlikely(error))
|
|
goto out;
|
|
child = vfs_tmpfile(path.dentry, op->mode, op->open_flag);
|
|
error = PTR_ERR(child);
|
|
if (IS_ERR(child))
|
|
goto out2;
|
|
dput(path.dentry);
|
|
path.dentry = child;
|
|
audit_inode(nd->name, child, 0);
|
|
/* Don't check for other permissions, the inode was just created */
|
|
error = may_open(&path, 0, op->open_flag);
|
|
if (error)
|
|
goto out2;
|
|
file->f_path.mnt = path.mnt;
|
|
error = finish_open(file, child, NULL);
|
|
out2:
|
|
mnt_drop_write(path.mnt);
|
|
out:
|
|
path_put(&path);
|
|
return error;
|
|
}
|
|
|
|
static int do_o_path(struct nameidata *nd, unsigned flags, struct file *file)
|
|
{
|
|
struct path path;
|
|
int error = path_lookupat(nd, flags, &path);
|
|
if (!error) {
|
|
audit_inode(nd->name, path.dentry, 0);
|
|
error = vfs_open(&path, file);
|
|
path_put(&path);
|
|
}
|
|
return error;
|
|
}
|
|
|
|
static struct file *path_openat(struct nameidata *nd,
|
|
const struct open_flags *op, unsigned flags)
|
|
{
|
|
struct file *file;
|
|
int error;
|
|
|
|
file = alloc_empty_file(op->open_flag, current_cred());
|
|
if (IS_ERR(file))
|
|
return file;
|
|
|
|
if (unlikely(file->f_flags & __O_TMPFILE)) {
|
|
error = do_tmpfile(nd, flags, op, file);
|
|
} else if (unlikely(file->f_flags & O_PATH)) {
|
|
error = do_o_path(nd, flags, file);
|
|
} else {
|
|
const char *s = path_init(nd, flags);
|
|
while (!(error = link_path_walk(s, nd)) &&
|
|
(s = open_last_lookups(nd, file, op)) != NULL)
|
|
;
|
|
if (!error)
|
|
error = do_open(nd, file, op);
|
|
terminate_walk(nd);
|
|
}
|
|
if (likely(!error)) {
|
|
if (likely(file->f_mode & FMODE_OPENED))
|
|
return file;
|
|
WARN_ON(1);
|
|
error = -EINVAL;
|
|
}
|
|
fput(file);
|
|
if (error == -EOPENSTALE) {
|
|
if (flags & LOOKUP_RCU)
|
|
error = -ECHILD;
|
|
else
|
|
error = -ESTALE;
|
|
}
|
|
return ERR_PTR(error);
|
|
}
|
|
|
|
struct file *do_filp_open(int dfd, struct filename *pathname,
|
|
const struct open_flags *op)
|
|
{
|
|
struct nameidata nd;
|
|
int flags = op->lookup_flags;
|
|
struct file *filp;
|
|
|
|
set_nameidata(&nd, dfd, pathname);
|
|
filp = path_openat(&nd, op, flags | LOOKUP_RCU);
|
|
if (unlikely(filp == ERR_PTR(-ECHILD)))
|
|
filp = path_openat(&nd, op, flags);
|
|
if (unlikely(filp == ERR_PTR(-ESTALE)))
|
|
filp = path_openat(&nd, op, flags | LOOKUP_REVAL);
|
|
restore_nameidata();
|
|
return filp;
|
|
}
|
|
|
|
struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
|
|
const char *name, const struct open_flags *op)
|
|
{
|
|
struct nameidata nd;
|
|
struct file *file;
|
|
struct filename *filename;
|
|
int flags = op->lookup_flags | LOOKUP_ROOT;
|
|
|
|
nd.root.mnt = mnt;
|
|
nd.root.dentry = dentry;
|
|
|
|
if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN)
|
|
return ERR_PTR(-ELOOP);
|
|
|
|
filename = getname_kernel(name);
|
|
if (IS_ERR(filename))
|
|
return ERR_CAST(filename);
|
|
|
|
set_nameidata(&nd, -1, filename);
|
|
file = path_openat(&nd, op, flags | LOOKUP_RCU);
|
|
if (unlikely(file == ERR_PTR(-ECHILD)))
|
|
file = path_openat(&nd, op, flags);
|
|
if (unlikely(file == ERR_PTR(-ESTALE)))
|
|
file = path_openat(&nd, op, flags | LOOKUP_REVAL);
|
|
restore_nameidata();
|
|
putname(filename);
|
|
return file;
|
|
}
|
|
|
|
static struct dentry *filename_create(int dfd, struct filename *name,
|
|
struct path *path, unsigned int lookup_flags)
|
|
{
|
|
struct dentry *dentry = ERR_PTR(-EEXIST);
|
|
struct qstr last;
|
|
int type;
|
|
int err2;
|
|
int error;
|
|
bool is_dir = (lookup_flags & LOOKUP_DIRECTORY);
|
|
|
|
/*
|
|
* Note that only LOOKUP_REVAL and LOOKUP_DIRECTORY matter here. Any
|
|
* other flags passed in are ignored!
|
|
*/
|
|
lookup_flags &= LOOKUP_REVAL;
|
|
|
|
name = filename_parentat(dfd, name, lookup_flags, path, &last, &type);
|
|
if (IS_ERR(name))
|
|
return ERR_CAST(name);
|
|
|
|
/*
|
|
* Yucky last component or no last component at all?
|
|
* (foo/., foo/.., /////)
|
|
*/
|
|
if (unlikely(type != LAST_NORM))
|
|
goto out;
|
|
|
|
/* don't fail immediately if it's r/o, at least try to report other errors */
|
|
err2 = mnt_want_write(path->mnt);
|
|
/*
|
|
* Do the final lookup.
|
|
*/
|
|
lookup_flags |= LOOKUP_CREATE | LOOKUP_EXCL;
|
|
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
|
|
dentry = __lookup_hash(&last, path->dentry, lookup_flags);
|
|
if (IS_ERR(dentry))
|
|
goto unlock;
|
|
|
|
error = -EEXIST;
|
|
if (d_is_positive(dentry))
|
|
goto fail;
|
|
|
|
/*
|
|
* Special case - lookup gave negative, but... we had foo/bar/
|
|
* From the vfs_mknod() POV we just have a negative dentry -
|
|
* all is fine. Let's be bastards - you had / on the end, you've
|
|
* been asking for (non-existent) directory. -ENOENT for you.
|
|
*/
|
|
if (unlikely(!is_dir && last.name[last.len])) {
|
|
error = -ENOENT;
|
|
goto fail;
|
|
}
|
|
if (unlikely(err2)) {
|
|
error = err2;
|
|
goto fail;
|
|
}
|
|
putname(name);
|
|
return dentry;
|
|
fail:
|
|
dput(dentry);
|
|
dentry = ERR_PTR(error);
|
|
unlock:
|
|
inode_unlock(path->dentry->d_inode);
|
|
if (!err2)
|
|
mnt_drop_write(path->mnt);
|
|
out:
|
|
path_put(path);
|
|
putname(name);
|
|
return dentry;
|
|
}
|
|
|
|
struct dentry *kern_path_create(int dfd, const char *pathname,
|
|
struct path *path, unsigned int lookup_flags)
|
|
{
|
|
return filename_create(dfd, getname_kernel(pathname),
|
|
path, lookup_flags);
|
|
}
|
|
EXPORT_SYMBOL(kern_path_create);
|
|
|
|
void done_path_create(struct path *path, struct dentry *dentry)
|
|
{
|
|
dput(dentry);
|
|
inode_unlock(path->dentry->d_inode);
|
|
mnt_drop_write(path->mnt);
|
|
path_put(path);
|
|
}
|
|
EXPORT_SYMBOL(done_path_create);
|
|
|
|
inline struct dentry *user_path_create(int dfd, const char __user *pathname,
|
|
struct path *path, unsigned int lookup_flags)
|
|
{
|
|
return filename_create(dfd, getname(pathname), path, lookup_flags);
|
|
}
|
|
EXPORT_SYMBOL(user_path_create);
|
|
|
|
int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
|
|
{
|
|
bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV;
|
|
int error = may_create(dir, dentry);
|
|
|
|
if (error)
|
|
return error;
|
|
|
|
if ((S_ISCHR(mode) || S_ISBLK(mode)) && !is_whiteout &&
|
|
!capable(CAP_MKNOD))
|
|
return -EPERM;
|
|
|
|
if (!dir->i_op->mknod)
|
|
return -EPERM;
|
|
|
|
error = devcgroup_inode_mknod(mode, dev);
|
|
if (error)
|
|
return error;
|
|
|
|
error = security_inode_mknod(dir, dentry, mode, dev);
|
|
if (error)
|
|
return error;
|
|
|
|
error = dir->i_op->mknod(dir, dentry, mode, dev);
|
|
if (!error)
|
|
fsnotify_create(dir, dentry);
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL(vfs_mknod);
|
|
|
|
static int may_mknod(umode_t mode)
|
|
{
|
|
switch (mode & S_IFMT) {
|
|
case S_IFREG:
|
|
case S_IFCHR:
|
|
case S_IFBLK:
|
|
case S_IFIFO:
|
|
case S_IFSOCK:
|
|
case 0: /* zero mode translates to S_IFREG */
|
|
return 0;
|
|
case S_IFDIR:
|
|
return -EPERM;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
static long do_mknodat(int dfd, const char __user *filename, umode_t mode,
|
|
unsigned int dev)
|
|
{
|
|
struct dentry *dentry;
|
|
struct path path;
|
|
int error;
|
|
unsigned int lookup_flags = 0;
|
|
|
|
error = may_mknod(mode);
|
|
if (error)
|
|
return error;
|
|
retry:
|
|
dentry = user_path_create(dfd, filename, &path, lookup_flags);
|
|
if (IS_ERR(dentry))
|
|
return PTR_ERR(dentry);
|
|
|
|
if (!IS_POSIXACL(path.dentry->d_inode))
|
|
mode &= ~current_umask();
|
|
error = security_path_mknod(&path, dentry, mode, dev);
|
|
if (error)
|
|
goto out;
|
|
switch (mode & S_IFMT) {
|
|
case 0: case S_IFREG:
|
|
error = vfs_create(path.dentry->d_inode,dentry,mode,true);
|
|
if (!error)
|
|
ima_post_path_mknod(dentry);
|
|
break;
|
|
case S_IFCHR: case S_IFBLK:
|
|
error = vfs_mknod(path.dentry->d_inode,dentry,mode,
|
|
new_decode_dev(dev));
|
|
break;
|
|
case S_IFIFO: case S_IFSOCK:
|
|
error = vfs_mknod(path.dentry->d_inode,dentry,mode,0);
|
|
break;
|
|
}
|
|
out:
|
|
done_path_create(&path, dentry);
|
|
if (retry_estale(error, lookup_flags)) {
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
goto retry;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
|
|
unsigned int, dev)
|
|
{
|
|
return do_mknodat(dfd, filename, mode, dev);
|
|
}
|
|
|
|
SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev)
|
|
{
|
|
return do_mknodat(AT_FDCWD, filename, mode, dev);
|
|
}
|
|
|
|
int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|
{
|
|
int error = may_create(dir, dentry);
|
|
unsigned max_links = dir->i_sb->s_max_links;
|
|
|
|
if (error)
|
|
return error;
|
|
|
|
if (!dir->i_op->mkdir)
|
|
return -EPERM;
|
|
|
|
mode &= (S_IRWXUGO|S_ISVTX);
|
|
error = security_inode_mkdir(dir, dentry, mode);
|
|
if (error)
|
|
return error;
|
|
|
|
if (max_links && dir->i_nlink >= max_links)
|
|
return -EMLINK;
|
|
|
|
error = dir->i_op->mkdir(dir, dentry, mode);
|
|
if (!error)
|
|
fsnotify_mkdir(dir, dentry);
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL_NS(vfs_mkdir, ANDROID_GKI_VFS_EXPORT_ONLY);
|
|
|
|
static long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
|
|
{
|
|
struct dentry *dentry;
|
|
struct path path;
|
|
int error;
|
|
unsigned int lookup_flags = LOOKUP_DIRECTORY;
|
|
|
|
retry:
|
|
dentry = user_path_create(dfd, pathname, &path, lookup_flags);
|
|
if (IS_ERR(dentry))
|
|
return PTR_ERR(dentry);
|
|
|
|
if (!IS_POSIXACL(path.dentry->d_inode))
|
|
mode &= ~current_umask();
|
|
error = security_path_mkdir(&path, dentry, mode);
|
|
if (!error)
|
|
error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
|
|
done_path_create(&path, dentry);
|
|
if (retry_estale(error, lookup_flags)) {
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
goto retry;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
|
|
{
|
|
return do_mkdirat(dfd, pathname, mode);
|
|
}
|
|
|
|
SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
|
|
{
|
|
return do_mkdirat(AT_FDCWD, pathname, mode);
|
|
}
|
|
|
|
int vfs_rmdir(struct inode *dir, struct dentry *dentry)
|
|
{
|
|
int error = may_delete(dir, dentry, 1);
|
|
|
|
if (error)
|
|
return error;
|
|
|
|
if (!dir->i_op->rmdir)
|
|
return -EPERM;
|
|
|
|
dget(dentry);
|
|
inode_lock(dentry->d_inode);
|
|
|
|
error = -EBUSY;
|
|
if (is_local_mountpoint(dentry))
|
|
goto out;
|
|
|
|
error = security_inode_rmdir(dir, dentry);
|
|
if (error)
|
|
goto out;
|
|
|
|
error = dir->i_op->rmdir(dir, dentry);
|
|
if (error)
|
|
goto out;
|
|
|
|
shrink_dcache_parent(dentry);
|
|
dentry->d_inode->i_flags |= S_DEAD;
|
|
dont_mount(dentry);
|
|
detach_mounts(dentry);
|
|
|
|
out:
|
|
inode_unlock(dentry->d_inode);
|
|
dput(dentry);
|
|
if (!error)
|
|
d_delete_notify(dir, dentry);
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL_NS(vfs_rmdir, ANDROID_GKI_VFS_EXPORT_ONLY);
|
|
|
|
long do_rmdir(int dfd, struct filename *name)
|
|
{
|
|
int error = 0;
|
|
struct dentry *dentry;
|
|
struct path path;
|
|
struct qstr last;
|
|
int type;
|
|
unsigned int lookup_flags = 0;
|
|
retry:
|
|
name = filename_parentat(dfd, name, lookup_flags,
|
|
&path, &last, &type);
|
|
if (IS_ERR(name))
|
|
return PTR_ERR(name);
|
|
|
|
switch (type) {
|
|
case LAST_DOTDOT:
|
|
error = -ENOTEMPTY;
|
|
goto exit1;
|
|
case LAST_DOT:
|
|
error = -EINVAL;
|
|
goto exit1;
|
|
case LAST_ROOT:
|
|
error = -EBUSY;
|
|
goto exit1;
|
|
}
|
|
|
|
error = mnt_want_write(path.mnt);
|
|
if (error)
|
|
goto exit1;
|
|
|
|
inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT);
|
|
dentry = __lookup_hash(&last, path.dentry, lookup_flags);
|
|
error = PTR_ERR(dentry);
|
|
if (IS_ERR(dentry))
|
|
goto exit2;
|
|
if (!dentry->d_inode) {
|
|
error = -ENOENT;
|
|
goto exit3;
|
|
}
|
|
error = security_path_rmdir(&path, dentry);
|
|
if (error)
|
|
goto exit3;
|
|
error = vfs_rmdir(path.dentry->d_inode, dentry);
|
|
exit3:
|
|
dput(dentry);
|
|
exit2:
|
|
inode_unlock(path.dentry->d_inode);
|
|
mnt_drop_write(path.mnt);
|
|
exit1:
|
|
path_put(&path);
|
|
if (retry_estale(error, lookup_flags)) {
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
goto retry;
|
|
}
|
|
putname(name);
|
|
return error;
|
|
}
|
|
|
|
SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
|
|
{
|
|
return do_rmdir(AT_FDCWD, getname(pathname));
|
|
}
|
|
|
|
/**
|
|
* vfs_unlink - unlink a filesystem object
|
|
* @dir: parent directory
|
|
* @dentry: victim
|
|
* @delegated_inode: returns victim inode, if the inode is delegated.
|
|
*
|
|
* The caller must hold dir->i_mutex.
|
|
*
|
|
* If vfs_unlink discovers a delegation, it will return -EWOULDBLOCK and
|
|
* return a reference to the inode in delegated_inode. The caller
|
|
* should then break the delegation on that inode and retry. Because
|
|
* breaking a delegation may take a long time, the caller should drop
|
|
* dir->i_mutex before doing so.
|
|
*
|
|
* Alternatively, a caller may pass NULL for delegated_inode. This may
|
|
* be appropriate for callers that expect the underlying filesystem not
|
|
* to be NFS exported.
|
|
*/
|
|
int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode)
|
|
{
|
|
struct inode *target = dentry->d_inode;
|
|
int error = may_delete(dir, dentry, 0);
|
|
|
|
if (error)
|
|
return error;
|
|
|
|
if (!dir->i_op->unlink)
|
|
return -EPERM;
|
|
|
|
inode_lock(target);
|
|
if (is_local_mountpoint(dentry))
|
|
error = -EBUSY;
|
|
else {
|
|
error = security_inode_unlink(dir, dentry);
|
|
if (!error) {
|
|
error = try_break_deleg(target, delegated_inode);
|
|
if (error)
|
|
goto out;
|
|
error = dir->i_op->unlink(dir, dentry);
|
|
if (!error) {
|
|
dont_mount(dentry);
|
|
detach_mounts(dentry);
|
|
}
|
|
}
|
|
}
|
|
out:
|
|
inode_unlock(target);
|
|
|
|
/* We don't d_delete() NFS sillyrenamed files--they still exist. */
|
|
if (!error && dentry->d_flags & DCACHE_NFSFS_RENAMED) {
|
|
fsnotify_unlink(dir, dentry);
|
|
} else if (!error) {
|
|
fsnotify_link_count(target);
|
|
d_delete_notify(dir, dentry);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL_NS(vfs_unlink, ANDROID_GKI_VFS_EXPORT_ONLY);
|
|
|
|
/*
|
|
* Make sure that the actual truncation of the file will occur outside its
|
|
* directory's i_mutex. Truncate can take a long time if there is a lot of
|
|
* writeout happening, and we don't want to prevent access to the directory
|
|
* while waiting on the I/O.
|
|
*/
|
|
long do_unlinkat(int dfd, struct filename *name)
|
|
{
|
|
int error;
|
|
struct dentry *dentry;
|
|
struct path path;
|
|
struct qstr last;
|
|
int type;
|
|
struct inode *inode = NULL;
|
|
struct inode *delegated_inode = NULL;
|
|
unsigned int lookup_flags = 0;
|
|
retry:
|
|
name = filename_parentat(dfd, name, lookup_flags, &path, &last, &type);
|
|
if (IS_ERR(name))
|
|
return PTR_ERR(name);
|
|
|
|
error = -EISDIR;
|
|
if (type != LAST_NORM)
|
|
goto exit1;
|
|
|
|
error = mnt_want_write(path.mnt);
|
|
if (error)
|
|
goto exit1;
|
|
retry_deleg:
|
|
inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT);
|
|
dentry = __lookup_hash(&last, path.dentry, lookup_flags);
|
|
error = PTR_ERR(dentry);
|
|
if (!IS_ERR(dentry)) {
|
|
/* Why not before? Because we want correct error value */
|
|
if (last.name[last.len])
|
|
goto slashes;
|
|
inode = dentry->d_inode;
|
|
if (d_is_negative(dentry))
|
|
goto slashes;
|
|
ihold(inode);
|
|
error = security_path_unlink(&path, dentry);
|
|
if (error)
|
|
goto exit2;
|
|
error = vfs_unlink(path.dentry->d_inode, dentry, &delegated_inode);
|
|
exit2:
|
|
dput(dentry);
|
|
}
|
|
inode_unlock(path.dentry->d_inode);
|
|
if (inode)
|
|
iput(inode); /* truncate the inode here */
|
|
inode = NULL;
|
|
if (delegated_inode) {
|
|
error = break_deleg_wait(&delegated_inode);
|
|
if (!error)
|
|
goto retry_deleg;
|
|
}
|
|
mnt_drop_write(path.mnt);
|
|
exit1:
|
|
path_put(&path);
|
|
if (retry_estale(error, lookup_flags)) {
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
inode = NULL;
|
|
goto retry;
|
|
}
|
|
putname(name);
|
|
return error;
|
|
|
|
slashes:
|
|
if (d_is_negative(dentry))
|
|
error = -ENOENT;
|
|
else if (d_is_dir(dentry))
|
|
error = -EISDIR;
|
|
else
|
|
error = -ENOTDIR;
|
|
goto exit2;
|
|
}
|
|
|
|
SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag)
|
|
{
|
|
if ((flag & ~AT_REMOVEDIR) != 0)
|
|
return -EINVAL;
|
|
|
|
if (flag & AT_REMOVEDIR)
|
|
return do_rmdir(dfd, getname(pathname));
|
|
return do_unlinkat(dfd, getname(pathname));
|
|
}
|
|
|
|
SYSCALL_DEFINE1(unlink, const char __user *, pathname)
|
|
{
|
|
return do_unlinkat(AT_FDCWD, getname(pathname));
|
|
}
|
|
|
|
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
|
|
{
|
|
int error = may_create(dir, dentry);
|
|
|
|
if (error)
|
|
return error;
|
|
|
|
if (!dir->i_op->symlink)
|
|
return -EPERM;
|
|
|
|
error = security_inode_symlink(dir, dentry, oldname);
|
|
if (error)
|
|
return error;
|
|
|
|
error = dir->i_op->symlink(dir, dentry, oldname);
|
|
if (!error)
|
|
fsnotify_create(dir, dentry);
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL(vfs_symlink);
|
|
|
|
static long do_symlinkat(const char __user *oldname, int newdfd,
|
|
const char __user *newname)
|
|
{
|
|
int error;
|
|
struct filename *from;
|
|
struct dentry *dentry;
|
|
struct path path;
|
|
unsigned int lookup_flags = 0;
|
|
|
|
from = getname(oldname);
|
|
if (IS_ERR(from))
|
|
return PTR_ERR(from);
|
|
retry:
|
|
dentry = user_path_create(newdfd, newname, &path, lookup_flags);
|
|
error = PTR_ERR(dentry);
|
|
if (IS_ERR(dentry))
|
|
goto out_putname;
|
|
|
|
error = security_path_symlink(&path, dentry, from->name);
|
|
if (!error)
|
|
error = vfs_symlink(path.dentry->d_inode, dentry, from->name);
|
|
done_path_create(&path, dentry);
|
|
if (retry_estale(error, lookup_flags)) {
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
goto retry;
|
|
}
|
|
out_putname:
|
|
putname(from);
|
|
return error;
|
|
}
|
|
|
|
SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
|
|
int, newdfd, const char __user *, newname)
|
|
{
|
|
return do_symlinkat(oldname, newdfd, newname);
|
|
}
|
|
|
|
SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newname)
|
|
{
|
|
return do_symlinkat(oldname, AT_FDCWD, newname);
|
|
}
|
|
|
|
/**
|
|
* vfs_link - create a new link
|
|
* @old_dentry: object to be linked
|
|
* @dir: new parent
|
|
* @new_dentry: where to create the new link
|
|
* @delegated_inode: returns inode needing a delegation break
|
|
*
|
|
* The caller must hold dir->i_mutex
|
|
*
|
|
* If vfs_link discovers a delegation on the to-be-linked file in need
|
|
* of breaking, it will return -EWOULDBLOCK and return a reference to the
|
|
* inode in delegated_inode. The caller should then break the delegation
|
|
* and retry. Because breaking a delegation may take a long time, the
|
|
* caller should drop the i_mutex before doing so.
|
|
*
|
|
* Alternatively, a caller may pass NULL for delegated_inode. This may
|
|
* be appropriate for callers that expect the underlying filesystem not
|
|
* to be NFS exported.
|
|
*/
|
|
int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode)
|
|
{
|
|
struct inode *inode = old_dentry->d_inode;
|
|
unsigned max_links = dir->i_sb->s_max_links;
|
|
int error;
|
|
|
|
if (!inode)
|
|
return -ENOENT;
|
|
|
|
error = may_create(dir, new_dentry);
|
|
if (error)
|
|
return error;
|
|
|
|
if (dir->i_sb != inode->i_sb)
|
|
return -EXDEV;
|
|
|
|
/*
|
|
* A link to an append-only or immutable file cannot be created.
|
|
*/
|
|
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
|
|
return -EPERM;
|
|
/*
|
|
* Updating the link count will likely cause i_uid and i_gid to
|
|
* be writen back improperly if their true value is unknown to
|
|
* the vfs.
|
|
*/
|
|
if (HAS_UNMAPPED_ID(inode))
|
|
return -EPERM;
|
|
if (!dir->i_op->link)
|
|
return -EPERM;
|
|
if (S_ISDIR(inode->i_mode))
|
|
return -EPERM;
|
|
|
|
error = security_inode_link(old_dentry, dir, new_dentry);
|
|
if (error)
|
|
return error;
|
|
|
|
inode_lock(inode);
|
|
/* Make sure we don't allow creating hardlink to an unlinked file */
|
|
if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
|
|
error = -ENOENT;
|
|
else if (max_links && inode->i_nlink >= max_links)
|
|
error = -EMLINK;
|
|
else {
|
|
error = try_break_deleg(inode, delegated_inode);
|
|
if (!error)
|
|
error = dir->i_op->link(old_dentry, dir, new_dentry);
|
|
}
|
|
|
|
if (!error && (inode->i_state & I_LINKABLE)) {
|
|
spin_lock(&inode->i_lock);
|
|
inode->i_state &= ~I_LINKABLE;
|
|
spin_unlock(&inode->i_lock);
|
|
}
|
|
inode_unlock(inode);
|
|
if (!error)
|
|
fsnotify_link(dir, inode, new_dentry);
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL_NS(vfs_link, ANDROID_GKI_VFS_EXPORT_ONLY);
|
|
|
|
/*
|
|
* Hardlinks are often used in delicate situations. We avoid
|
|
* security-related surprises by not following symlinks on the
|
|
* newname. --KAB
|
|
*
|
|
* We don't follow them on the oldname either to be compatible
|
|
* with linux 2.0, and to avoid hard-linking to directories
|
|
* and other special files. --ADM
|
|
*/
|
|
static int do_linkat(int olddfd, const char __user *oldname, int newdfd,
|
|
const char __user *newname, int flags)
|
|
{
|
|
struct dentry *new_dentry;
|
|
struct path old_path, new_path;
|
|
struct inode *delegated_inode = NULL;
|
|
int how = 0;
|
|
int error;
|
|
|
|
if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
|
|
return -EINVAL;
|
|
/*
|
|
* To use null names we require CAP_DAC_READ_SEARCH
|
|
* This ensures that not everyone will be able to create
|
|
* handlink using the passed filedescriptor.
|
|
*/
|
|
if (flags & AT_EMPTY_PATH) {
|
|
if (!capable(CAP_DAC_READ_SEARCH))
|
|
return -ENOENT;
|
|
how = LOOKUP_EMPTY;
|
|
}
|
|
|
|
if (flags & AT_SYMLINK_FOLLOW)
|
|
how |= LOOKUP_FOLLOW;
|
|
retry:
|
|
error = user_path_at(olddfd, oldname, how, &old_path);
|
|
if (error)
|
|
return error;
|
|
|
|
new_dentry = user_path_create(newdfd, newname, &new_path,
|
|
(how & LOOKUP_REVAL));
|
|
error = PTR_ERR(new_dentry);
|
|
if (IS_ERR(new_dentry))
|
|
goto out;
|
|
|
|
error = -EXDEV;
|
|
if (old_path.mnt != new_path.mnt)
|
|
goto out_dput;
|
|
error = may_linkat(&old_path);
|
|
if (unlikely(error))
|
|
goto out_dput;
|
|
error = security_path_link(old_path.dentry, &new_path, new_dentry);
|
|
if (error)
|
|
goto out_dput;
|
|
error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry, &delegated_inode);
|
|
out_dput:
|
|
done_path_create(&new_path, new_dentry);
|
|
if (delegated_inode) {
|
|
error = break_deleg_wait(&delegated_inode);
|
|
if (!error) {
|
|
path_put(&old_path);
|
|
goto retry;
|
|
}
|
|
}
|
|
if (retry_estale(error, how)) {
|
|
path_put(&old_path);
|
|
how |= LOOKUP_REVAL;
|
|
goto retry;
|
|
}
|
|
out:
|
|
path_put(&old_path);
|
|
|
|
return error;
|
|
}
|
|
|
|
SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
|
|
int, newdfd, const char __user *, newname, int, flags)
|
|
{
|
|
return do_linkat(olddfd, oldname, newdfd, newname, flags);
|
|
}
|
|
|
|
SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname)
|
|
{
|
|
return do_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
|
|
}
|
|
|
|
/**
|
|
* vfs_rename - rename a filesystem object
|
|
* @old_dir: parent of source
|
|
* @old_dentry: source
|
|
* @new_dir: parent of destination
|
|
* @new_dentry: destination
|
|
* @delegated_inode: returns an inode needing a delegation break
|
|
* @flags: rename flags
|
|
*
|
|
* The caller must hold multiple mutexes--see lock_rename()).
|
|
*
|
|
* If vfs_rename discovers a delegation in need of breaking at either
|
|
* the source or destination, it will return -EWOULDBLOCK and return a
|
|
* reference to the inode in delegated_inode. The caller should then
|
|
* break the delegation and retry. Because breaking a delegation may
|
|
* take a long time, the caller should drop all locks before doing
|
|
* so.
|
|
*
|
|
* Alternatively, a caller may pass NULL for delegated_inode. This may
|
|
* be appropriate for callers that expect the underlying filesystem not
|
|
* to be NFS exported.
|
|
*
|
|
* The worst of all namespace operations - renaming directory. "Perverted"
|
|
* doesn't even start to describe it. Somebody in UCB had a heck of a trip...
|
|
* Problems:
|
|
*
|
|
* a) we can get into loop creation.
|
|
* b) race potential - two innocent renames can create a loop together.
|
|
* That's where 4.4 screws up. Current fix: serialization on
|
|
* sb->s_vfs_rename_mutex. We might be more accurate, but that's another
|
|
* story.
|
|
* c) we have to lock _four_ objects - parents and victim (if it exists),
|
|
* and source (if it is not a directory).
|
|
* And that - after we got ->i_mutex on parents (until then we don't know
|
|
* whether the target exists). Solution: try to be smart with locking
|
|
* order for inodes. We rely on the fact that tree topology may change
|
|
* only under ->s_vfs_rename_mutex _and_ that parent of the object we
|
|
* move will be locked. Thus we can rank directories by the tree
|
|
* (ancestors first) and rank all non-directories after them.
|
|
* That works since everybody except rename does "lock parent, lookup,
|
|
* lock child" and rename is under ->s_vfs_rename_mutex.
|
|
* HOWEVER, it relies on the assumption that any object with ->lookup()
|
|
* has no more than 1 dentry. If "hybrid" objects will ever appear,
|
|
* we'd better make sure that there's no link(2) for them.
|
|
* d) conversion from fhandle to dentry may come in the wrong moment - when
|
|
* we are removing the target. Solution: we will have to grab ->i_mutex
|
|
* in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on
|
|
* ->i_mutex on parents, which works but leads to some truly excessive
|
|
* locking].
|
|
*/
|
|
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
struct inode *new_dir, struct dentry *new_dentry,
|
|
struct inode **delegated_inode, unsigned int flags)
|
|
{
|
|
int error;
|
|
bool is_dir = d_is_dir(old_dentry);
|
|
struct inode *source = old_dentry->d_inode;
|
|
struct inode *target = new_dentry->d_inode;
|
|
bool new_is_dir = false;
|
|
unsigned max_links = new_dir->i_sb->s_max_links;
|
|
struct name_snapshot old_name;
|
|
|
|
if (source == target)
|
|
return 0;
|
|
|
|
error = may_delete(old_dir, old_dentry, is_dir);
|
|
if (error)
|
|
return error;
|
|
|
|
if (!target) {
|
|
error = may_create(new_dir, new_dentry);
|
|
} else {
|
|
new_is_dir = d_is_dir(new_dentry);
|
|
|
|
if (!(flags & RENAME_EXCHANGE))
|
|
error = may_delete(new_dir, new_dentry, is_dir);
|
|
else
|
|
error = may_delete(new_dir, new_dentry, new_is_dir);
|
|
}
|
|
if (error)
|
|
return error;
|
|
|
|
if (!old_dir->i_op->rename)
|
|
return -EPERM;
|
|
|
|
/*
|
|
* If we are going to change the parent - check write permissions,
|
|
* we'll need to flip '..'.
|
|
*/
|
|
if (new_dir != old_dir) {
|
|
if (is_dir) {
|
|
error = inode_permission(source, MAY_WRITE);
|
|
if (error)
|
|
return error;
|
|
}
|
|
if ((flags & RENAME_EXCHANGE) && new_is_dir) {
|
|
error = inode_permission(target, MAY_WRITE);
|
|
if (error)
|
|
return error;
|
|
}
|
|
}
|
|
|
|
error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry,
|
|
flags);
|
|
if (error)
|
|
return error;
|
|
|
|
take_dentry_name_snapshot(&old_name, old_dentry);
|
|
dget(new_dentry);
|
|
if (!is_dir || (flags & RENAME_EXCHANGE))
|
|
lock_two_nondirectories(source, target);
|
|
else if (target)
|
|
inode_lock(target);
|
|
|
|
error = -EBUSY;
|
|
if (is_local_mountpoint(old_dentry) || is_local_mountpoint(new_dentry))
|
|
goto out;
|
|
|
|
if (max_links && new_dir != old_dir) {
|
|
error = -EMLINK;
|
|
if (is_dir && !new_is_dir && new_dir->i_nlink >= max_links)
|
|
goto out;
|
|
if ((flags & RENAME_EXCHANGE) && !is_dir && new_is_dir &&
|
|
old_dir->i_nlink >= max_links)
|
|
goto out;
|
|
}
|
|
if (!is_dir) {
|
|
error = try_break_deleg(source, delegated_inode);
|
|
if (error)
|
|
goto out;
|
|
}
|
|
if (target && !new_is_dir) {
|
|
error = try_break_deleg(target, delegated_inode);
|
|
if (error)
|
|
goto out;
|
|
}
|
|
error = old_dir->i_op->rename(old_dir, old_dentry,
|
|
new_dir, new_dentry, flags);
|
|
if (error)
|
|
goto out;
|
|
|
|
if (!(flags & RENAME_EXCHANGE) && target) {
|
|
if (is_dir) {
|
|
shrink_dcache_parent(new_dentry);
|
|
target->i_flags |= S_DEAD;
|
|
}
|
|
dont_mount(new_dentry);
|
|
detach_mounts(new_dentry);
|
|
}
|
|
if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) {
|
|
if (!(flags & RENAME_EXCHANGE))
|
|
d_move(old_dentry, new_dentry);
|
|
else
|
|
d_exchange(old_dentry, new_dentry);
|
|
}
|
|
out:
|
|
if (!is_dir || (flags & RENAME_EXCHANGE))
|
|
unlock_two_nondirectories(source, target);
|
|
else if (target)
|
|
inode_unlock(target);
|
|
dput(new_dentry);
|
|
if (!error) {
|
|
fsnotify_move(old_dir, new_dir, &old_name.name, is_dir,
|
|
!(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry);
|
|
if (flags & RENAME_EXCHANGE) {
|
|
fsnotify_move(new_dir, old_dir, &old_dentry->d_name,
|
|
new_is_dir, NULL, new_dentry);
|
|
}
|
|
}
|
|
release_dentry_name_snapshot(&old_name);
|
|
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL_NS(vfs_rename, ANDROID_GKI_VFS_EXPORT_ONLY);
|
|
|
|
static int do_renameat2(int olddfd, const char __user *oldname, int newdfd,
|
|
const char __user *newname, unsigned int flags)
|
|
{
|
|
struct dentry *old_dentry, *new_dentry;
|
|
struct dentry *trap;
|
|
struct path old_path, new_path;
|
|
struct qstr old_last, new_last;
|
|
int old_type, new_type;
|
|
struct inode *delegated_inode = NULL;
|
|
struct filename *from;
|
|
struct filename *to;
|
|
unsigned int lookup_flags = 0, target_flags = LOOKUP_RENAME_TARGET;
|
|
bool should_retry = false;
|
|
int error;
|
|
|
|
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
|
|
return -EINVAL;
|
|
|
|
if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT)) &&
|
|
(flags & RENAME_EXCHANGE))
|
|
return -EINVAL;
|
|
|
|
if (flags & RENAME_EXCHANGE)
|
|
target_flags = 0;
|
|
|
|
retry:
|
|
from = filename_parentat(olddfd, getname(oldname), lookup_flags,
|
|
&old_path, &old_last, &old_type);
|
|
if (IS_ERR(from)) {
|
|
error = PTR_ERR(from);
|
|
goto exit;
|
|
}
|
|
|
|
to = filename_parentat(newdfd, getname(newname), lookup_flags,
|
|
&new_path, &new_last, &new_type);
|
|
if (IS_ERR(to)) {
|
|
error = PTR_ERR(to);
|
|
goto exit1;
|
|
}
|
|
|
|
error = -EXDEV;
|
|
if (old_path.mnt != new_path.mnt)
|
|
goto exit2;
|
|
|
|
error = -EBUSY;
|
|
if (old_type != LAST_NORM)
|
|
goto exit2;
|
|
|
|
if (flags & RENAME_NOREPLACE)
|
|
error = -EEXIST;
|
|
if (new_type != LAST_NORM)
|
|
goto exit2;
|
|
|
|
error = mnt_want_write(old_path.mnt);
|
|
if (error)
|
|
goto exit2;
|
|
|
|
retry_deleg:
|
|
trap = lock_rename(new_path.dentry, old_path.dentry);
|
|
|
|
old_dentry = __lookup_hash(&old_last, old_path.dentry, lookup_flags);
|
|
error = PTR_ERR(old_dentry);
|
|
if (IS_ERR(old_dentry))
|
|
goto exit3;
|
|
/* source must exist */
|
|
error = -ENOENT;
|
|
if (d_is_negative(old_dentry))
|
|
goto exit4;
|
|
new_dentry = __lookup_hash(&new_last, new_path.dentry, lookup_flags | target_flags);
|
|
error = PTR_ERR(new_dentry);
|
|
if (IS_ERR(new_dentry))
|
|
goto exit4;
|
|
error = -EEXIST;
|
|
if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry))
|
|
goto exit5;
|
|
if (flags & RENAME_EXCHANGE) {
|
|
error = -ENOENT;
|
|
if (d_is_negative(new_dentry))
|
|
goto exit5;
|
|
|
|
if (!d_is_dir(new_dentry)) {
|
|
error = -ENOTDIR;
|
|
if (new_last.name[new_last.len])
|
|
goto exit5;
|
|
}
|
|
}
|
|
/* unless the source is a directory trailing slashes give -ENOTDIR */
|
|
if (!d_is_dir(old_dentry)) {
|
|
error = -ENOTDIR;
|
|
if (old_last.name[old_last.len])
|
|
goto exit5;
|
|
if (!(flags & RENAME_EXCHANGE) && new_last.name[new_last.len])
|
|
goto exit5;
|
|
}
|
|
/* source should not be ancestor of target */
|
|
error = -EINVAL;
|
|
if (old_dentry == trap)
|
|
goto exit5;
|
|
/* target should not be an ancestor of source */
|
|
if (!(flags & RENAME_EXCHANGE))
|
|
error = -ENOTEMPTY;
|
|
if (new_dentry == trap)
|
|
goto exit5;
|
|
|
|
error = security_path_rename(&old_path, old_dentry,
|
|
&new_path, new_dentry, flags);
|
|
if (error)
|
|
goto exit5;
|
|
error = vfs_rename(old_path.dentry->d_inode, old_dentry,
|
|
new_path.dentry->d_inode, new_dentry,
|
|
&delegated_inode, flags);
|
|
exit5:
|
|
dput(new_dentry);
|
|
exit4:
|
|
dput(old_dentry);
|
|
exit3:
|
|
unlock_rename(new_path.dentry, old_path.dentry);
|
|
if (delegated_inode) {
|
|
error = break_deleg_wait(&delegated_inode);
|
|
if (!error)
|
|
goto retry_deleg;
|
|
}
|
|
mnt_drop_write(old_path.mnt);
|
|
exit2:
|
|
if (retry_estale(error, lookup_flags))
|
|
should_retry = true;
|
|
path_put(&new_path);
|
|
putname(to);
|
|
exit1:
|
|
path_put(&old_path);
|
|
putname(from);
|
|
if (should_retry) {
|
|
should_retry = false;
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
goto retry;
|
|
}
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
|
|
int, newdfd, const char __user *, newname, unsigned int, flags)
|
|
{
|
|
return do_renameat2(olddfd, oldname, newdfd, newname, flags);
|
|
}
|
|
|
|
SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
|
|
int, newdfd, const char __user *, newname)
|
|
{
|
|
return do_renameat2(olddfd, oldname, newdfd, newname, 0);
|
|
}
|
|
|
|
SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname)
|
|
{
|
|
return do_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
|
|
}
|
|
|
|
int readlink_copy(char __user *buffer, int buflen, const char *link)
|
|
{
|
|
int len = PTR_ERR(link);
|
|
if (IS_ERR(link))
|
|
goto out;
|
|
|
|
len = strlen(link);
|
|
if (len > (unsigned) buflen)
|
|
len = buflen;
|
|
if (copy_to_user(buffer, link, len))
|
|
len = -EFAULT;
|
|
out:
|
|
return len;
|
|
}
|
|
|
|
/**
|
|
* vfs_readlink - copy symlink body into userspace buffer
|
|
* @dentry: dentry on which to get symbolic link
|
|
* @buffer: user memory pointer
|
|
* @buflen: size of buffer
|
|
*
|
|
* Does not touch atime. That's up to the caller if necessary
|
|
*
|
|
* Does not call security hook.
|
|
*/
|
|
int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
|
|
{
|
|
struct inode *inode = d_inode(dentry);
|
|
DEFINE_DELAYED_CALL(done);
|
|
const char *link;
|
|
int res;
|
|
|
|
if (unlikely(!(inode->i_opflags & IOP_DEFAULT_READLINK))) {
|
|
if (unlikely(inode->i_op->readlink))
|
|
return inode->i_op->readlink(dentry, buffer, buflen);
|
|
|
|
if (!d_is_symlink(dentry))
|
|
return -EINVAL;
|
|
|
|
spin_lock(&inode->i_lock);
|
|
inode->i_opflags |= IOP_DEFAULT_READLINK;
|
|
spin_unlock(&inode->i_lock);
|
|
}
|
|
|
|
link = READ_ONCE(inode->i_link);
|
|
if (!link) {
|
|
link = inode->i_op->get_link(dentry, inode, &done);
|
|
if (IS_ERR(link))
|
|
return PTR_ERR(link);
|
|
}
|
|
res = readlink_copy(buffer, buflen, link);
|
|
do_delayed_call(&done);
|
|
return res;
|
|
}
|
|
EXPORT_SYMBOL(vfs_readlink);
|
|
|
|
/**
|
|
* vfs_get_link - get symlink body
|
|
* @dentry: dentry on which to get symbolic link
|
|
* @done: caller needs to free returned data with this
|
|
*
|
|
* Calls security hook and i_op->get_link() on the supplied inode.
|
|
*
|
|
* It does not touch atime. That's up to the caller if necessary.
|
|
*
|
|
* Does not work on "special" symlinks like /proc/$$/fd/N
|
|
*/
|
|
const char *vfs_get_link(struct dentry *dentry, struct delayed_call *done)
|
|
{
|
|
const char *res = ERR_PTR(-EINVAL);
|
|
struct inode *inode = d_inode(dentry);
|
|
|
|
if (d_is_symlink(dentry)) {
|
|
res = ERR_PTR(security_inode_readlink(dentry));
|
|
if (!res)
|
|
res = inode->i_op->get_link(dentry, inode, done);
|
|
}
|
|
return res;
|
|
}
|
|
EXPORT_SYMBOL(vfs_get_link);
|
|
|
|
/* get the link contents into pagecache */
|
|
const char *page_get_link(struct dentry *dentry, struct inode *inode,
|
|
struct delayed_call *callback)
|
|
{
|
|
char *kaddr;
|
|
struct page *page;
|
|
struct address_space *mapping = inode->i_mapping;
|
|
|
|
if (!dentry) {
|
|
page = find_get_page(mapping, 0);
|
|
if (!page)
|
|
return ERR_PTR(-ECHILD);
|
|
if (!PageUptodate(page)) {
|
|
put_page(page);
|
|
return ERR_PTR(-ECHILD);
|
|
}
|
|
} else {
|
|
page = read_mapping_page(mapping, 0, NULL);
|
|
if (IS_ERR(page))
|
|
return (char*)page;
|
|
}
|
|
set_delayed_call(callback, page_put_link, page);
|
|
BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM);
|
|
kaddr = page_address(page);
|
|
nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1);
|
|
return kaddr;
|
|
}
|
|
|
|
EXPORT_SYMBOL(page_get_link);
|
|
|
|
void page_put_link(void *arg)
|
|
{
|
|
put_page(arg);
|
|
}
|
|
EXPORT_SYMBOL(page_put_link);
|
|
|
|
int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
|
|
{
|
|
DEFINE_DELAYED_CALL(done);
|
|
int res = readlink_copy(buffer, buflen,
|
|
page_get_link(dentry, d_inode(dentry),
|
|
&done));
|
|
do_delayed_call(&done);
|
|
return res;
|
|
}
|
|
EXPORT_SYMBOL(page_readlink);
|
|
|
|
/*
|
|
* The nofs argument instructs pagecache_write_begin to pass AOP_FLAG_NOFS
|
|
*/
|
|
int __page_symlink(struct inode *inode, const char *symname, int len, int nofs)
|
|
{
|
|
struct address_space *mapping = inode->i_mapping;
|
|
struct page *page;
|
|
void *fsdata;
|
|
int err;
|
|
unsigned int flags = 0;
|
|
if (nofs)
|
|
flags |= AOP_FLAG_NOFS;
|
|
|
|
retry:
|
|
err = pagecache_write_begin(NULL, mapping, 0, len-1,
|
|
flags, &page, &fsdata);
|
|
if (err)
|
|
goto fail;
|
|
|
|
memcpy(page_address(page), symname, len-1);
|
|
|
|
err = pagecache_write_end(NULL, mapping, 0, len-1, len-1,
|
|
page, fsdata);
|
|
if (err < 0)
|
|
goto fail;
|
|
if (err < len-1)
|
|
goto retry;
|
|
|
|
mark_inode_dirty(inode);
|
|
return 0;
|
|
fail:
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL(__page_symlink);
|
|
|
|
int page_symlink(struct inode *inode, const char *symname, int len)
|
|
{
|
|
return __page_symlink(inode, symname, len,
|
|
!mapping_gfp_constraint(inode->i_mapping, __GFP_FS));
|
|
}
|
|
EXPORT_SYMBOL(page_symlink);
|
|
|
|
const struct inode_operations page_symlink_inode_operations = {
|
|
.get_link = page_get_link,
|
|
};
|
|
EXPORT_SYMBOL(page_symlink_inode_operations);
|