* refs/heads/tmp-d2d05bc:
Linux 4.14.190
ath9k: Fix regression with Atheros 9271
ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb
parisc: Add atomic64_set_release() define to avoid CPU soft lockups
io-mapping: indicate mapping failure
mm/memcg: fix refcount error while moving and swapping
Makefile: Fix GCC_TOOLCHAIN_DIR prefix for Clang cross compilation
vt: Reject zero-sized screen buffer size.
fbdev: Detect integer underflow at "struct fbcon_ops"->clear_margins.
serial: 8250_mtk: Fix high-speed baud rates clamping
serial: 8250: fix null-ptr-deref in serial8250_start_tx()
staging: comedi: addi_apci_1564: check INSN_CONFIG_DIGITAL_TRIG shift
staging: comedi: addi_apci_1500: check INSN_CONFIG_DIGITAL_TRIG shift
staging: comedi: ni_6527: fix INSN_CONFIG_DIGITAL_TRIG support
staging: comedi: addi_apci_1032: check INSN_CONFIG_DIGITAL_TRIG shift
staging: wlan-ng: properly check endpoint types
Revert "cifs: Fix the target file was deleted when rename failed."
usb: xhci: Fix ASM2142/ASM3142 DMA addressing
usb: xhci-mtk: fix the failure of bandwidth allocation
binder: Don't use mmput() from shrinker function.
x86: math-emu: Fix up 'cmp' insn for clang ias
arm64: Use test_tsk_thread_flag() for checking TIF_SINGLESTEP
usb: gadget: udc: gr_udc: fix memleak on error handling path in gr_ep_init()
Input: synaptics - enable InterTouch for ThinkPad X1E 1st gen
dmaengine: ioat setting ioat timeout as module parameter
hwmon: (aspeed-pwm-tacho) Avoid possible buffer overflow
regmap: dev_get_regmap_match(): fix string comparison
spi: mediatek: use correct SPI_CFG2_REG MACRO
Input: add `SW_MACHINE_COVER`
dmaengine: tegra210-adma: Fix runtime PM imbalance on error
HID: apple: Disable Fn-key key-re-mapping on clone keyboards
HID: i2c-hid: add Mediacom FlexBook edge13 to descriptor override
scripts/decode_stacktrace: strip basepath from all paths
serial: exar: Fix GPIO configuration for Sealevel cards based on XR17V35X
bonding: check return value of register_netdevice() in bond_newlink()
i2c: rcar: always clear ICSAR to avoid side effects
ipvs: fix the connection sync failed in some cases
mlxsw: destroy workqueue when trap_register in mlxsw_emad_init
bonding: check error value of register_netdevice() immediately
net: smc91x: Fix possible memory leak in smc_drv_probe()
drm: sun4i: hdmi: Fix inverted HPD result
net: dp83640: fix SIOCSHWTSTAMP to update the struct with actual configuration
ax88172a: fix ax88172a_unbind() failures
hippi: Fix a size used in a 'pci_free_consistent()' in an error handling path
bnxt_en: Fix race when modifying pause settings.
btrfs: fix page leaks after failure to lock page for delalloc
btrfs: fix mount failure caused by race with umount
btrfs: fix double free on ulist after backref resolution failure
ASoC: rt5670: Correct RT5670_LDO_SEL_MASK
ALSA: info: Drop WARN_ON() from buffer NULL sanity check
uprobes: Change handle_swbp() to send SIGTRAP with si_code=SI_KERNEL, to fix GDB regression
IB/umem: fix reference count leak in ib_umem_odp_get()
spi: spi-fsl-dspi: Exit the ISR with IRQ_NONE when it's not ours
SUNRPC reverting d03727b248d0 ("NFSv4 fix CLOSE not waiting for direct IO compeletion")
irqdomain/treewide: Keep firmware node unconditionally allocated
drm/nouveau/i2c/g94-: increase NV_PMGR_DP_AUXCTL_TRANSACTREQ timeout
net: sky2: initialize return of gm_phy_read
drivers/net/wan/lapbether: Fixed the value of hard_header_len
xtensa: update *pos in cpuinfo_op.next
xtensa: fix __sync_fetch_and_{and,or}_4 declarations
scsi: scsi_transport_spi: Fix function pointer check
mac80211: allow rx of mesh eapol frames with default rx key
pinctrl: amd: fix npins for uart0 in kerncz_groups
gpio: arizona: put pm_runtime in case of failure
gpio: arizona: handle pm_runtime_get_sync failure case
ANDROID: Incremental fs: magic number compatible 32-bit
ANDROID: kbuild: don't merge .*..compoundliteral in modules
Revert "arm64/alternatives: use subsections for replacement sequences"
Linux 4.14.189
rxrpc: Fix trace string
libceph: don't omit recovery_deletes in target_copy()
x86/cpu: Move x86_cache_bits settings
sched/fair: handle case of task_h_load() returning 0
arm64: ptrace: Override SPSR.SS when single-stepping is enabled
thermal/drivers/cpufreq_cooling: Fix wrong frequency converted from power
misc: atmel-ssc: lock with mutex instead of spinlock
dmaengine: fsl-edma: Fix NULL pointer exception in fsl_edma_tx_handler
intel_th: pci: Add Emmitsburg PCH support
intel_th: pci: Add Tiger Lake PCH-H support
intel_th: pci: Add Jasper Lake CPU support
hwmon: (emc2103) fix unable to change fan pwm1_enable attribute
MIPS: Fix build for LTS kernel caused by backporting lpj adjustment
timer: Fix wheel index calculation on last level
uio_pdrv_genirq: fix use without device tree and no interrupt
Input: i8042 - add Lenovo XiaoXin Air 12 to i8042 nomux list
mei: bus: don't clean driver pointer
Revert "zram: convert remaining CLASS_ATTR() to CLASS_ATTR_RO()"
fuse: Fix parameter for FS_IOC_{GET,SET}FLAGS
virtio: virtio_console: add missing MODULE_DEVICE_TABLE() for rproc serial
USB: serial: option: add Quectel EG95 LTE modem
USB: serial: option: add GosunCn GM500 series
USB: serial: ch341: add new Product ID for CH340
USB: serial: cypress_m8: enable Simply Automated UPB PIM
USB: serial: iuu_phoenix: fix memory corruption
usb: gadget: function: fix missing spinlock in f_uac1_legacy
usb: chipidea: core: add wakeup support for extcon
usb: dwc2: Fix shutdown callback in platform
USB: c67x00: fix use after free in c67x00_giveback_urb
ALSA: usb-audio: Fix race against the error recovery URB submission
ALSA: line6: Perform sanity check for each URB creation
HID: magicmouse: do not set up autorepeat
mtd: rawnand: oxnas: Release all devices in the _remove() path
mtd: rawnand: oxnas: Unregister all devices on error
mtd: rawnand: oxnas: Keep track of registered devices
mtd: rawnand: brcmnand: fix CS0 layout
perf stat: Zero all the 'ena' and 'run' array slot stats for interval mode
copy_xstate_to_kernel: Fix typo which caused GDB regression
ARM: dts: socfpga: Align L2 cache-controller nodename with dtschema
Revert "thermal: mediatek: fix register index error"
staging: comedi: verify array index is correct before using it
usb: gadget: udc: atmel: fix uninitialized read in debug printk
spi: spi-sun6i: sun6i_spi_transfer_one(): fix setting of clock rate
arm64: dts: meson: add missing gxl rng clock
phy: sun4i-usb: fix dereference of pointer phy0 before it is null checked
iio:health:afe4404 Fix timestamp alignment and prevent data leak.
ACPI: video: Use native backlight on Acer TravelMate 5735Z
ACPI: video: Use native backlight on Acer Aspire 5783z
mmc: sdhci: do not enable card detect interrupt for gpio cd type
doc: dt: bindings: usb: dwc3: Update entries for disabling SS instances in park mode
Revert "usb/xhci-plat: Set PM runtime as active on resume"
Revert "usb/ehci-platform: Set PM runtime as active on resume"
Revert "usb/ohci-platform: Fix a warning when hibernating"
of: of_mdio: Correct loop scanning logic
net: dsa: bcm_sf2: Fix node reference count
spi: fix initial SPI_SR value in spi-fsl-dspi
spi: spi-fsl-dspi: Fix lockup if device is shutdown during SPI transfer
iio:health:afe4403 Fix timestamp alignment and prevent data leak.
iio:pressure:ms5611 Fix buffer element alignment
iio: pressure: zpa2326: handle pm_runtime_get_sync failure
iio: mma8452: Add missed iio_device_unregister() call in mma8452_probe()
iio: magnetometer: ak8974: Fix runtime PM imbalance on error
iio:humidity:hdc100x Fix alignment and data leak issues
iio:magnetometer:ak8974: Fix alignment and data leak issues
arm64/alternatives: don't patch up internal branches
arm64: alternative: Use true and false for boolean values
i2c: eg20t: Load module automatically if ID matches
gfs2: read-only mounts should grab the sd_freeze_gl glock
tpm_tis: extra chip->ops check on error path in tpm_tis_core_init
arm64/alternatives: use subsections for replacement sequences
drm/exynos: fix ref count leak in mic_pre_enable
cgroup: Fix sock_cgroup_data on big-endian.
cgroup: fix cgroup_sk_alloc() for sk_clone_lock()
tcp: md5: do not send silly options in SYNCOOKIES
tcp: make sure listeners don't initialize congestion-control state
net_sched: fix a memory leak in atm_tc_init()
tcp: md5: allow changing MD5 keys in all socket states
tcp: md5: refine tcp_md5_do_add()/tcp_md5_hash_key() barriers
tcp: md5: add missing memory barriers in tcp_md5_do_add()/tcp_md5_hash_key()
net: usb: qmi_wwan: add support for Quectel EG95 LTE modem
net: Added pointer check for dst->ops->neigh_lookup in dst_neigh_lookup_skb
llc: make sure applications use ARPHRD_ETHER
l2tp: remove skb_dst_set() from l2tp_xmit_skb()
ipv4: fill fl4_icmp_{type,code} in ping_v4_sendmsg
genetlink: remove genl_bind
s390/mm: fix huge pte soft dirty copying
ARC: elf: use right ELF_ARCH
ARC: entry: fix potential EFA clobber when TIF_SYSCALL_TRACE
dm: use noio when sending kobject event
drm/radeon: fix double free
btrfs: fix fatal extent_buffer readahead vs releasepage race
Revert "ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb"
KVM: x86: Mark CR4.TSD as being possibly owned by the guest
KVM: x86: Inject #GP if guest attempts to toggle CR4.LA57 in 64-bit mode
KVM: x86: bit 8 of non-leaf PDPEs is not reserved
KVM: arm64: Stop clobbering x0 for HVC_SOFT_RESTART
KVM: arm64: Fix definition of PAGE_HYP_DEVICE
ALSA: usb-audio: add quirk for MacroSilicon MS2109
ALSA: hda - let hs_mic be picked ahead of hp_mic
ALSA: opl3: fix infoleak in opl3
mlxsw: spectrum_router: Remove inappropriate usage of WARN_ON()
net: macb: mark device wake capable when "magic-packet" property present
bnxt_en: fix NULL dereference in case SR-IOV configuration fails
nbd: Fix memory leak in nbd_add_socket
arm64: kgdb: Fix single-step exception handling oops
ALSA: compress: fix partial_drain completion state
smsc95xx: avoid memory leak in smsc95xx_bind
smsc95xx: check return value of smsc95xx_reset
net: cxgb4: fix return error value in t4_prep_fw
x86/entry: Increase entry_stack size to a full page
nvme-rdma: assign completion vector correctly
scsi: mptscsih: Fix read sense data size
ARM: imx6: add missing put_device() call in imx6q_suspend_init()
cifs: update ctime and mtime during truncate
s390/kasan: fix early pgm check handler execution
ixgbe: protect ring accesses with READ- and WRITE_ONCE
spi: spidev: fix a potential use-after-free in spidev_release()
spi: spidev: fix a race between spidev_release and spidev_remove
gpu: host1x: Detach driver on unregister
ARM: dts: omap4-droid4: Fix spi configuration and increase rate
spi: spi-fsl-dspi: Fix external abort on interrupt in resume or exit paths
spi: spi-fsl-dspi: use IRQF_SHARED mode to request IRQ
spi: spi-fsl-dspi: Fix lockup if device is removed during SPI transfer
spi: spi-fsl-dspi: Adding shutdown hook
KVM: s390: reduce number of IO pins to 1
UPSTREAM: perf/core: Fix crash when using HW tracing kernel filters
ANDROID: fscrypt: fix DUN contiguity with inline encryption + IV_INO_LBLK_32 policies
ANDROID: f2fs: add back compress inode check
Linux 4.14.188
efi: Make it possible to disable efivar_ssdt entirely
dm zoned: assign max_io_len correctly
irqchip/gic: Atomically update affinity
MIPS: Add missing EHB in mtc0 -> mfc0 sequence for DSPen
cifs: Fix the target file was deleted when rename failed.
SMB3: Honor persistent/resilient handle flags for multiuser mounts
SMB3: Honor 'seal' flag for multiuser mounts
Revert "ALSA: usb-audio: Improve frames size computation"
nfsd: apply umask on fs without ACL support
i2c: algo-pca: Add 0x78 as SCL stuck low status for PCA9665
virtio-blk: free vblk-vqs in error path of virtblk_probe()
drm: sun4i: hdmi: Remove extra HPD polling
hwmon: (acpi_power_meter) Fix potential memory leak in acpi_power_meter_add()
hwmon: (max6697) Make sure the OVERT mask is set correctly
cxgb4: parse TC-U32 key values and masks natively
cxgb4: use unaligned conversion for fetching timestamp
crypto: af_alg - fix use-after-free in af_alg_accept() due to bh_lock_sock()
kgdb: Avoid suspicious RCU usage warning
usb: usbtest: fix missing kfree(dev->buf) in usbtest_disconnect
mm/slub: fix stack overruns with SLUB_STATS
mm/slub.c: fix corrupted freechain in deactivate_slab()
usbnet: smsc95xx: Fix use-after-free after removal
EDAC/amd64: Read back the scrub rate PCI register on F15h
mm: fix swap cache node allocation mask
btrfs: fix data block group relocation failure due to concurrent scrub
btrfs: cow_file_range() num_bytes and disk_num_bytes are same
btrfs: fix a block group ref counter leak after failure to remove block group
UPSTREAM: binder: fix null deref of proc->context
ANDROID: GKI: scripts: Makefile: update the lz4 command (#2)
Linux 4.14.187
Revert "tty: hvc: Fix data abort due to race in hvc_open"
xfs: add agf freeblocks verify in xfs_agf_verify
NFSv4 fix CLOSE not waiting for direct IO compeletion
pNFS/flexfiles: Fix list corruption if the mirror count changes
SUNRPC: Properly set the @subbuf parameter of xdr_buf_subsegment()
sunrpc: fixed rollback in rpc_gssd_dummy_populate()
Staging: rtl8723bs: prevent buffer overflow in update_sta_support_rate()
drm/radeon: fix fb_div check in ni_init_smc_spll_table()
tracing: Fix event trigger to accept redundant spaces
arm64: perf: Report the PC value in REGS_ABI_32 mode
ocfs2: fix panic on nfs server over ocfs2
ocfs2: fix value of OCFS2_INVALID_SLOT
ocfs2: load global_inode_alloc
mm/slab: use memzero_explicit() in kzfree()
btrfs: fix failure of RWF_NOWAIT write into prealloc extent beyond eof
KVM: nVMX: Plumb L2 GPA through to PML emulation
KVM: X86: Fix MSR range of APIC registers in X2APIC mode
ACPI: sysfs: Fix pm_profile_attr type
ALSA: hda: Add NVIDIA codec IDs 9a & 9d through a0 to patch table
blktrace: break out of blktrace setup on concurrent calls
kbuild: improve cc-option to clean up all temporary files
s390/ptrace: fix setting syscall number
net: alx: fix race condition in alx_remove
ata/libata: Fix usage of page address by page_address in ata_scsi_mode_select_xlat function
sched/core: Fix PI boosting between RT and DEADLINE tasks
net: bcmgenet: use hardware padding of runt frames
netfilter: ipset: fix unaligned atomic access
usb: gadget: udc: Potential Oops in error handling code
ARM: imx5: add missing put_device() call in imx_suspend_alloc_ocram()
net: qed: fix excessive QM ILT lines consumption
net: qed: fix NVMe login fails over VFs
net: qed: fix left elements count calculation
RDMA/mad: Fix possible memory leak in ib_mad_post_receive_mads()
ASoC: rockchip: Fix a reference count leak.
RDMA/cma: Protect bind_list and listen_list while finding matching cm id
rxrpc: Fix handling of rwind from an ACK packet
ARM: dts: NSP: Correct FA2 mailbox node
efi/esrt: Fix reference count leak in esre_create_sysfs_entry.
cifs/smb3: Fix data inconsistent when zero file range
cifs/smb3: Fix data inconsistent when punch hole
xhci: Poll for U0 after disabling USB2 LPM
ALSA: usb-audio: Fix OOB access of mixer element list
ALSA: usb-audio: Clean up mixer element list traverse
ALSA: usb-audio: uac1: Invalidate ctl on interrupt
loop: replace kill_bdev with invalidate_bdev
cdc-acm: Add DISABLE_ECHO quirk for Microchip/SMSC chip
xhci: Fix enumeration issue when setting max packet size for FS devices.
xhci: Fix incorrect EP_STATE_MASK
ALSA: usb-audio: add quirk for Denon DCD-1500RE
usb: host: ehci-exynos: Fix error check in exynos_ehci_probe()
usb: host: xhci-mtk: avoid runtime suspend when removing hcd
USB: ehci: reopen solution for Synopsys HC bug
usb: add USB_QUIRK_DELAY_INIT for Logitech C922
usb: dwc2: Postponed gadget registration to the udc class driver
USB: ohci-sm501: Add missed iounmap() in remove
net: core: reduce recursion limit value
net: Do not clear the sock TX queue in sk_set_socket()
net: Fix the arp error in some cases
ip6_gre: fix use-after-free in ip6gre_tunnel_lookup()
tcp_cubic: fix spurious HYSTART_DELAY exit upon drop in min RTT
ip_tunnel: fix use-after-free in ip_tunnel_lookup()
tg3: driver sleeps indefinitely when EEH errors exceed eeh_max_freezes
tcp: grow window for OOO packets only for SACK flows
sctp: Don't advertise IPv4 addresses if ipv6only is set on the socket
rxrpc: Fix notification call on completion of discarded calls
rocker: fix incorrect error handling in dma_rings_init
net: usb: ax88179_178a: fix packet alignment padding
net: fix memleak in register_netdevice()
net: bridge: enfore alignment for ethernet address
mld: fix memory leak in ipv6_mc_destroy_dev()
ibmveth: Fix max MTU limit
apparmor: don't try to replace stale label in ptraceme check
fix a braino in "sparc32: fix register window handling in genregs32_[gs]et()"
net: sched: export __netdev_watchdog_up()
block/bio-integrity: don't free 'buf' if bio_integrity_add_page() failed
net: be more gentle about silly gso requests coming from user
scsi: scsi_devinfo: handle non-terminated strings
ANDROID: Makefile: append BUILD_NUMBER to version string when defined
Linux 4.14.186
KVM: x86/mmu: Set mmio_value to '0' if reserved #PF can't be generated
kvm: x86: Fix reserved bits related calculation errors caused by MKTME
kvm: x86: Move kvm_set_mmio_spte_mask() from x86.c to mmu.c
md: add feature flag MD_FEATURE_RAID0_LAYOUT
net: core: device_rename: Use rwsem instead of a seqcount
sched/rt, net: Use CONFIG_PREEMPTION.patch
kretprobe: Prevent triggering kretprobe from within kprobe_flush_task
e1000e: Do not wake up the system via WOL if device wakeup is disabled
kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex
crypto: algboss - don't wait during notifier callback
crypto: algif_skcipher - Cap recv SG list at ctx->used
mtd: rawnand: tmio: Fix the probe error path
mtd: rawnand: mtk: Fix the probe error path
mtd: rawnand: plat_nand: Fix the probe error path
mtd: rawnand: socrates: Fix the probe error path
mtd: rawnand: oxnas: Fix the probe error path
mtd: rawnand: oxnas: Add of_node_put()
mtd: rawnand: orion: Fix the probe error path
mtd: rawnand: xway: Fix the probe error path
mtd: rawnand: sharpsl: Fix the probe error path
mtd: rawnand: diskonchip: Fix the probe error path
mtd: rawnand: Pass a nand_chip object to nand_release()
block: nr_sects_write(): Disable preemption on seqcount write
x86/boot/compressed: Relax sed symbol type regex for LLVM ld.lld
drm/dp_mst: Increase ACT retry timeout to 3s
ext4: fix partial cluster initialization when splitting extent
selinux: fix double free
drm/qxl: Use correct notify port address when creating cursor ring
drm/dp_mst: Reformat drm_dp_check_act_status() a bit
drm: encoder_slave: fix refcouting error for modules
libata: Use per port sync for detach
arm64: hw_breakpoint: Don't invoke overflow handler on uaccess watchpoints
block: Fix use-after-free in blkdev_get()
bcache: fix potential deadlock problem in btree_gc_coalesce
perf report: Fix NULL pointer dereference in hists__fprintf_nr_sample_events()
usb/ehci-platform: Set PM runtime as active on resume
usb/xhci-plat: Set PM runtime as active on resume
scsi: acornscsi: Fix an error handling path in acornscsi_probe()
drm/sun4i: hdmi ddc clk: Fix size of m divider
selftests/net: in timestamping, strncpy needs to preserve null byte
gfs2: fix use-after-free on transaction ail lists
blktrace: fix endianness for blk_log_remap()
blktrace: fix endianness in get_pdu_int()
blktrace: use errno instead of bi_status
selftests/vm/pkeys: fix alloc_random_pkey() to make it really random
elfnote: mark all .note sections SHF_ALLOC
include/linux/bitops.h: avoid clang shift-count-overflow warnings
lib/zlib: remove outdated and incorrect pre-increment optimization
geneve: change from tx_error to tx_dropped on missing metadata
crypto: omap-sham - add proper load balancing support for multicore
pinctrl: freescale: imx: Fix an error handling path in 'imx_pinctrl_probe()'
pinctrl: imxl: Fix an error handling path in 'imx1_pinctrl_core_probe()'
scsi: ufs: Don't update urgent bkops level when toggling auto bkops
scsi: iscsi: Fix reference count leak in iscsi_boot_create_kobj
gfs2: Allow lock_nolock mount to specify jid=X
openrisc: Fix issue with argument clobbering for clone/fork
vfio/mdev: Fix reference count leak in add_mdev_supported_type
ASoC: fsl_asrc_dma: Fix dma_chan leak when config DMA channel failed
extcon: adc-jack: Fix an error handling path in 'adc_jack_probe()'
powerpc/4xx: Don't unmap NULL mbase
NFSv4.1 fix rpc_call_done assignment for BIND_CONN_TO_SESSION
net: sunrpc: Fix off-by-one issues in 'rpc_ntop6'
scsi: ufs-qcom: Fix scheduling while atomic issue
clk: bcm2835: Fix return type of bcm2835_register_gate
x86/apic: Make TSC deadline timer detection message visible
usb: gadget: Fix issue with config_ep_by_speed function
usb: gadget: fix potential double-free in m66592_probe.
usb: gadget: lpc32xx_udc: don't dereference ep pointer before null check
USB: gadget: udc: s3c2410_udc: Remove pointless NULL check in s3c2410_udc_nuke
usb: dwc2: gadget: move gadget resume after the core is in L0 state
watchdog: da9062: No need to ping manually before setting timeout
IB/cma: Fix ports memory leak in cma_configfs
PCI/PTM: Inherit Switch Downstream Port PTM settings from Upstream Port
dm zoned: return NULL if dmz_get_zone_for_reclaim() fails to find a zone
powerpc/64s/pgtable: fix an undefined behaviour
clk: samsung: exynos5433: Add IGNORE_UNUSED flag to sclk_i2s1
tty: n_gsm: Fix bogus i++ in gsm_data_kick
USB: host: ehci-mxc: Add error handling in ehci_mxc_drv_probe()
drm/msm/mdp5: Fix mdp5_init error path for failed mdp5_kms allocation
usb/ohci-platform: Fix a warning when hibernating
vfio-pci: Mask cap zero
powerpc/ps3: Fix kexec shutdown hang
powerpc/pseries/ras: Fix FWNMI_VALID off by one
tty: n_gsm: Fix waking up upper tty layer when room available
tty: n_gsm: Fix SOF skipping
PCI: Fix pci_register_host_bridge() device_register() error handling
clk: ti: composite: fix memory leak
dlm: remove BUG() before panic()
scsi: mpt3sas: Fix double free warnings
power: supply: smb347-charger: IRQSTAT_D is volatile
power: supply: lp8788: Fix an error handling path in 'lp8788_charger_probe()'
scsi: qla2xxx: Fix warning after FC target reset
PCI/ASPM: Allow ASPM on links to PCIe-to-PCI/PCI-X Bridges
PCI: rcar: Fix incorrect programming of OB windows
drivers: base: Fix NULL pointer exception in __platform_driver_probe() if a driver developer is foolish
serial: amba-pl011: Make sure we initialize the port.lock spinlock
i2c: pxa: fix i2c_pxa_scream_blue_murder() debug output
staging: sm750fb: add missing case while setting FB_VISUAL
thermal/drivers/ti-soc-thermal: Avoid dereferencing ERR_PTR
tty: hvc: Fix data abort due to race in hvc_open
s390/qdio: put thinint indicator after early error
ALSA: usb-audio: Improve frames size computation
scsi: qedi: Do not flush offload work if ARP not resolved
staging: greybus: fix a missing-check bug in gb_lights_light_config()
scsi: ibmvscsi: Don't send host info in adapter info MAD after LPM
scsi: sr: Fix sr_probe() missing deallocate of device minor
apparmor: fix introspection of of task mode for unconfined tasks
mksysmap: Fix the mismatch of '.L' symbols in System.map
NTB: Fix the default port and peer numbers for legacy drivers
yam: fix possible memory leak in yam_init_driver
powerpc/crashkernel: Take "mem=" option into account
nfsd: Fix svc_xprt refcnt leak when setup callback client failed
powerpc/perf/hv-24x7: Fix inconsistent output values incase multiple hv-24x7 events run
clk: clk-flexgen: fix clock-critical handling
scsi: lpfc: Fix lpfc_nodelist leak when processing unsolicited event
mfd: wm8994: Fix driver operation if loaded as modules
m68k/PCI: Fix a memory leak in an error handling path
vfio/pci: fix memory leaks in alloc_perm_bits()
ps3disk: use the default segment boundary
PCI: aardvark: Don't blindly enable ASPM L0s and don't write to read-only register
dm mpath: switch paths in dm_blk_ioctl() code path
usblp: poison URBs upon disconnect
i2c: pxa: clear all master action bits in i2c_pxa_stop_message()
f2fs: report delalloc reserve as non-free in statfs for project quota
iio: bmp280: fix compensation of humidity
scsi: qla2xxx: Fix issue with adapter's stopping state
ALSA: isa/wavefront: prevent out of bounds write in ioctl
scsi: qedi: Check for buffer overflow in qedi_set_path()
ARM: integrator: Add some Kconfig selections
ASoC: davinci-mcasp: Fix dma_chan refcnt leak when getting dma type
backlight: lp855x: Ensure regulators are disabled on probe failure
clk: qcom: msm8916: Fix the address location of pll->config_reg
remoteproc: Fix IDR initialisation in rproc_alloc()
iio: pressure: bmp280: Tolerate IRQ before registering
i2c: piix4: Detect secondary SMBus controller on AMD AM4 chipsets
clk: sunxi: Fix incorrect usage of round_down()
power: supply: bq24257_charger: Replace depends on REGMAP_I2C with select
drm/i915: Whitelist context-local timestamp in the gen9 cmdparser
s390: fix syscall_get_error for compat processes
ANDROID: ext4: Optimize match for casefolded encrypted dirs
ANDROID: ext4: Handle casefolding with encryption
ANDROID: cuttlefish_defconfig: x86: Enable KERNEL_LZ4
ANDROID: GKI: scripts: Makefile: update the lz4 command
FROMLIST: f2fs: fix use-after-free when accessing bio->bi_crypt_context
Linux 4.14.185
perf symbols: Fix debuginfo search for Ubuntu
perf probe: Fix to check blacklist address correctly
perf probe: Do not show the skipped events
w1: omap-hdq: cleanup to add missing newline for some dev_dbg
mtd: rawnand: pasemi: Fix the probe error path
mtd: rawnand: brcmnand: fix hamming oob layout
sunrpc: clean up properly in gss_mech_unregister()
sunrpc: svcauth_gss_register_pseudoflavor must reject duplicate registrations.
kbuild: force to build vmlinux if CONFIG_MODVERSION=y
powerpc/64s: Save FSCR to init_task.thread.fscr after feature init
powerpc/64s: Don't let DT CPU features set FSCR_DSCR
drivers/macintosh: Fix memleak in windfarm_pm112 driver
ARM: tegra: Correct PL310 Auxiliary Control Register initialization
kernel/cpu_pm: Fix uninitted local in cpu_pm
dm crypt: avoid truncating the logical block size
sparc64: fix misuses of access_process_vm() in genregs32_[sg]et()
sparc32: fix register window handling in genregs32_[gs]et()
pinctrl: samsung: Save/restore eint_mask over suspend for EINT_TYPE GPIOs
power: vexpress: add suppress_bind_attrs to true
igb: Report speed and duplex as unknown when device is runtime suspended
media: ov5640: fix use of destroyed mutex
b43_legacy: Fix connection problem with WPA3
b43: Fix connection problem with WPA3
b43legacy: Fix case where channel status is corrupted
media: go7007: fix a miss of snd_card_free
carl9170: remove P2P_GO support
e1000e: Relax condition to trigger reset for ME workaround
e1000e: Disable TSO for buffer overrun workaround
PCI: Program MPS for RCiEP devices
blk-mq: move _blk_mq_update_nr_hw_queues synchronize_rcu call
btrfs: fix wrong file range cleanup after an error filling dealloc range
btrfs: fix error handling when submitting direct I/O bio
PCI: Unify ACS quirk desired vs provided checking
PCI: Add ACS quirk for Intel Root Complex Integrated Endpoints
PCI: Generalize multi-function power dependency device links
vga_switcheroo: Use device link for HDA controller
vga_switcheroo: Deduplicate power state tracking
PCI: Make ACS quirk implementations more uniform
PCI: Add ACS quirk for Ampere root ports
PCI: Add ACS quirk for iProc PAXB
PCI: Avoid FLR for AMD Starship USB 3.0
PCI: Avoid FLR for AMD Matisse HD Audio & USB 3.0
PCI: Disable MSI for Freescale Layerscape PCIe RC mode
ext4: fix race between ext4_sync_parent() and rename()
ext4: fix error pointer dereference
ext4: fix EXT_MAX_EXTENT/INDEX to check for zeroed eh_max
evm: Fix possible memory leak in evm_calc_hmac_or_hash()
ima: Directly assign the ima_default_policy pointer to ima_rules
ima: Fix ima digest hash table key calculation
mm: thp: make the THP mapcount atomic against __split_huge_pmd_locked()
btrfs: send: emit file capabilities after chown
string.h: fix incompatibility between FORTIFY_SOURCE and KASAN
platform/x86: hp-wmi: Convert simple_strtoul() to kstrtou32()
cpuidle: Fix three reference count leaks
spi: dw: Return any value retrieved from the dma_transfer callback
mmc: sdhci-esdhc-imx: fix the mask for tuning start point
ixgbe: fix signed-integer-overflow warning
mmc: via-sdmmc: Respect the cmd->busy_timeout from the mmc core
staging: greybus: sdio: Respect the cmd->busy_timeout from the mmc core
mmc: sdhci-msm: Set SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 quirk
MIPS: Fix IRQ tracing when call handle_fpe() and handle_msa_fpe()
PCI: Don't disable decoding when mmio_always_on is set
macvlan: Skip loopback packets in RX handler
m68k: mac: Don't call via_flush_cache() on Mac IIfx
x86/mm: Stop printing BRK addresses
mips: Add udelay lpj numbers adjustment
mips: MAAR: Use more precise address mask
x86/boot: Correct relocation destination on old linkers
mwifiex: Fix memory corruption in dump_station
rtlwifi: Fix a double free in _rtl_usb_tx_urb_setup()
md: don't flush workqueue unconditionally in md_open
net: qed*: Reduce RX and TX default ring count when running inside kdump kernel
wcn36xx: Fix error handling path in 'wcn36xx_probe()'
nvme: refine the Qemu Identify CNS quirk
kgdb: Fix spurious true from in_dbg_master()
mips: cm: Fix an invalid error code of INTVN_*_ERR
MIPS: Truncate link address into 32bit for 32bit kernel
Crypto/chcr: fix for ccm(aes) failed test
powerpc/spufs: fix copy_to_user while atomic
net: allwinner: Fix use correct return type for ndo_start_xmit()
media: cec: silence shift wrapping warning in __cec_s_log_addrs()
net: lpc-enet: fix error return code in lpc_mii_init()
exit: Move preemption fixup up, move blocking operations down
lib/mpi: Fix 64-bit MIPS build with Clang
net: bcmgenet: set Rx mode before starting netif
netfilter: nft_nat: return EOPNOTSUPP if type or flags are not supported
audit: fix a net reference leak in audit_list_rules_send()
MIPS: Make sparse_init() using top-down allocation
media: platform: fcp: Set appropriate DMA parameters
media: dvb: return -EREMOTEIO on i2c transfer failure.
audit: fix a net reference leak in audit_send_reply()
dt-bindings: display: mediatek: control dpi pins mode to avoid leakage
e1000: Distribute switch variables for initialization
tools api fs: Make xxx__mountpoint() more scalable
brcmfmac: fix wrong location to get firmware feature
staging: android: ion: use vmap instead of vm_map_ram
net: vmxnet3: fix possible buffer overflow caused by bad DMA value in vmxnet3_get_rss()
x86/kvm/hyper-v: Explicitly align hcall param for kvm_hyperv_exit
spi: dw: Fix Rx-only DMA transfers
ARM: 8978/1: mm: make act_mm() respect THREAD_SIZE
btrfs: do not ignore error from btrfs_next_leaf() when inserting checksums
clocksource: dw_apb_timer_of: Fix missing clockevent timers
clocksource: dw_apb_timer: Make CPU-affiliation being optional
spi: dw: Enable interrupts in accordance with DMA xfer mode
kgdb: Prevent infinite recursive entries to the debugger
Bluetooth: Add SCO fallback for invalid LMP parameters error
MIPS: Loongson: Build ATI Radeon GPU driver as module
ixgbe: Fix XDP redirect on archs with PAGE_SIZE above 4K
spi: dw: Zero DMA Tx and Rx configurations on stack
net: ena: fix error returning in ena_com_get_hash_function()
spi: pxa2xx: Apply CS clk quirk to BXT
objtool: Ignore empty alternatives
media: si2157: Better check for running tuner in init
crypto: ccp -- don't "select" CONFIG_DMADEVICES
drm: bridge: adv7511: Extend list of audio sample rates
ACPI: GED: use correct trigger type field in _Exx / _Lxx handling
xen/pvcalls-back: test for errors when calling backend_connect()
can: kvaser_usb: kvaser_usb_leaf: Fix some info-leaks to USB devices
mmc: sdio: Fix potential NULL pointer error in mmc_sdio_init_card()
mmc: sdhci-msm: Clear tuning done flag while hs400 tuning
agp/intel: Reinforce the barrier after GTT updates
perf: Add cond_resched() to task_function_call()
fat: don't allow to mount if the FAT length == 0
mm/slub: fix a memory leak in sysfs_slab_add()
Smack: slab-out-of-bounds in vsscanf
ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb
ath9x: Fix stack-out-of-bounds Write in ath9k_hif_usb_rx_cb
ath9k: Fix use-after-free Write in ath9k_htc_rx_msg
ath9k: Fix use-after-free Read in ath9k_wmi_ctrl_rx
KVM: arm64: Make vcpu_cp1x() work on Big Endian hosts
KVM: MIPS: Fix VPN2_MASK definition for variable cpu_vmbits
KVM: MIPS: Define KVM_ENTRYHI_ASID to cpu_asid_mask(&boot_cpu_data)
KVM: nVMX: Consult only the "basic" exit reason when routing nested exit
KVM: nSVM: leave ASID aside in copy_vmcb_control_area
KVM: nSVM: fix condition for filtering async PF
video: fbdev: w100fb: Fix a potential double free.
proc: Use new_inode not new_inode_pseudo
ovl: initialize error in ovl_copy_xattr
selftests/net: in rxtimestamp getopt_long needs terminating null entry
crypto: virtio: Fix dest length calculation in __virtio_crypto_skcipher_do_req()
crypto: virtio: Fix src/dst scatterlist calculation in __virtio_crypto_skcipher_do_req()
crypto: virtio: Fix use-after-free in virtio_crypto_skcipher_finalize_req()
spi: bcm2835: Fix controller unregister order
spi: pxa2xx: Fix controller unregister order
spi: Fix controller unregister order
spi: No need to assign dummy value in spi_unregister_controller()
spi: dw: Fix controller unregister order
spi: dw: fix possible race condition
x86/speculation: PR_SPEC_FORCE_DISABLE enforcement for indirect branches.
x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS.
x86/speculation: Add support for STIBP always-on preferred mode
x86/speculation: Change misspelled STIPB to STIBP
KVM: x86: only do L1TF workaround on affected processors
KVM: x86/mmu: Consolidate "is MMIO SPTE" code
kvm: x86: Fix L1TF mitigation for shadow MMU
ALSA: pcm: disallow linking stream to itself
crypto: cavium/nitrox - Fix 'nitrox_get_first_device()' when ndevlist is fully iterated
spi: bcm-qspi: when tx/rx buffer is NULL set to 0
spi: bcm2835aux: Fix controller unregister order
nilfs2: fix null pointer dereference at nilfs_segctor_do_construct()
cgroup, blkcg: Prepare some symbols for module and !CONFIG_CGROUP usages
ACPI: PM: Avoid using power resources if there are none for D0
ACPI: GED: add support for _Exx / _Lxx handler methods
ACPI: CPPC: Fix reference count leak in acpi_cppc_processor_probe()
ACPI: sysfs: Fix reference count leak in acpi_sysfs_add_hotplug_profile()
ALSA: usb-audio: Fix inconsistent card PM state after resume
ALSA: hda/realtek - add a pintbl quirk for several Lenovo machines
ALSA: es1688: Add the missed snd_card_free()
efi/efivars: Add missing kobject_put() in sysfs entry creation error path
x86/reboot/quirks: Add MacBook6,1 reboot quirk
x86/speculation: Prevent rogue cross-process SSBD shutdown
x86/PCI: Mark Intel C620 MROMs as having non-compliant BARs
x86_64: Fix jiffies ODR violation
mm: add kvfree_sensitive() for freeing sensitive data objects
perf probe: Accept the instance number of kretprobe event
ath9k_htc: Silence undersized packet warnings
powerpc/xive: Clear the page tables for the ESB IO mapping
drivers/net/ibmvnic: Update VNIC protocol version reporting
Input: synaptics - add a second working PNP_ID for Lenovo T470s
sched/fair: Don't NUMA balance for kthreads
ARM: 8977/1: ptrace: Fix mask for thumb breakpoint hook
crypto: talitos - fix ECB and CBC algs ivsize
serial: imx: Fix handling of TC irq in combination with DMA
lib: Reduce user_access_begin() boundaries in strncpy_from_user() and strnlen_user()
x86: uaccess: Inhibit speculation past access_ok() in user_access_begin()
arch/openrisc: Fix issues with access_ok()
Fix 'acccess_ok()' on alpha and SH
make 'user_access_begin()' do 'access_ok()'
vxlan: Avoid infinite loop when suppressing NS messages with invalid options
ipv6: fix IPV6_ADDRFORM operation logic
writeback: Drop I_DIRTY_TIME_EXPIRE
writeback: Fix sync livelock due to b_dirty_time processing
writeback: Avoid skipping inode writeback
writeback: Protect inode->i_io_list with inode->i_lock
Revert "writeback: Avoid skipping inode writeback"
ANDROID: Enable LZ4_RAMDISK
fscrypt: remove stale definition
fs-verity: remove unnecessary extern keywords
fs-verity: fix all kerneldoc warnings
fscrypt: add support for IV_INO_LBLK_32 policies
fscrypt: make test_dummy_encryption use v2 by default
fscrypt: support test_dummy_encryption=v2
fscrypt: add fscrypt_add_test_dummy_key()
linux/parser.h: add include guards
fscrypt: remove unnecessary extern keywords
fscrypt: name all function parameters
fscrypt: fix all kerneldoc warnings
ANDROID: kbuild: merge more sections with LTO
Linux 4.14.184
uprobes: ensure that uprobe->offset and ->ref_ctr_offset are properly aligned
iio: vcnl4000: Fix i2c swapped word reading.
x86/speculation: Add Ivy Bridge to affected list
x86/speculation: Add SRBDS vulnerability and mitigation documentation
x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation
x86/cpu: Add 'table' argument to cpu_matches()
x86/cpu: Add a steppings field to struct x86_cpu_id
nvmem: qfprom: remove incorrect write support
CDC-ACM: heed quirk also in error handling
staging: rtl8712: Fix IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK
tty: hvc_console, fix crashes on parallel open/close
vt: keyboard: avoid signed integer overflow in k_ascii
usb: musb: Fix runtime PM imbalance on error
usb: musb: start session in resume for host port
USB: serial: option: add Telit LE910C1-EUX compositions
USB: serial: usb_wwan: do not resubmit rx urb on fatal errors
USB: serial: qcserial: add DW5816e QDL support
l2tp: add sk_family checks to l2tp_validate_socket
net: check untrusted gso_size at kernel entry
vsock: fix timeout in vsock_accept()
NFC: st21nfca: add missed kfree_skb() in an error path
net: usb: qmi_wwan: add Telit LE910C1-EUX composition
l2tp: do not use inet_hash()/inet_unhash()
devinet: fix memleak in inetdev_init()
airo: Fix read overflows sending packets
scsi: ufs: Release clock if DMA map fails
mmc: fix compilation of user API
kernel/relay.c: handle alloc_percpu returning NULL in relay_open
p54usb: add AirVasT USB stick device-id
HID: i2c-hid: add Schneider SCL142ALM to descriptor override
HID: sony: Fix for broken buttons on DS3 USB dongles
mm: Fix mremap not considering huge pmd devmap
net: smsc911x: Fix runtime PM imbalance on error
net: ethernet: stmmac: Enable interface clocks on probe for IPQ806x
net/ethernet/freescale: rework quiesce/activate for ucc_geth
net: bmac: Fix read of MAC address from ROM
x86/mmiotrace: Use cpumask_available() for cpumask_var_t variables
i2c: altera: Fix race between xfer_msg and isr thread
ARC: [plat-eznps]: Restrict to CONFIG_ISA_ARCOMPACT
ARC: Fix ICCM & DCCM runtime size checks
pppoe: only process PADT targeted at local interfaces
s390/ftrace: save traced function caller
spi: dw: use "smp_mb()" to avoid sending spi data error
scsi: hisi_sas: Check sas_port before using it
libnvdimm: Fix endian conversion issues
scsi: scsi_devinfo: fixup string compare
ANDROID: Incremental fs: Remove dependency on PKCS7_MESSAGE_PARSER
f2fs: attach IO flags to the missing cases
f2fs: add node_io_flag for bio flags likewise data_io_flag
f2fs: remove unused parameter of f2fs_put_rpages_mapping()
f2fs: handle readonly filesystem in f2fs_ioc_shutdown()
f2fs: avoid utf8_strncasecmp() with unstable name
f2fs: don't return vmalloc() memory from f2fs_kmalloc()
ANDROID: dm-bow: Add block_size option
ANDROID: Incremental fs: Cache successful hash calculations
ANDROID: Incremental fs: Fix four error-path bugs
ANDROID: cuttlefish_defconfig: Disable CMOS RTC driver
f2fs: fix retry logic in f2fs_write_cache_pages()
ANDROID: modules: fix lockprove warning
BACKPORT: arm64: vdso: Explicitly add build-id option
BACKPORT: arm64: vdso: use $(LD) instead of $(CC) to link VDSO
Linux 4.14.183
scsi: zfcp: fix request object use-after-free in send path causing wrong traces
genirq/generic_pending: Do not lose pending affinity update
net: hns: Fixes the missing put_device in positive leg for roce reset
net: hns: fix unsigned comparison to less than zero
KVM: VMX: check for existence of secondary exec controls before accessing
rxrpc: Fix transport sockopts to get IPv4 errors on an IPv6 socket
sc16is7xx: move label 'err_spi' to correct section
mm/vmalloc.c: don't dereference possible NULL pointer in __vunmap()
netfilter: nf_conntrack_pptp: fix compilation warning with W=1 build
bonding: Fix reference count leak in bond_sysfs_slave_add.
qlcnic: fix missing release in qlcnic_83xx_interrupt_test.
esp6: get the right proto for transport mode in esp6_gso_encap
netfilter: nf_conntrack_pptp: prevent buffer overflows in debug code
netfilter: nfnetlink_cthelper: unbreak userspace helper support
netfilter: ipset: Fix subcounter update skip
netfilter: nft_reject_bridge: enable reject with bridge vlan
ip_vti: receive ipip packet by calling ip_tunnel_rcv
vti4: eliminated some duplicate code.
xfrm: fix error in comment
xfrm: fix a NULL-ptr deref in xfrm_local_error
xfrm: fix a warning in xfrm_policy_insert_list
xfrm: call xfrm_output_gso when inner_protocol is set in xfrm_output
xfrm: allow to accept packets with ipv6 NEXTHDR_HOP in xfrm_input
copy_xstate_to_kernel(): don't leave parts of destination uninitialized
x86/dma: Fix max PFN arithmetic overflow on 32 bit systems
mac80211: mesh: fix discovery timer re-arming issue / crash
parisc: Fix kernel panic in mem_init()
iommu: Fix reference count leak in iommu_group_alloc.
include/asm-generic/topology.h: guard cpumask_of_node() macro argument
fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info()
mm: remove VM_BUG_ON(PageSlab()) from page_mapcount()
libceph: ignore pool overlay and cache logic on redirects
ALSA: hda/realtek - Add new codec supported for ALC287
exec: Always set cap_ambient in cap_bprm_set_creds
ALSA: usb-audio: mixer: volume quirk for ESS Technology Asus USB DAC
ALSA: hwdep: fix a left shifting 1 by 31 UB bug
RDMA/pvrdma: Fix missing pci disable in pvrdma_pci_probe()
mmc: block: Fix use-after-free issue for rpmb
ARM: dts: bcm2835-rpi-zero-w: Fix led polarity
ARM: dts/imx6q-bx50v3: Set display interface clock parents
ARM: dts: imx6q-bx50v3: Add internal switch
IB/qib: Call kobject_put() when kobject_init_and_add() fails
gpio: exar: Fix bad handling for ida_simple_get error path
ARM: uaccess: fix DACR mismatch with nested exceptions
ARM: uaccess: integrate uaccess_save and uaccess_restore
ARM: uaccess: consolidate uaccess asm to asm/uaccess-asm.h
ARM: 8843/1: use unified assembler in headers
Input: synaptics-rmi4 - fix error return code in rmi_driver_probe()
Input: synaptics-rmi4 - really fix attn_data use-after-free
Input: i8042 - add ThinkPad S230u to i8042 reset list
Input: dlink-dir685-touchkeys - fix a typo in driver name
Input: xpad - add custom init packet for Xbox One S controllers
Input: evdev - call input_flush_device() on release(), not flush()
Input: usbtouchscreen - add support for BonXeon TP
samples: bpf: Fix build error
cifs: Fix null pointer check in cifs_read
net: freescale: select CONFIG_FIXED_PHY where needed
usb: gadget: legacy: fix redundant initialization warnings
cachefiles: Fix race between read_waiter and read_copier involving op->to_do
gfs2: move privileged user check to gfs2_quota_lock_check
net: microchip: encx24j600: add missed kthread_stop
gpio: tegra: mask GPIO IRQs during IRQ shutdown
ARM: dts: rockchip: fix pinctrl sub nodename for spi in rk322x.dtsi
arm64: dts: rockchip: swap interrupts interrupt-names rk3399 gpu node
ARM: dts: rockchip: fix phy nodename for rk3228-evb
net/mlx4_core: fix a memory leak bug.
net: sun: fix missing release regions in cas_init_one().
net: qrtr: Fix passing invalid reference to qrtr_local_enqueue()
net/mlx5e: Update netdev txq on completions during closure
sctp: Start shutdown on association restart if in SHUTDOWN-SENT state and socket is closed
r8152: support additional Microsoft Surface Ethernet Adapter variant
net sched: fix reporting the first-time use timestamp
net: revert "net: get rid of an signed integer overflow in ip_idents_reserve()"
net/mlx5: Add command entry handling completion
net: ipip: fix wrong address family in init error path
ax25: fix setsockopt(SO_BINDTODEVICE)
ANDROID: scs: fix recursive spinlock in scs_check_usage
ANDROID: timer: fix timer_setup with CFI
FROMGIT: USB: dummy-hcd: use configurable endpoint naming scheme
UPSTREAM: USB: dummy-hcd: remove unsupported isochronous endpoints
UPSTREAM: usb: raw-gadget: fix null-ptr-deref when reenabling endpoints
UPSTREAM: usb: raw-gadget: documentation updates
UPSTREAM: usb: raw-gadget: support stalling/halting/wedging endpoints
UPSTREAM: usb: raw-gadget: fix gadget endpoint selection
UPSTREAM: usb: raw-gadget: improve uapi headers comments
UPSTREAM: usb: raw-gadget: fix return value of ep read ioctls
UPSTREAM: usb: raw-gadget: fix raw_event_queue_fetch locking
UPSTREAM: usb: raw-gadget: Fix copy_to/from_user() checks
f2fs: fix wrong discard space
f2fs: compress: don't compress any datas after cp stop
f2fs: remove unneeded return value of __insert_discard_tree()
f2fs: fix wrong value of tracepoint parameter
f2fs: protect new segment allocation in expand_inode_data
f2fs: code cleanup by removing ifdef macro surrounding
writeback: Avoid skipping inode writeback
ANDROID: net: bpf: permit redirect from ingress L3 to egress L2 devices at near max mtu
Revert "ANDROID: Incremental fs: Avoid continually recalculating hashes"
Linux 4.14.182
iio: adc: stm32-adc: fix device used to request dma
iio: adc: stm32-adc: Use dma_request_chan() instead dma_request_slave_channel()
x86/unwind/orc: Fix unwind_get_return_address_ptr() for inactive tasks
rxrpc: Fix a memory leak in rxkad_verify_response()
rapidio: fix an error in get_user_pages_fast() error handling
mei: release me_cl object reference
iio: dac: vf610: Fix an error handling path in 'vf610_dac_probe()'
iio: sca3000: Remove an erroneous 'get_device()'
staging: greybus: Fix uninitialized scalar variable
staging: iio: ad2s1210: Fix SPI reading
Revert "gfs2: Don't demote a glock until its revokes are written"
cxgb4/cxgb4vf: Fix mac_hlist initialization and free
cxgb4: free mac_hlist properly
media: fdp1: Fix R-Car M3-N naming in debug message
libnvdimm/btt: Fix LBA masking during 'free list' population
libnvdimm/btt: Remove unnecessary code in btt_freelist_init
ubsan: build ubsan.c more conservatively
x86/uaccess, ubsan: Fix UBSAN vs. SMAP
powerpc/64s: Disable STRICT_KERNEL_RWX
powerpc: Remove STRICT_KERNEL_RWX incompatibility with RELOCATABLE
powerpc: restore alphabetic order in Kconfig
dmaengine: tegra210-adma: Fix an error handling path in 'tegra_adma_probe()'
apparmor: Fix aa_label refcnt leak in policy_update
ALSA: pcm: fix incorrect hw_base increase
ALSA: iec1712: Initialize STDSP24 properly when using the model=staudio option
l2tp: initialise PPP sessions before registering them
l2tp: protect sock pointer of struct pppol2tp_session with RCU
l2tp: initialise l2tp_eth sessions before registering them
l2tp: don't register sessions in l2tp_session_create()
arm64: fix the flush_icache_range arguments in machine_kexec
padata: purge get_cpu and reorder_via_wq from padata_do_serial
padata: initialize pd->cpu with effective cpumask
padata: Replace delayed timer with immediate workqueue in padata_reorder
padata: set cpu_index of unused CPUs to -1
ARM: futex: Address build warning
platform/x86: asus-nb-wmi: Do not load on Asus T100TA and T200TA
USB: core: Fix misleading driver bug report
ceph: fix double unlock in handle_cap_export()
gtp: set NLM_F_MULTI flag in gtp_genl_dump_pdp()
x86/apic: Move TSC deadline timer debug printk
scsi: ibmvscsi: Fix WARN_ON during event pool release
component: Silence bind error on -EPROBE_DEFER
vhost/vsock: fix packet delivery order to monitoring devices
configfs: fix config_item refcnt leak in configfs_rmdir()
scsi: qla2xxx: Fix hang when issuing nvme disconnect-all in NPIV
HID: multitouch: add eGalaxTouch P80H84 support
gcc-common.h: Update for GCC 10
ubi: Fix seq_file usage in detailed_erase_block_info debugfs file
i2c: mux: demux-pinctrl: Fix an error handling path in 'i2c_demux_pinctrl_probe()'
iommu/amd: Fix over-read of ACPI UID from IVRS table
fix multiplication overflow in copy_fdtable()
ima: Fix return value of ima_write_policy()
evm: Check also if *tfm is an error pointer in init_desc()
ima: Set file->f_mode instead of file->f_flags in ima_calc_file_hash()
padata: ensure padata_do_serial() runs on the correct CPU
padata: ensure the reorder timer callback runs on the correct CPU
i2c: dev: Fix the race between the release of i2c_dev and cdev
watchdog: Fix the race between the release of watchdog_core_data and cdev
ext4: add cond_resched() to ext4_protect_reserved_inode
ANDROID: scsi: ufs: Handle clocks when lrbp fails
ANDROID: fscrypt: handle direct I/O with IV_INO_LBLK_32
BACKPORT: FROMLIST: fscrypt: add support for IV_INO_LBLK_32 policies
f2fs: avoid inifinite loop to wait for flushing node pages at cp_error
ANDROID: namespace'ify tcp_default_init_rwnd implementation
Linux 4.14.181
Makefile: disallow data races on gcc-10 as well
KVM: x86: Fix off-by-one error in kvm_vcpu_ioctl_x86_setup_mce
ARM: dts: r8a7740: Add missing extal2 to CPG node
ARM: dts: r8a73a4: Add missing CMT1 interrupts
arm64: dts: rockchip: Rename dwc3 device nodes on rk3399 to make dtc happy
arm64: dts: rockchip: Replace RK805 PMIC node name with "pmic" on rk3328 boards
Revert "ALSA: hda/realtek: Fix pop noise on ALC225"
usb: gadget: legacy: fix error return code in cdc_bind()
usb: gadget: legacy: fix error return code in gncm_bind()
usb: gadget: audio: Fix a missing error return value in audio_bind()
usb: gadget: net2272: Fix a memory leak in an error handling path in 'net2272_plat_probe()'
clk: rockchip: fix incorrect configuration of rk3228 aclk_gpu* clocks
exec: Move would_dump into flush_old_exec
x86/unwind/orc: Fix error handling in __unwind_start()
usb: xhci: Fix NULL pointer dereference when enqueuing trbs from urb sg list
USB: gadget: fix illegal array access in binding with UDC
usb: host: xhci-plat: keep runtime active when removing host
usb: core: hub: limit HUB_QUIRK_DISABLE_AUTOSUSPEND to USB5534B
ALSA: usb-audio: Add control message quirk delay for Kingston HyperX headset
x86: Fix early boot crash on gcc-10, third try
ARM: dts: imx27-phytec-phycard-s-rdk: Fix the I2C1 pinctrl entries
ARM: dts: dra7: Fix bus_dma_limit for PCIe
ALSA: rawmidi: Fix racy buffer resize under concurrent accesses
ALSA: rawmidi: Initialize allocated buffers
ALSA: hda/realtek - Limit int mic boost for Thinkpad T530
net: tcp: fix rx timestamp behavior for tcp_recvmsg
netprio_cgroup: Fix unlimited memory leak of v2 cgroups
net: ipv4: really enforce backoff for redirects
net: dsa: loop: Add module soft dependency
hinic: fix a bug of ndo_stop
Revert "ipv6: add mtu lock check in __ip6_rt_update_pmtu"
net: phy: fix aneg restart in phy_ethtool_set_eee
netlabel: cope with NULL catmap
net: fix a potential recursive NETDEV_FEAT_CHANGE
net: phy: micrel: Use strlcpy() for ethtool::get_strings
x86/asm: Add instruction suffixes to bitops
gcc-10: avoid shadowing standard library 'free()' in crypto
gcc-10: disable 'restrict' warning for now
gcc-10: disable 'stringop-overflow' warning for now
gcc-10: disable 'array-bounds' warning for now
gcc-10: disable 'zero-length-bounds' warning for now
Stop the ad-hoc games with -Wno-maybe-initialized
kbuild: compute false-positive -Wmaybe-uninitialized cases in Kconfig
gcc-10 warnings: fix low-hanging fruit
pnp: Use list_for_each_entry() instead of open coding
hwmon: (da9052) Synchronize access with mfd
IB/mlx4: Test return value of calls to ib_get_cached_pkey
netfilter: conntrack: avoid gcc-10 zero-length-bounds warning
i40iw: Fix error handling in i40iw_manage_arp_cache()
pinctrl: cherryview: Add missing spinlock usage in chv_gpio_irq_handler
pinctrl: baytrail: Enable pin configuration setting for GPIO chip
ipmi: Fix NULL pointer dereference in ssif_probe
x86/entry/64: Fix unwind hints in register clearing code
ALSA: hda/realtek - Fix S3 pop noise on Dell Wyse
ipc/util.c: sysvipc_find_ipc() incorrectly updates position index
drm/qxl: lost qxl_bo_kunmap_atomic_page in qxl_image_init_helper()
ALSA: hda/hdmi: fix race in monitor detection during probe
cpufreq: intel_pstate: Only mention the BIOS disabling turbo mode once
dmaengine: mmp_tdma: Reset channel error on release
dmaengine: pch_dma.c: Avoid data race between probe and irq handler
scsi: sg: add sg_remove_request in sg_write
virtio-blk: handle block_device_operations callbacks after hot unplug
drop_monitor: work around gcc-10 stringop-overflow warning
net: moxa: Fix a potential double 'free_irq()'
net/sonic: Fix a resource leak in an error handling path in 'jazz_sonic_probe()'
shmem: fix possible deadlocks on shmlock_user_lock
net: stmmac: Use mutex instead of spinlock
f2fs: fix to avoid memory leakage in f2fs_listxattr
f2fs: fix to avoid accessing xattr across the boundary
f2fs: sanity check of xattr entry size
f2fs: introduce read_xattr_block
f2fs: introduce read_inline_xattr
blktrace: fix dereference after null check
blktrace: Protect q->blk_trace with RCU
blktrace: fix trace mutex deadlock
blktrace: fix unlocked access to init/start-stop/teardown
net: ipv6_stub: use ip6_dst_lookup_flow instead of ip6_dst_lookup
net: ipv6: add net argument to ip6_dst_lookup_flow
scripts/decodecode: fix trapping instruction formatting
objtool: Fix stack offset tracking for indirect CFAs
netfilter: nat: never update the UDP checksum when it's 0
x86/unwind/orc: Fix error path for bad ORC entry type
x86/unwind/orc: Prevent unwinding before ORC initialization
x86/unwind/orc: Don't skip the first frame for inactive tasks
x86/entry/64: Fix unwind hints in rewind_stack_do_exit()
x86/entry/64: Fix unwind hints in kernel exit path
batman-adv: Fix refcnt leak in batadv_v_ogm_process
batman-adv: Fix refcnt leak in batadv_store_throughput_override
batman-adv: Fix refcnt leak in batadv_show_throughput_override
batman-adv: fix batadv_nc_random_weight_tq
coredump: fix crash when umh is disabled
mm/page_alloc: fix watchdog soft lockups during set_zone_contiguous()
KVM: arm: vgic: Fix limit condition when writing to GICD_I[CS]ACTIVER
tracing: Add a vmalloc_sync_mappings() for safe measure
USB: serial: garmin_gps: add sanity checking for data length
USB: uas: add quirk for LaCie 2Big Quadra
HID: usbhid: Fix race between usbhid_close() and usbhid_stop()
geneve: only configure or fill UDP_ZERO_CSUM6_RX/TX info when CONFIG_IPV6
HID: wacom: Read HID_DG_CONTACTMAX directly for non-generic devices
ipv6: fix cleanup ordering for ip6_mr failure
net: stricter validation of untrusted gso packets
bnxt_en: Fix VF anti-spoof filter setup.
bnxt_en: Improve AER slot reset.
net/mlx5: Fix command entry leak in Internal Error State
net/mlx5: Fix forced completion access non initialized command entry
bnxt_en: Fix VLAN acceleration handling in bnxt_fix_features().
sch_sfq: validate silly quantum values
sch_choke: avoid potential panic in choke_reset()
net: usb: qmi_wwan: add support for DW5816e
net/mlx4_core: Fix use of ENOSPC around mlx4_counter_alloc()
net: macsec: preserve ingress frame ordering
fq_codel: fix TCA_FQ_CODEL_DROP_BATCH_SIZE sanity checks
dp83640: reverse arguments to list_add_tail
USB: serial: qcserial: Add DW5816e support
f2fs: compress: fix zstd data corruption
f2fs: add compressed/gc data read IO stat
f2fs: fix potential use-after-free issue
f2fs: compress: don't handle non-compressed data in workqueue
f2fs: remove redundant assignment to variable err
f2fs: refactor resize_fs to avoid meta updates in progress
f2fs: use round_up to enhance calculation
f2fs: introduce F2FS_IOC_RESERVE_COMPRESS_BLOCKS
f2fs: Avoid double lock for cp_rwsem during checkpoint
f2fs: report delalloc reserve as non-free in statfs for project quota
f2fs: Fix wrong stub helper update_sit_info
f2fs: compress: let lz4 compressor handle output buffer budget properly
f2fs: remove blk_plugging in block_operations
f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS
f2fs: shrink spinlock coverage
f2fs: correctly fix the parent inode number during fsync()
f2fs: introduce mempool for {,de}compress intermediate page allocation
f2fs: introduce f2fs_bmap_compress()
f2fs: support fiemap on compressed inode
f2fs: support partial truncation on compressed inode
f2fs: remove redundant compress inode check
f2fs: flush dirty meta pages when flushing them
f2fs: use strcmp() in parse_options()
f2fs: fix checkpoint=disable:%u%%
f2fs: Use the correct style for SPDX License Identifier
f2fs: rework filename handling
f2fs: split f2fs_d_compare() from f2fs_match_name()
f2fs: don't leak filename in f2fs_try_convert_inline_dir()
ANDROID: clang: update to 11.0.1
FROMLIST: x86_64: fix jiffies ODR violation
ANDROID: cuttlefish_defconfig: Enable net testing options
ANDROID: Incremental fs: wake up log pollers less often
ANDROID: Incremental fs: Fix scheduling while atomic error
ANDROID: Incremental fs: Avoid continually recalculating hashes
Revert "f2fs: refactor resize_fs to avoid meta updates in progress"
UPSTREAM: HID: steam: Fix input device disappearing
ANDROID: fscrypt: set dun_bytes more precisely
ANDROID: dm-default-key: set dun_bytes more precisely
ANDROID: block: backport the ability to specify max_dun_bytes
ANDROID: hid: steam: remove BT controller matching
ANDROID: dm-default-key: Update key size for wrapped keys
ANDROID: cuttlefish_defconfig: Enable CONFIG_STATIC_USERMODEHELPER
ANDROID: cuttlefish_defconfig: enable CONFIG_MMC_CRYPTO
ANDROID: Add padding for crypto related structs in UFS and MMC
ANDROID: mmc: MMC crypto API
f2fs: fix missing check for f2fs_unlock_op
f2fs: refactor resize_fs to avoid meta updates in progress
Conflicts:
Documentation/devicetree/bindings/usb/dwc3.txt
drivers/block/virtio_blk.c
drivers/mmc/core/Kconfig
drivers/mmc/core/block.c
drivers/mmc/host/sdhci-msm.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/scsi/ufs/ufs-qcom.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_uac1_legacy.c
fs/crypto/crypto.c
fs/crypto/inline_crypt.c
fs/crypto/keyring.c
fs/f2fs/checkpoint.c
include/linux/fs.h
include/linux/mmc/host.h
include/linux/mod_devicetable.h
include/uapi/linux/input-event-codes.h
net/qrtr/qrtr.c
sound/core/compress_offload.c
sound/core/rawmidi.c
Fixed build errors:
drivers/scsi/ufs/ufshcd.c
Change-Id: I2add911b58d3c87b666ffa0fe46cbceb6cc56430
Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
4427 lines
112 KiB
C
4427 lines
112 KiB
C
/*
|
|
Copyright (C) 2002 Richard Henderson
|
|
Copyright (C) 2001 Rusty Russell, 2002, 2010 Rusty Russell IBM.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
#include <linux/export.h>
|
|
#include <linux/extable.h>
|
|
#include <linux/moduleloader.h>
|
|
#include <linux/trace_events.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kallsyms.h>
|
|
#include <linux/file.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/sysfs.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/elf.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/security.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/syscalls.h>
|
|
#include <linux/fcntl.h>
|
|
#include <linux/rcupdate.h>
|
|
#include <linux/capability.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/err.h>
|
|
#include <linux/vermagic.h>
|
|
#include <linux/notifier.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/device.h>
|
|
#include <linux/string.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/rculist.h>
|
|
#include <linux/uaccess.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <linux/set_memory.h>
|
|
#include <asm/mmu_context.h>
|
|
#include <linux/license.h>
|
|
#include <asm/sections.h>
|
|
#include <linux/tracepoint.h>
|
|
#include <linux/ftrace.h>
|
|
#include <linux/livepatch.h>
|
|
#include <linux/async.h>
|
|
#include <linux/percpu.h>
|
|
#include <linux/kmemleak.h>
|
|
#include <linux/jump_label.h>
|
|
#include <linux/pfn.h>
|
|
#include <linux/bsearch.h>
|
|
#include <linux/dynamic_debug.h>
|
|
#include <linux/audit.h>
|
|
#include <uapi/linux/module.h>
|
|
#include "module-internal.h"
|
|
|
|
#define CREATE_TRACE_POINTS
|
|
#include <trace/events/module.h>
|
|
|
|
#ifndef ARCH_SHF_SMALL
|
|
#define ARCH_SHF_SMALL 0
|
|
#endif
|
|
|
|
/*
|
|
* Modules' sections will be aligned on page boundaries
|
|
* to ensure complete separation of code and data, but
|
|
* only when CONFIG_STRICT_MODULE_RWX=y
|
|
*/
|
|
#ifdef CONFIG_STRICT_MODULE_RWX
|
|
# define debug_align(X) ALIGN(X, PAGE_SIZE)
|
|
#else
|
|
# define debug_align(X) (X)
|
|
#endif
|
|
|
|
/* If this is set, the section belongs in the init part of the module */
|
|
#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
|
|
|
|
/*
|
|
* Mutex protects:
|
|
* 1) List of modules (also safely readable with preempt_disable),
|
|
* 2) module_use links,
|
|
* 3) module_addr_min/module_addr_max.
|
|
* (delete and add uses RCU list operations). */
|
|
DEFINE_MUTEX(module_mutex);
|
|
EXPORT_SYMBOL_GPL(module_mutex);
|
|
static LIST_HEAD(modules);
|
|
|
|
#ifdef CONFIG_MODULES_TREE_LOOKUP
|
|
|
|
/*
|
|
* Use a latched RB-tree for __module_address(); this allows us to use
|
|
* RCU-sched lookups of the address from any context.
|
|
*
|
|
* This is conditional on PERF_EVENTS || TRACING because those can really hit
|
|
* __module_address() hard by doing a lot of stack unwinding; potentially from
|
|
* NMI context.
|
|
*/
|
|
|
|
static __always_inline unsigned long __mod_tree_val(struct latch_tree_node *n)
|
|
{
|
|
struct module_layout *layout = container_of(n, struct module_layout, mtn.node);
|
|
|
|
return (unsigned long)layout->base;
|
|
}
|
|
|
|
static __always_inline unsigned long __mod_tree_size(struct latch_tree_node *n)
|
|
{
|
|
struct module_layout *layout = container_of(n, struct module_layout, mtn.node);
|
|
|
|
return (unsigned long)layout->size;
|
|
}
|
|
|
|
static __always_inline bool
|
|
mod_tree_less(struct latch_tree_node *a, struct latch_tree_node *b)
|
|
{
|
|
return __mod_tree_val(a) < __mod_tree_val(b);
|
|
}
|
|
|
|
static __always_inline int
|
|
mod_tree_comp(void *key, struct latch_tree_node *n)
|
|
{
|
|
unsigned long val = (unsigned long)key;
|
|
unsigned long start, end;
|
|
|
|
start = __mod_tree_val(n);
|
|
if (val < start)
|
|
return -1;
|
|
|
|
end = start + __mod_tree_size(n);
|
|
if (val >= end)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct latch_tree_ops mod_tree_ops = {
|
|
.less = mod_tree_less,
|
|
.comp = mod_tree_comp,
|
|
};
|
|
|
|
static struct mod_tree_root {
|
|
struct latch_tree_root root;
|
|
unsigned long addr_min;
|
|
unsigned long addr_max;
|
|
} mod_tree __cacheline_aligned = {
|
|
.addr_min = -1UL,
|
|
};
|
|
|
|
#define module_addr_min mod_tree.addr_min
|
|
#define module_addr_max mod_tree.addr_max
|
|
|
|
static noinline void __mod_tree_insert(struct mod_tree_node *node)
|
|
{
|
|
latch_tree_insert(&node->node, &mod_tree.root, &mod_tree_ops);
|
|
}
|
|
|
|
static void __mod_tree_remove(struct mod_tree_node *node)
|
|
{
|
|
latch_tree_erase(&node->node, &mod_tree.root, &mod_tree_ops);
|
|
}
|
|
|
|
/*
|
|
* These modifications: insert, remove_init and remove; are serialized by the
|
|
* module_mutex.
|
|
*/
|
|
static void mod_tree_insert(struct module *mod)
|
|
{
|
|
mod->core_layout.mtn.mod = mod;
|
|
mod->init_layout.mtn.mod = mod;
|
|
|
|
__mod_tree_insert(&mod->core_layout.mtn);
|
|
if (mod->init_layout.size)
|
|
__mod_tree_insert(&mod->init_layout.mtn);
|
|
}
|
|
|
|
static void mod_tree_remove_init(struct module *mod)
|
|
{
|
|
if (mod->init_layout.size)
|
|
__mod_tree_remove(&mod->init_layout.mtn);
|
|
}
|
|
|
|
static void mod_tree_remove(struct module *mod)
|
|
{
|
|
__mod_tree_remove(&mod->core_layout.mtn);
|
|
mod_tree_remove_init(mod);
|
|
}
|
|
|
|
static struct module *mod_find(unsigned long addr)
|
|
{
|
|
struct latch_tree_node *ltn;
|
|
|
|
ltn = latch_tree_find((void *)addr, &mod_tree.root, &mod_tree_ops);
|
|
if (!ltn)
|
|
return NULL;
|
|
|
|
return container_of(ltn, struct mod_tree_node, node)->mod;
|
|
}
|
|
|
|
#else /* MODULES_TREE_LOOKUP */
|
|
|
|
static unsigned long module_addr_min = -1UL, module_addr_max = 0;
|
|
|
|
static void mod_tree_insert(struct module *mod) { }
|
|
static void mod_tree_remove_init(struct module *mod) { }
|
|
static void mod_tree_remove(struct module *mod) { }
|
|
|
|
static struct module *mod_find(unsigned long addr)
|
|
{
|
|
struct module *mod;
|
|
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (within_module(addr, mod))
|
|
return mod;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* MODULES_TREE_LOOKUP */
|
|
|
|
/*
|
|
* Bounds of module text, for speeding up __module_address.
|
|
* Protected by module_mutex.
|
|
*/
|
|
static void __mod_update_bounds(void *base, unsigned int size)
|
|
{
|
|
unsigned long min = (unsigned long)base;
|
|
unsigned long max = min + size;
|
|
|
|
if (min < module_addr_min)
|
|
module_addr_min = min;
|
|
if (max > module_addr_max)
|
|
module_addr_max = max;
|
|
}
|
|
|
|
static void mod_update_bounds(struct module *mod)
|
|
{
|
|
__mod_update_bounds(mod->core_layout.base, mod->core_layout.size);
|
|
if (mod->init_layout.size)
|
|
__mod_update_bounds(mod->init_layout.base, mod->init_layout.size);
|
|
}
|
|
|
|
#ifdef CONFIG_KGDB_KDB
|
|
struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
|
|
#endif /* CONFIG_KGDB_KDB */
|
|
|
|
static void module_assert_mutex(void)
|
|
{
|
|
lockdep_assert_held(&module_mutex);
|
|
}
|
|
|
|
static void module_assert_mutex_or_preempt(void)
|
|
{
|
|
#ifdef CONFIG_LOCKDEP
|
|
if (unlikely(!debug_locks))
|
|
return;
|
|
|
|
WARN_ON_ONCE(!rcu_read_lock_sched_held() &&
|
|
!lockdep_is_held(&module_mutex));
|
|
#endif
|
|
}
|
|
|
|
static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE);
|
|
#ifndef CONFIG_MODULE_SIG_FORCE
|
|
module_param(sig_enforce, bool_enable_only, 0644);
|
|
#endif /* !CONFIG_MODULE_SIG_FORCE */
|
|
|
|
/* Block module loading/unloading? */
|
|
int modules_disabled = 0;
|
|
core_param(nomodule, modules_disabled, bint, 0);
|
|
|
|
/* Waiting for a module to finish initializing? */
|
|
static DECLARE_WAIT_QUEUE_HEAD(module_wq);
|
|
|
|
static BLOCKING_NOTIFIER_HEAD(module_notify_list);
|
|
|
|
int register_module_notifier(struct notifier_block *nb)
|
|
{
|
|
return blocking_notifier_chain_register(&module_notify_list, nb);
|
|
}
|
|
EXPORT_SYMBOL(register_module_notifier);
|
|
|
|
int unregister_module_notifier(struct notifier_block *nb)
|
|
{
|
|
return blocking_notifier_chain_unregister(&module_notify_list, nb);
|
|
}
|
|
EXPORT_SYMBOL(unregister_module_notifier);
|
|
|
|
struct load_info {
|
|
const char *name;
|
|
Elf_Ehdr *hdr;
|
|
unsigned long len;
|
|
Elf_Shdr *sechdrs;
|
|
char *secstrings, *strtab;
|
|
unsigned long symoffs, stroffs;
|
|
struct _ddebug *debug;
|
|
unsigned int num_debug;
|
|
bool sig_ok;
|
|
#ifdef CONFIG_KALLSYMS
|
|
unsigned long mod_kallsyms_init_off;
|
|
#endif
|
|
struct {
|
|
unsigned int sym, str, mod, vers, info, pcpu;
|
|
} index;
|
|
};
|
|
|
|
/*
|
|
* We require a truly strong try_module_get(): 0 means success.
|
|
* Otherwise an error is returned due to ongoing or failed
|
|
* initialization etc.
|
|
*/
|
|
static inline int strong_try_module_get(struct module *mod)
|
|
{
|
|
BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED);
|
|
if (mod && mod->state == MODULE_STATE_COMING)
|
|
return -EBUSY;
|
|
if (try_module_get(mod))
|
|
return 0;
|
|
else
|
|
return -ENOENT;
|
|
}
|
|
|
|
static inline void add_taint_module(struct module *mod, unsigned flag,
|
|
enum lockdep_ok lockdep_ok)
|
|
{
|
|
add_taint(flag, lockdep_ok);
|
|
set_bit(flag, &mod->taints);
|
|
}
|
|
|
|
/*
|
|
* A thread that wants to hold a reference to a module only while it
|
|
* is running can call this to safely exit. nfsd and lockd use this.
|
|
*/
|
|
void __noreturn __module_put_and_exit(struct module *mod, long code)
|
|
{
|
|
module_put(mod);
|
|
do_exit(code);
|
|
}
|
|
EXPORT_SYMBOL(__module_put_and_exit);
|
|
|
|
/* Find a module section: 0 means not found. */
|
|
static unsigned int find_sec(const struct load_info *info, const char *name)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 1; i < info->hdr->e_shnum; i++) {
|
|
Elf_Shdr *shdr = &info->sechdrs[i];
|
|
/* Alloc bit cleared means "ignore it." */
|
|
if ((shdr->sh_flags & SHF_ALLOC)
|
|
&& strcmp(info->secstrings + shdr->sh_name, name) == 0)
|
|
return i;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Find a module section, or NULL. */
|
|
static void *section_addr(const struct load_info *info, const char *name)
|
|
{
|
|
/* Section 0 has sh_addr 0. */
|
|
return (void *)info->sechdrs[find_sec(info, name)].sh_addr;
|
|
}
|
|
|
|
/* Find a module section, or NULL. Fill in number of "objects" in section. */
|
|
static void *section_objs(const struct load_info *info,
|
|
const char *name,
|
|
size_t object_size,
|
|
unsigned int *num)
|
|
{
|
|
unsigned int sec = find_sec(info, name);
|
|
|
|
/* Section 0 has sh_addr 0 and sh_size 0. */
|
|
*num = info->sechdrs[sec].sh_size / object_size;
|
|
return (void *)info->sechdrs[sec].sh_addr;
|
|
}
|
|
|
|
/* Provided by the linker */
|
|
extern const struct kernel_symbol __start___ksymtab[];
|
|
extern const struct kernel_symbol __stop___ksymtab[];
|
|
extern const struct kernel_symbol __start___ksymtab_gpl[];
|
|
extern const struct kernel_symbol __stop___ksymtab_gpl[];
|
|
extern const struct kernel_symbol __start___ksymtab_gpl_future[];
|
|
extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
|
|
extern const s32 __start___kcrctab[];
|
|
extern const s32 __start___kcrctab_gpl[];
|
|
extern const s32 __start___kcrctab_gpl_future[];
|
|
#ifdef CONFIG_UNUSED_SYMBOLS
|
|
extern const struct kernel_symbol __start___ksymtab_unused[];
|
|
extern const struct kernel_symbol __stop___ksymtab_unused[];
|
|
extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
|
|
extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
|
|
extern const s32 __start___kcrctab_unused[];
|
|
extern const s32 __start___kcrctab_unused_gpl[];
|
|
#endif
|
|
|
|
#ifndef CONFIG_MODVERSIONS
|
|
#define symversion(base, idx) NULL
|
|
#else
|
|
#define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
|
|
#endif
|
|
|
|
static bool each_symbol_in_section(const struct symsearch *arr,
|
|
unsigned int arrsize,
|
|
struct module *owner,
|
|
bool (*fn)(const struct symsearch *syms,
|
|
struct module *owner,
|
|
void *data),
|
|
void *data)
|
|
{
|
|
unsigned int j;
|
|
|
|
for (j = 0; j < arrsize; j++) {
|
|
if (fn(&arr[j], owner, data))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* Returns true as soon as fn returns true, otherwise false. */
|
|
bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
|
|
struct module *owner,
|
|
void *data),
|
|
void *data)
|
|
{
|
|
struct module *mod;
|
|
static const struct symsearch arr[] = {
|
|
{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,
|
|
NOT_GPL_ONLY, false },
|
|
{ __start___ksymtab_gpl, __stop___ksymtab_gpl,
|
|
__start___kcrctab_gpl,
|
|
GPL_ONLY, false },
|
|
{ __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future,
|
|
__start___kcrctab_gpl_future,
|
|
WILL_BE_GPL_ONLY, false },
|
|
#ifdef CONFIG_UNUSED_SYMBOLS
|
|
{ __start___ksymtab_unused, __stop___ksymtab_unused,
|
|
__start___kcrctab_unused,
|
|
NOT_GPL_ONLY, true },
|
|
{ __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl,
|
|
__start___kcrctab_unused_gpl,
|
|
GPL_ONLY, true },
|
|
#endif
|
|
};
|
|
|
|
module_assert_mutex_or_preempt();
|
|
|
|
if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))
|
|
return true;
|
|
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
struct symsearch arr[] = {
|
|
{ mod->syms, mod->syms + mod->num_syms, mod->crcs,
|
|
NOT_GPL_ONLY, false },
|
|
{ mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,
|
|
mod->gpl_crcs,
|
|
GPL_ONLY, false },
|
|
{ mod->gpl_future_syms,
|
|
mod->gpl_future_syms + mod->num_gpl_future_syms,
|
|
mod->gpl_future_crcs,
|
|
WILL_BE_GPL_ONLY, false },
|
|
#ifdef CONFIG_UNUSED_SYMBOLS
|
|
{ mod->unused_syms,
|
|
mod->unused_syms + mod->num_unused_syms,
|
|
mod->unused_crcs,
|
|
NOT_GPL_ONLY, true },
|
|
{ mod->unused_gpl_syms,
|
|
mod->unused_gpl_syms + mod->num_unused_gpl_syms,
|
|
mod->unused_gpl_crcs,
|
|
GPL_ONLY, true },
|
|
#endif
|
|
};
|
|
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
|
|
if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
EXPORT_SYMBOL_GPL(each_symbol_section);
|
|
|
|
struct find_symbol_arg {
|
|
/* Input */
|
|
const char *name;
|
|
bool gplok;
|
|
bool warn;
|
|
|
|
/* Output */
|
|
struct module *owner;
|
|
const s32 *crc;
|
|
const struct kernel_symbol *sym;
|
|
};
|
|
|
|
static bool check_symbol(const struct symsearch *syms,
|
|
struct module *owner,
|
|
unsigned int symnum, void *data)
|
|
{
|
|
struct find_symbol_arg *fsa = data;
|
|
|
|
if (!fsa->gplok) {
|
|
if (syms->licence == GPL_ONLY)
|
|
return false;
|
|
if (syms->licence == WILL_BE_GPL_ONLY && fsa->warn) {
|
|
pr_warn("Symbol %s is being used by a non-GPL module, "
|
|
"which will not be allowed in the future\n",
|
|
fsa->name);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_UNUSED_SYMBOLS
|
|
if (syms->unused && fsa->warn) {
|
|
pr_warn("Symbol %s is marked as UNUSED, however this module is "
|
|
"using it.\n", fsa->name);
|
|
pr_warn("This symbol will go away in the future.\n");
|
|
pr_warn("Please evaluate if this is the right api to use and "
|
|
"if it really is, submit a report to the linux kernel "
|
|
"mailing list together with submitting your code for "
|
|
"inclusion.\n");
|
|
}
|
|
#endif
|
|
|
|
fsa->owner = owner;
|
|
fsa->crc = symversion(syms->crcs, symnum);
|
|
fsa->sym = &syms->start[symnum];
|
|
return true;
|
|
}
|
|
|
|
static int cmp_name(const void *va, const void *vb)
|
|
{
|
|
const char *a;
|
|
const struct kernel_symbol *b;
|
|
a = va; b = vb;
|
|
return strcmp(a, b->name);
|
|
}
|
|
|
|
static bool find_symbol_in_section(const struct symsearch *syms,
|
|
struct module *owner,
|
|
void *data)
|
|
{
|
|
struct find_symbol_arg *fsa = data;
|
|
struct kernel_symbol *sym;
|
|
|
|
sym = bsearch(fsa->name, syms->start, syms->stop - syms->start,
|
|
sizeof(struct kernel_symbol), cmp_name);
|
|
|
|
if (sym != NULL && check_symbol(syms, owner, sym - syms->start, data))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/* Find a symbol and return it, along with, (optional) crc and
|
|
* (optional) module which owns it. Needs preempt disabled or module_mutex. */
|
|
const struct kernel_symbol *find_symbol(const char *name,
|
|
struct module **owner,
|
|
const s32 **crc,
|
|
bool gplok,
|
|
bool warn)
|
|
{
|
|
struct find_symbol_arg fsa;
|
|
|
|
fsa.name = name;
|
|
fsa.gplok = gplok;
|
|
fsa.warn = warn;
|
|
|
|
if (each_symbol_section(find_symbol_in_section, &fsa)) {
|
|
if (owner)
|
|
*owner = fsa.owner;
|
|
if (crc)
|
|
*crc = fsa.crc;
|
|
return fsa.sym;
|
|
}
|
|
|
|
pr_debug("Failed to find symbol %s\n", name);
|
|
return NULL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(find_symbol);
|
|
|
|
/*
|
|
* Search for module by name: must hold module_mutex (or preempt disabled
|
|
* for read-only access).
|
|
*/
|
|
static struct module *find_module_all(const char *name, size_t len,
|
|
bool even_unformed)
|
|
{
|
|
struct module *mod;
|
|
|
|
module_assert_mutex_or_preempt();
|
|
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (strlen(mod->name) == len && !memcmp(mod->name, name, len))
|
|
return mod;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
struct module *find_module(const char *name)
|
|
{
|
|
module_assert_mutex();
|
|
return find_module_all(name, strlen(name), false);
|
|
}
|
|
EXPORT_SYMBOL_GPL(find_module);
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
static inline void __percpu *mod_percpu(struct module *mod)
|
|
{
|
|
return mod->percpu;
|
|
}
|
|
|
|
static int percpu_modalloc(struct module *mod, struct load_info *info)
|
|
{
|
|
Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu];
|
|
unsigned long align = pcpusec->sh_addralign;
|
|
|
|
if (!pcpusec->sh_size)
|
|
return 0;
|
|
|
|
if (align > PAGE_SIZE) {
|
|
pr_warn("%s: per-cpu alignment %li > %li\n",
|
|
mod->name, align, PAGE_SIZE);
|
|
align = PAGE_SIZE;
|
|
}
|
|
|
|
mod->percpu = __alloc_reserved_percpu(pcpusec->sh_size, align);
|
|
if (!mod->percpu) {
|
|
pr_warn("%s: Could not allocate %lu bytes percpu data\n",
|
|
mod->name, (unsigned long)pcpusec->sh_size);
|
|
return -ENOMEM;
|
|
}
|
|
mod->percpu_size = pcpusec->sh_size;
|
|
return 0;
|
|
}
|
|
|
|
static void percpu_modfree(struct module *mod)
|
|
{
|
|
free_percpu(mod->percpu);
|
|
}
|
|
|
|
static unsigned int find_pcpusec(struct load_info *info)
|
|
{
|
|
return find_sec(info, ".data..percpu");
|
|
}
|
|
|
|
static void percpu_modcopy(struct module *mod,
|
|
const void *from, unsigned long size)
|
|
{
|
|
int cpu;
|
|
|
|
for_each_possible_cpu(cpu)
|
|
memcpy(per_cpu_ptr(mod->percpu, cpu), from, size);
|
|
}
|
|
|
|
bool __is_module_percpu_address(unsigned long addr, unsigned long *can_addr)
|
|
{
|
|
struct module *mod;
|
|
unsigned int cpu;
|
|
|
|
preempt_disable();
|
|
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (!mod->percpu_size)
|
|
continue;
|
|
for_each_possible_cpu(cpu) {
|
|
void *start = per_cpu_ptr(mod->percpu, cpu);
|
|
void *va = (void *)addr;
|
|
|
|
if (va >= start && va < start + mod->percpu_size) {
|
|
if (can_addr) {
|
|
*can_addr = (unsigned long) (va - start);
|
|
*can_addr += (unsigned long)
|
|
per_cpu_ptr(mod->percpu,
|
|
get_boot_cpu_id());
|
|
}
|
|
preempt_enable();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
preempt_enable();
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* is_module_percpu_address - test whether address is from module static percpu
|
|
* @addr: address to test
|
|
*
|
|
* Test whether @addr belongs to module static percpu area.
|
|
*
|
|
* RETURNS:
|
|
* %true if @addr is from module static percpu area
|
|
*/
|
|
bool is_module_percpu_address(unsigned long addr)
|
|
{
|
|
return __is_module_percpu_address(addr, NULL);
|
|
}
|
|
|
|
#else /* ... !CONFIG_SMP */
|
|
|
|
static inline void __percpu *mod_percpu(struct module *mod)
|
|
{
|
|
return NULL;
|
|
}
|
|
static int percpu_modalloc(struct module *mod, struct load_info *info)
|
|
{
|
|
/* UP modules shouldn't have this section: ENOMEM isn't quite right */
|
|
if (info->sechdrs[info->index.pcpu].sh_size != 0)
|
|
return -ENOMEM;
|
|
return 0;
|
|
}
|
|
static inline void percpu_modfree(struct module *mod)
|
|
{
|
|
}
|
|
static unsigned int find_pcpusec(struct load_info *info)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline void percpu_modcopy(struct module *mod,
|
|
const void *from, unsigned long size)
|
|
{
|
|
/* pcpusec should be 0, and size of that section should be 0. */
|
|
BUG_ON(size != 0);
|
|
}
|
|
bool is_module_percpu_address(unsigned long addr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool __is_module_percpu_address(unsigned long addr, unsigned long *can_addr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
#define MODINFO_ATTR(field) \
|
|
static void setup_modinfo_##field(struct module *mod, const char *s) \
|
|
{ \
|
|
mod->field = kstrdup(s, GFP_KERNEL); \
|
|
} \
|
|
static ssize_t show_modinfo_##field(struct module_attribute *mattr, \
|
|
struct module_kobject *mk, char *buffer) \
|
|
{ \
|
|
return scnprintf(buffer, PAGE_SIZE, "%s\n", mk->mod->field); \
|
|
} \
|
|
static int modinfo_##field##_exists(struct module *mod) \
|
|
{ \
|
|
return mod->field != NULL; \
|
|
} \
|
|
static void free_modinfo_##field(struct module *mod) \
|
|
{ \
|
|
kfree(mod->field); \
|
|
mod->field = NULL; \
|
|
} \
|
|
static struct module_attribute modinfo_##field = { \
|
|
.attr = { .name = __stringify(field), .mode = 0444 }, \
|
|
.show = show_modinfo_##field, \
|
|
.setup = setup_modinfo_##field, \
|
|
.test = modinfo_##field##_exists, \
|
|
.free = free_modinfo_##field, \
|
|
};
|
|
|
|
MODINFO_ATTR(version);
|
|
MODINFO_ATTR(srcversion);
|
|
|
|
static char last_unloaded_module[MODULE_NAME_LEN+1];
|
|
|
|
#ifdef CONFIG_MODULE_UNLOAD
|
|
|
|
EXPORT_TRACEPOINT_SYMBOL(module_get);
|
|
|
|
/* MODULE_REF_BASE is the base reference count by kmodule loader. */
|
|
#define MODULE_REF_BASE 1
|
|
|
|
/* Init the unload section of the module. */
|
|
static int module_unload_init(struct module *mod)
|
|
{
|
|
/*
|
|
* Initialize reference counter to MODULE_REF_BASE.
|
|
* refcnt == 0 means module is going.
|
|
*/
|
|
atomic_set(&mod->refcnt, MODULE_REF_BASE);
|
|
|
|
INIT_LIST_HEAD(&mod->source_list);
|
|
INIT_LIST_HEAD(&mod->target_list);
|
|
|
|
/* Hold reference count during initialization. */
|
|
atomic_inc(&mod->refcnt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Does a already use b? */
|
|
static int already_uses(struct module *a, struct module *b)
|
|
{
|
|
struct module_use *use;
|
|
|
|
list_for_each_entry(use, &b->source_list, source_list) {
|
|
if (use->source == a) {
|
|
pr_debug("%s uses %s!\n", a->name, b->name);
|
|
return 1;
|
|
}
|
|
}
|
|
pr_debug("%s does not use %s!\n", a->name, b->name);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Module a uses b
|
|
* - we add 'a' as a "source", 'b' as a "target" of module use
|
|
* - the module_use is added to the list of 'b' sources (so
|
|
* 'b' can walk the list to see who sourced them), and of 'a'
|
|
* targets (so 'a' can see what modules it targets).
|
|
*/
|
|
static int add_module_usage(struct module *a, struct module *b)
|
|
{
|
|
struct module_use *use;
|
|
|
|
pr_debug("Allocating new usage for %s.\n", a->name);
|
|
use = kmalloc(sizeof(*use), GFP_ATOMIC);
|
|
if (!use) {
|
|
pr_warn("%s: out of memory loading\n", a->name);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
use->source = a;
|
|
use->target = b;
|
|
list_add(&use->source_list, &b->source_list);
|
|
list_add(&use->target_list, &a->target_list);
|
|
return 0;
|
|
}
|
|
|
|
/* Module a uses b: caller needs module_mutex() */
|
|
int ref_module(struct module *a, struct module *b)
|
|
{
|
|
int err;
|
|
|
|
if (b == NULL || already_uses(a, b))
|
|
return 0;
|
|
|
|
/* If module isn't available, we fail. */
|
|
err = strong_try_module_get(b);
|
|
if (err)
|
|
return err;
|
|
|
|
err = add_module_usage(a, b);
|
|
if (err) {
|
|
module_put(b);
|
|
return err;
|
|
}
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(ref_module);
|
|
|
|
/* Clear the unload stuff of the module. */
|
|
static void module_unload_free(struct module *mod)
|
|
{
|
|
struct module_use *use, *tmp;
|
|
|
|
mutex_lock(&module_mutex);
|
|
list_for_each_entry_safe(use, tmp, &mod->target_list, target_list) {
|
|
struct module *i = use->target;
|
|
pr_debug("%s unusing %s\n", mod->name, i->name);
|
|
module_put(i);
|
|
list_del(&use->source_list);
|
|
list_del(&use->target_list);
|
|
kfree(use);
|
|
}
|
|
mutex_unlock(&module_mutex);
|
|
}
|
|
|
|
#ifdef CONFIG_MODULE_FORCE_UNLOAD
|
|
static inline int try_force_unload(unsigned int flags)
|
|
{
|
|
int ret = (flags & O_TRUNC);
|
|
if (ret)
|
|
add_taint(TAINT_FORCED_RMMOD, LOCKDEP_NOW_UNRELIABLE);
|
|
return ret;
|
|
}
|
|
#else
|
|
static inline int try_force_unload(unsigned int flags)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_MODULE_FORCE_UNLOAD */
|
|
|
|
/* Try to release refcount of module, 0 means success. */
|
|
static int try_release_module_ref(struct module *mod)
|
|
{
|
|
int ret;
|
|
|
|
/* Try to decrement refcnt which we set at loading */
|
|
ret = atomic_sub_return(MODULE_REF_BASE, &mod->refcnt);
|
|
BUG_ON(ret < 0);
|
|
if (ret)
|
|
/* Someone can put this right now, recover with checking */
|
|
ret = atomic_add_unless(&mod->refcnt, MODULE_REF_BASE, 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int try_stop_module(struct module *mod, int flags, int *forced)
|
|
{
|
|
/* If it's not unused, quit unless we're forcing. */
|
|
if (try_release_module_ref(mod) != 0) {
|
|
*forced = try_force_unload(flags);
|
|
if (!(*forced))
|
|
return -EWOULDBLOCK;
|
|
}
|
|
|
|
/* Mark it as dying. */
|
|
mod->state = MODULE_STATE_GOING;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* module_refcount - return the refcount or -1 if unloading
|
|
*
|
|
* @mod: the module we're checking
|
|
*
|
|
* Returns:
|
|
* -1 if the module is in the process of unloading
|
|
* otherwise the number of references in the kernel to the module
|
|
*/
|
|
int module_refcount(struct module *mod)
|
|
{
|
|
return atomic_read(&mod->refcnt) - MODULE_REF_BASE;
|
|
}
|
|
EXPORT_SYMBOL(module_refcount);
|
|
|
|
/* This exists whether we can unload or not */
|
|
static void free_module(struct module *mod);
|
|
|
|
SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
|
|
unsigned int, flags)
|
|
{
|
|
struct module *mod;
|
|
char name[MODULE_NAME_LEN];
|
|
int ret, forced = 0;
|
|
|
|
if (!capable(CAP_SYS_MODULE) || modules_disabled)
|
|
return -EPERM;
|
|
|
|
if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
|
|
return -EFAULT;
|
|
name[MODULE_NAME_LEN-1] = '\0';
|
|
|
|
audit_log_kern_module(name);
|
|
|
|
if (mutex_lock_interruptible(&module_mutex) != 0)
|
|
return -EINTR;
|
|
|
|
mod = find_module(name);
|
|
if (!mod) {
|
|
ret = -ENOENT;
|
|
goto out;
|
|
}
|
|
|
|
if (!list_empty(&mod->source_list)) {
|
|
/* Other modules depend on us: get rid of them first. */
|
|
ret = -EWOULDBLOCK;
|
|
goto out;
|
|
}
|
|
|
|
/* Doing init or already dying? */
|
|
if (mod->state != MODULE_STATE_LIVE) {
|
|
/* FIXME: if (force), slam module count damn the torpedoes */
|
|
pr_debug("%s already dying\n", mod->name);
|
|
ret = -EBUSY;
|
|
goto out;
|
|
}
|
|
|
|
/* If it has an init func, it must have an exit func to unload */
|
|
if (mod->init && !mod->exit) {
|
|
forced = try_force_unload(flags);
|
|
if (!forced) {
|
|
/* This module can't be removed */
|
|
ret = -EBUSY;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
/* Stop the machine so refcounts can't move and disable module. */
|
|
ret = try_stop_module(mod, flags, &forced);
|
|
if (ret != 0)
|
|
goto out;
|
|
|
|
mutex_unlock(&module_mutex);
|
|
/* Final destruction now no one is using it. */
|
|
if (mod->exit != NULL)
|
|
mod->exit();
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
MODULE_STATE_GOING, mod);
|
|
klp_module_going(mod);
|
|
ftrace_release_mod(mod);
|
|
|
|
async_synchronize_full();
|
|
|
|
/* Store the name of the last unloaded module for diagnostic purposes */
|
|
strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
|
|
|
|
free_module(mod);
|
|
/* someone could wait for the module in add_unformed_module() */
|
|
wake_up_all(&module_wq);
|
|
return 0;
|
|
out:
|
|
mutex_unlock(&module_mutex);
|
|
return ret;
|
|
}
|
|
|
|
static inline void print_unload_info(struct seq_file *m, struct module *mod)
|
|
{
|
|
struct module_use *use;
|
|
int printed_something = 0;
|
|
|
|
seq_printf(m, " %i ", module_refcount(mod));
|
|
|
|
/*
|
|
* Always include a trailing , so userspace can differentiate
|
|
* between this and the old multi-field proc format.
|
|
*/
|
|
list_for_each_entry(use, &mod->source_list, source_list) {
|
|
printed_something = 1;
|
|
seq_printf(m, "%s,", use->source->name);
|
|
}
|
|
|
|
if (mod->init != NULL && mod->exit == NULL) {
|
|
printed_something = 1;
|
|
seq_puts(m, "[permanent],");
|
|
}
|
|
|
|
if (!printed_something)
|
|
seq_puts(m, "-");
|
|
}
|
|
|
|
void __symbol_put(const char *symbol)
|
|
{
|
|
struct module *owner;
|
|
|
|
preempt_disable();
|
|
if (!find_symbol(symbol, &owner, NULL, true, false))
|
|
BUG();
|
|
module_put(owner);
|
|
preempt_enable();
|
|
}
|
|
EXPORT_SYMBOL(__symbol_put);
|
|
|
|
/* Note this assumes addr is a function, which it currently always is. */
|
|
void symbol_put_addr(void *addr)
|
|
{
|
|
struct module *modaddr;
|
|
unsigned long a = (unsigned long)dereference_function_descriptor(addr);
|
|
|
|
if (core_kernel_text(a))
|
|
return;
|
|
|
|
/*
|
|
* Even though we hold a reference on the module; we still need to
|
|
* disable preemption in order to safely traverse the data structure.
|
|
*/
|
|
preempt_disable();
|
|
modaddr = __module_text_address(a);
|
|
BUG_ON(!modaddr);
|
|
module_put(modaddr);
|
|
preempt_enable();
|
|
}
|
|
EXPORT_SYMBOL_GPL(symbol_put_addr);
|
|
|
|
static ssize_t show_refcnt(struct module_attribute *mattr,
|
|
struct module_kobject *mk, char *buffer)
|
|
{
|
|
return sprintf(buffer, "%i\n", module_refcount(mk->mod));
|
|
}
|
|
|
|
static struct module_attribute modinfo_refcnt =
|
|
__ATTR(refcnt, 0444, show_refcnt, NULL);
|
|
|
|
void __module_get(struct module *module)
|
|
{
|
|
if (module) {
|
|
preempt_disable();
|
|
atomic_inc(&module->refcnt);
|
|
trace_module_get(module, _RET_IP_);
|
|
preempt_enable();
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(__module_get);
|
|
|
|
bool try_module_get(struct module *module)
|
|
{
|
|
bool ret = true;
|
|
|
|
if (module) {
|
|
preempt_disable();
|
|
/* Note: here, we can fail to get a reference */
|
|
if (likely(module_is_live(module) &&
|
|
atomic_inc_not_zero(&module->refcnt) != 0))
|
|
trace_module_get(module, _RET_IP_);
|
|
else
|
|
ret = false;
|
|
|
|
preempt_enable();
|
|
}
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(try_module_get);
|
|
|
|
void module_put(struct module *module)
|
|
{
|
|
int ret;
|
|
|
|
if (module) {
|
|
preempt_disable();
|
|
ret = atomic_dec_if_positive(&module->refcnt);
|
|
WARN_ON(ret < 0); /* Failed to put refcount */
|
|
trace_module_put(module, _RET_IP_);
|
|
preempt_enable();
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(module_put);
|
|
|
|
#else /* !CONFIG_MODULE_UNLOAD */
|
|
static inline void print_unload_info(struct seq_file *m, struct module *mod)
|
|
{
|
|
/* We don't know the usage count, or what modules are using. */
|
|
seq_puts(m, " - -");
|
|
}
|
|
|
|
static inline void module_unload_free(struct module *mod)
|
|
{
|
|
}
|
|
|
|
int ref_module(struct module *a, struct module *b)
|
|
{
|
|
return strong_try_module_get(b);
|
|
}
|
|
EXPORT_SYMBOL_GPL(ref_module);
|
|
|
|
static inline int module_unload_init(struct module *mod)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_MODULE_UNLOAD */
|
|
|
|
static size_t module_flags_taint(struct module *mod, char *buf)
|
|
{
|
|
size_t l = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
|
|
if (taint_flags[i].module && test_bit(i, &mod->taints))
|
|
buf[l++] = taint_flags[i].c_true;
|
|
}
|
|
|
|
return l;
|
|
}
|
|
|
|
static ssize_t show_initstate(struct module_attribute *mattr,
|
|
struct module_kobject *mk, char *buffer)
|
|
{
|
|
const char *state = "unknown";
|
|
|
|
switch (mk->mod->state) {
|
|
case MODULE_STATE_LIVE:
|
|
state = "live";
|
|
break;
|
|
case MODULE_STATE_COMING:
|
|
state = "coming";
|
|
break;
|
|
case MODULE_STATE_GOING:
|
|
state = "going";
|
|
break;
|
|
default:
|
|
BUG();
|
|
}
|
|
return sprintf(buffer, "%s\n", state);
|
|
}
|
|
|
|
static struct module_attribute modinfo_initstate =
|
|
__ATTR(initstate, 0444, show_initstate, NULL);
|
|
|
|
static ssize_t store_uevent(struct module_attribute *mattr,
|
|
struct module_kobject *mk,
|
|
const char *buffer, size_t count)
|
|
{
|
|
int rc;
|
|
|
|
rc = kobject_synth_uevent(&mk->kobj, buffer, count);
|
|
return rc ? rc : count;
|
|
}
|
|
|
|
struct module_attribute module_uevent =
|
|
__ATTR(uevent, 0200, NULL, store_uevent);
|
|
|
|
static ssize_t show_coresize(struct module_attribute *mattr,
|
|
struct module_kobject *mk, char *buffer)
|
|
{
|
|
return sprintf(buffer, "%u\n", mk->mod->core_layout.size);
|
|
}
|
|
|
|
static struct module_attribute modinfo_coresize =
|
|
__ATTR(coresize, 0444, show_coresize, NULL);
|
|
|
|
static ssize_t show_initsize(struct module_attribute *mattr,
|
|
struct module_kobject *mk, char *buffer)
|
|
{
|
|
return sprintf(buffer, "%u\n", mk->mod->init_layout.size);
|
|
}
|
|
|
|
static struct module_attribute modinfo_initsize =
|
|
__ATTR(initsize, 0444, show_initsize, NULL);
|
|
|
|
static ssize_t show_taint(struct module_attribute *mattr,
|
|
struct module_kobject *mk, char *buffer)
|
|
{
|
|
size_t l;
|
|
|
|
l = module_flags_taint(mk->mod, buffer);
|
|
buffer[l++] = '\n';
|
|
return l;
|
|
}
|
|
|
|
static struct module_attribute modinfo_taint =
|
|
__ATTR(taint, 0444, show_taint, NULL);
|
|
|
|
static struct module_attribute *modinfo_attrs[] = {
|
|
&module_uevent,
|
|
&modinfo_version,
|
|
&modinfo_srcversion,
|
|
&modinfo_initstate,
|
|
&modinfo_coresize,
|
|
&modinfo_initsize,
|
|
&modinfo_taint,
|
|
#ifdef CONFIG_MODULE_UNLOAD
|
|
&modinfo_refcnt,
|
|
#endif
|
|
NULL,
|
|
};
|
|
|
|
static const char vermagic[] = VERMAGIC_STRING;
|
|
|
|
static int try_to_force_load(struct module *mod, const char *reason)
|
|
{
|
|
#ifdef CONFIG_MODULE_FORCE_LOAD
|
|
if (!test_taint(TAINT_FORCED_MODULE))
|
|
pr_warn("%s: %s: kernel tainted.\n", mod->name, reason);
|
|
add_taint_module(mod, TAINT_FORCED_MODULE, LOCKDEP_NOW_UNRELIABLE);
|
|
return 0;
|
|
#else
|
|
return -ENOEXEC;
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_MODVERSIONS
|
|
|
|
static u32 resolve_rel_crc(const s32 *crc)
|
|
{
|
|
return *(u32 *)((void *)crc + *crc);
|
|
}
|
|
|
|
static int check_version(const struct load_info *info,
|
|
const char *symname,
|
|
struct module *mod,
|
|
const s32 *crc)
|
|
{
|
|
Elf_Shdr *sechdrs = info->sechdrs;
|
|
unsigned int versindex = info->index.vers;
|
|
unsigned int i, num_versions;
|
|
struct modversion_info *versions;
|
|
|
|
/* Exporting module didn't supply crcs? OK, we're already tainted. */
|
|
if (!crc)
|
|
return 1;
|
|
|
|
/* No versions at all? modprobe --force does this. */
|
|
if (versindex == 0)
|
|
return try_to_force_load(mod, symname) == 0;
|
|
|
|
versions = (void *) sechdrs[versindex].sh_addr;
|
|
num_versions = sechdrs[versindex].sh_size
|
|
/ sizeof(struct modversion_info);
|
|
|
|
for (i = 0; i < num_versions; i++) {
|
|
u32 crcval;
|
|
|
|
if (strcmp(versions[i].name, symname) != 0)
|
|
continue;
|
|
|
|
if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
|
|
crcval = resolve_rel_crc(crc);
|
|
else
|
|
crcval = *crc;
|
|
if (versions[i].crc == crcval)
|
|
return 1;
|
|
pr_debug("Found checksum %X vs module %lX\n",
|
|
crcval, versions[i].crc);
|
|
goto bad_version;
|
|
}
|
|
|
|
/* Broken toolchain. Warn once, then let it go.. */
|
|
pr_warn_once("%s: no symbol version for %s\n", info->name, symname);
|
|
return 1;
|
|
|
|
bad_version:
|
|
pr_warn("%s: disagrees about version of symbol %s\n",
|
|
info->name, symname);
|
|
return 0;
|
|
}
|
|
|
|
static inline int check_modstruct_version(const struct load_info *info,
|
|
struct module *mod)
|
|
{
|
|
const s32 *crc;
|
|
|
|
/*
|
|
* Since this should be found in kernel (which can't be removed), no
|
|
* locking is necessary -- use preempt_disable() to placate lockdep.
|
|
*/
|
|
preempt_disable();
|
|
if (!find_symbol(VMLINUX_SYMBOL_STR(module_layout), NULL,
|
|
&crc, true, false)) {
|
|
preempt_enable();
|
|
BUG();
|
|
}
|
|
preempt_enable();
|
|
return check_version(info, VMLINUX_SYMBOL_STR(module_layout),
|
|
mod, crc);
|
|
}
|
|
|
|
/* First part is kernel version, which we ignore if module has crcs. */
|
|
static inline int same_magic(const char *amagic, const char *bmagic,
|
|
bool has_crcs)
|
|
{
|
|
if (has_crcs) {
|
|
amagic += strcspn(amagic, " ");
|
|
bmagic += strcspn(bmagic, " ");
|
|
}
|
|
return strcmp(amagic, bmagic) == 0;
|
|
}
|
|
#else
|
|
static inline int check_version(const struct load_info *info,
|
|
const char *symname,
|
|
struct module *mod,
|
|
const s32 *crc)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static inline int check_modstruct_version(const struct load_info *info,
|
|
struct module *mod)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static inline int same_magic(const char *amagic, const char *bmagic,
|
|
bool has_crcs)
|
|
{
|
|
return strcmp(amagic, bmagic) == 0;
|
|
}
|
|
#endif /* CONFIG_MODVERSIONS */
|
|
|
|
/* Resolve a symbol for this module. I.e. if we find one, record usage. */
|
|
static const struct kernel_symbol *resolve_symbol(struct module *mod,
|
|
const struct load_info *info,
|
|
const char *name,
|
|
char ownername[])
|
|
{
|
|
struct module *owner;
|
|
const struct kernel_symbol *sym;
|
|
const s32 *crc;
|
|
int err;
|
|
|
|
/*
|
|
* The module_mutex should not be a heavily contended lock;
|
|
* if we get the occasional sleep here, we'll go an extra iteration
|
|
* in the wait_event_interruptible(), which is harmless.
|
|
*/
|
|
sched_annotate_sleep();
|
|
mutex_lock(&module_mutex);
|
|
sym = find_symbol(name, &owner, &crc,
|
|
!(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
|
|
if (!sym)
|
|
goto unlock;
|
|
|
|
if (!check_version(info, name, mod, crc)) {
|
|
sym = ERR_PTR(-EINVAL);
|
|
goto getname;
|
|
}
|
|
|
|
err = ref_module(mod, owner);
|
|
if (err) {
|
|
sym = ERR_PTR(err);
|
|
goto getname;
|
|
}
|
|
|
|
getname:
|
|
/* We must make copy under the lock if we failed to get ref. */
|
|
strncpy(ownername, module_name(owner), MODULE_NAME_LEN);
|
|
unlock:
|
|
mutex_unlock(&module_mutex);
|
|
return sym;
|
|
}
|
|
|
|
static const struct kernel_symbol *
|
|
resolve_symbol_wait(struct module *mod,
|
|
const struct load_info *info,
|
|
const char *name)
|
|
{
|
|
const struct kernel_symbol *ksym;
|
|
char owner[MODULE_NAME_LEN];
|
|
|
|
if (wait_event_interruptible_timeout(module_wq,
|
|
!IS_ERR(ksym = resolve_symbol(mod, info, name, owner))
|
|
|| PTR_ERR(ksym) != -EBUSY,
|
|
30 * HZ) <= 0) {
|
|
pr_warn("%s: gave up waiting for init of module %s.\n",
|
|
mod->name, owner);
|
|
}
|
|
return ksym;
|
|
}
|
|
|
|
/*
|
|
* /sys/module/foo/sections stuff
|
|
* J. Corbet <corbet@lwn.net>
|
|
*/
|
|
#ifdef CONFIG_SYSFS
|
|
|
|
#ifdef CONFIG_KALLSYMS
|
|
static inline bool sect_empty(const Elf_Shdr *sect)
|
|
{
|
|
return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0;
|
|
}
|
|
|
|
struct module_sect_attr {
|
|
struct module_attribute mattr;
|
|
char *name;
|
|
unsigned long address;
|
|
};
|
|
|
|
struct module_sect_attrs {
|
|
struct attribute_group grp;
|
|
unsigned int nsections;
|
|
struct module_sect_attr attrs[0];
|
|
};
|
|
|
|
static ssize_t module_sect_show(struct module_attribute *mattr,
|
|
struct module_kobject *mk, char *buf)
|
|
{
|
|
struct module_sect_attr *sattr =
|
|
container_of(mattr, struct module_sect_attr, mattr);
|
|
return sprintf(buf, "0x%pK\n", (void *)sattr->address);
|
|
}
|
|
|
|
static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
|
|
{
|
|
unsigned int section;
|
|
|
|
for (section = 0; section < sect_attrs->nsections; section++)
|
|
kfree(sect_attrs->attrs[section].name);
|
|
kfree(sect_attrs);
|
|
}
|
|
|
|
static void add_sect_attrs(struct module *mod, const struct load_info *info)
|
|
{
|
|
unsigned int nloaded = 0, i, size[2];
|
|
struct module_sect_attrs *sect_attrs;
|
|
struct module_sect_attr *sattr;
|
|
struct attribute **gattr;
|
|
|
|
/* Count loaded sections and allocate structures */
|
|
for (i = 0; i < info->hdr->e_shnum; i++)
|
|
if (!sect_empty(&info->sechdrs[i]))
|
|
nloaded++;
|
|
size[0] = ALIGN(sizeof(*sect_attrs)
|
|
+ nloaded * sizeof(sect_attrs->attrs[0]),
|
|
sizeof(sect_attrs->grp.attrs[0]));
|
|
size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]);
|
|
sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
|
|
if (sect_attrs == NULL)
|
|
return;
|
|
|
|
/* Setup section attributes. */
|
|
sect_attrs->grp.name = "sections";
|
|
sect_attrs->grp.attrs = (void *)sect_attrs + size[0];
|
|
|
|
sect_attrs->nsections = 0;
|
|
sattr = §_attrs->attrs[0];
|
|
gattr = §_attrs->grp.attrs[0];
|
|
for (i = 0; i < info->hdr->e_shnum; i++) {
|
|
Elf_Shdr *sec = &info->sechdrs[i];
|
|
if (sect_empty(sec))
|
|
continue;
|
|
sattr->address = sec->sh_addr;
|
|
sattr->name = kstrdup(info->secstrings + sec->sh_name,
|
|
GFP_KERNEL);
|
|
if (sattr->name == NULL)
|
|
goto out;
|
|
sect_attrs->nsections++;
|
|
sysfs_attr_init(&sattr->mattr.attr);
|
|
sattr->mattr.show = module_sect_show;
|
|
sattr->mattr.store = NULL;
|
|
sattr->mattr.attr.name = sattr->name;
|
|
sattr->mattr.attr.mode = S_IRUGO;
|
|
*(gattr++) = &(sattr++)->mattr.attr;
|
|
}
|
|
*gattr = NULL;
|
|
|
|
if (sysfs_create_group(&mod->mkobj.kobj, §_attrs->grp))
|
|
goto out;
|
|
|
|
mod->sect_attrs = sect_attrs;
|
|
return;
|
|
out:
|
|
free_sect_attrs(sect_attrs);
|
|
}
|
|
|
|
static void remove_sect_attrs(struct module *mod)
|
|
{
|
|
if (mod->sect_attrs) {
|
|
sysfs_remove_group(&mod->mkobj.kobj,
|
|
&mod->sect_attrs->grp);
|
|
/* We are positive that no one is using any sect attrs
|
|
* at this point. Deallocate immediately. */
|
|
free_sect_attrs(mod->sect_attrs);
|
|
mod->sect_attrs = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections.
|
|
*/
|
|
|
|
struct module_notes_attrs {
|
|
struct kobject *dir;
|
|
unsigned int notes;
|
|
struct bin_attribute attrs[0];
|
|
};
|
|
|
|
static ssize_t module_notes_read(struct file *filp, struct kobject *kobj,
|
|
struct bin_attribute *bin_attr,
|
|
char *buf, loff_t pos, size_t count)
|
|
{
|
|
/*
|
|
* The caller checked the pos and count against our size.
|
|
*/
|
|
memcpy(buf, bin_attr->private + pos, count);
|
|
return count;
|
|
}
|
|
|
|
static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
|
|
unsigned int i)
|
|
{
|
|
if (notes_attrs->dir) {
|
|
while (i-- > 0)
|
|
sysfs_remove_bin_file(notes_attrs->dir,
|
|
¬es_attrs->attrs[i]);
|
|
kobject_put(notes_attrs->dir);
|
|
}
|
|
kfree(notes_attrs);
|
|
}
|
|
|
|
static void add_notes_attrs(struct module *mod, const struct load_info *info)
|
|
{
|
|
unsigned int notes, loaded, i;
|
|
struct module_notes_attrs *notes_attrs;
|
|
struct bin_attribute *nattr;
|
|
|
|
/* failed to create section attributes, so can't create notes */
|
|
if (!mod->sect_attrs)
|
|
return;
|
|
|
|
/* Count notes sections and allocate structures. */
|
|
notes = 0;
|
|
for (i = 0; i < info->hdr->e_shnum; i++)
|
|
if (!sect_empty(&info->sechdrs[i]) &&
|
|
(info->sechdrs[i].sh_type == SHT_NOTE))
|
|
++notes;
|
|
|
|
if (notes == 0)
|
|
return;
|
|
|
|
notes_attrs = kzalloc(sizeof(*notes_attrs)
|
|
+ notes * sizeof(notes_attrs->attrs[0]),
|
|
GFP_KERNEL);
|
|
if (notes_attrs == NULL)
|
|
return;
|
|
|
|
notes_attrs->notes = notes;
|
|
nattr = ¬es_attrs->attrs[0];
|
|
for (loaded = i = 0; i < info->hdr->e_shnum; ++i) {
|
|
if (sect_empty(&info->sechdrs[i]))
|
|
continue;
|
|
if (info->sechdrs[i].sh_type == SHT_NOTE) {
|
|
sysfs_bin_attr_init(nattr);
|
|
nattr->attr.name = mod->sect_attrs->attrs[loaded].name;
|
|
nattr->attr.mode = S_IRUGO;
|
|
nattr->size = info->sechdrs[i].sh_size;
|
|
nattr->private = (void *) info->sechdrs[i].sh_addr;
|
|
nattr->read = module_notes_read;
|
|
++nattr;
|
|
}
|
|
++loaded;
|
|
}
|
|
|
|
notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj);
|
|
if (!notes_attrs->dir)
|
|
goto out;
|
|
|
|
for (i = 0; i < notes; ++i)
|
|
if (sysfs_create_bin_file(notes_attrs->dir,
|
|
¬es_attrs->attrs[i]))
|
|
goto out;
|
|
|
|
mod->notes_attrs = notes_attrs;
|
|
return;
|
|
|
|
out:
|
|
free_notes_attrs(notes_attrs, i);
|
|
}
|
|
|
|
static void remove_notes_attrs(struct module *mod)
|
|
{
|
|
if (mod->notes_attrs)
|
|
free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes);
|
|
}
|
|
|
|
#else
|
|
|
|
static inline void add_sect_attrs(struct module *mod,
|
|
const struct load_info *info)
|
|
{
|
|
}
|
|
|
|
static inline void remove_sect_attrs(struct module *mod)
|
|
{
|
|
}
|
|
|
|
static inline void add_notes_attrs(struct module *mod,
|
|
const struct load_info *info)
|
|
{
|
|
}
|
|
|
|
static inline void remove_notes_attrs(struct module *mod)
|
|
{
|
|
}
|
|
#endif /* CONFIG_KALLSYMS */
|
|
|
|
static void del_usage_links(struct module *mod)
|
|
{
|
|
#ifdef CONFIG_MODULE_UNLOAD
|
|
struct module_use *use;
|
|
|
|
mutex_lock(&module_mutex);
|
|
list_for_each_entry(use, &mod->target_list, target_list)
|
|
sysfs_remove_link(use->target->holders_dir, mod->name);
|
|
mutex_unlock(&module_mutex);
|
|
#endif
|
|
}
|
|
|
|
static int add_usage_links(struct module *mod)
|
|
{
|
|
int ret = 0;
|
|
#ifdef CONFIG_MODULE_UNLOAD
|
|
struct module_use *use;
|
|
|
|
mutex_lock(&module_mutex);
|
|
list_for_each_entry(use, &mod->target_list, target_list) {
|
|
ret = sysfs_create_link(use->target->holders_dir,
|
|
&mod->mkobj.kobj, mod->name);
|
|
if (ret)
|
|
break;
|
|
}
|
|
mutex_unlock(&module_mutex);
|
|
if (ret)
|
|
del_usage_links(mod);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
static void module_remove_modinfo_attrs(struct module *mod, int end);
|
|
|
|
static int module_add_modinfo_attrs(struct module *mod)
|
|
{
|
|
struct module_attribute *attr;
|
|
struct module_attribute *temp_attr;
|
|
int error = 0;
|
|
int i;
|
|
|
|
mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) *
|
|
(ARRAY_SIZE(modinfo_attrs) + 1)),
|
|
GFP_KERNEL);
|
|
if (!mod->modinfo_attrs)
|
|
return -ENOMEM;
|
|
|
|
temp_attr = mod->modinfo_attrs;
|
|
for (i = 0; (attr = modinfo_attrs[i]); i++) {
|
|
if (!attr->test || attr->test(mod)) {
|
|
memcpy(temp_attr, attr, sizeof(*temp_attr));
|
|
sysfs_attr_init(&temp_attr->attr);
|
|
error = sysfs_create_file(&mod->mkobj.kobj,
|
|
&temp_attr->attr);
|
|
if (error)
|
|
goto error_out;
|
|
++temp_attr;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
error_out:
|
|
if (i > 0)
|
|
module_remove_modinfo_attrs(mod, --i);
|
|
else
|
|
kfree(mod->modinfo_attrs);
|
|
return error;
|
|
}
|
|
|
|
static void module_remove_modinfo_attrs(struct module *mod, int end)
|
|
{
|
|
struct module_attribute *attr;
|
|
int i;
|
|
|
|
for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
|
|
if (end >= 0 && i > end)
|
|
break;
|
|
/* pick a field to test for end of list */
|
|
if (!attr->attr.name)
|
|
break;
|
|
sysfs_remove_file(&mod->mkobj.kobj, &attr->attr);
|
|
if (attr->free)
|
|
attr->free(mod);
|
|
}
|
|
kfree(mod->modinfo_attrs);
|
|
}
|
|
|
|
static void mod_kobject_put(struct module *mod)
|
|
{
|
|
DECLARE_COMPLETION_ONSTACK(c);
|
|
mod->mkobj.kobj_completion = &c;
|
|
kobject_put(&mod->mkobj.kobj);
|
|
wait_for_completion(&c);
|
|
}
|
|
|
|
static int mod_sysfs_init(struct module *mod)
|
|
{
|
|
int err;
|
|
struct kobject *kobj;
|
|
|
|
if (!module_sysfs_initialized) {
|
|
pr_err("%s: module sysfs not initialized\n", mod->name);
|
|
err = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
kobj = kset_find_obj(module_kset, mod->name);
|
|
if (kobj) {
|
|
pr_err("%s: module is already loaded\n", mod->name);
|
|
kobject_put(kobj);
|
|
err = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
mod->mkobj.mod = mod;
|
|
|
|
memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj));
|
|
mod->mkobj.kobj.kset = module_kset;
|
|
err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL,
|
|
"%s", mod->name);
|
|
if (err)
|
|
mod_kobject_put(mod);
|
|
|
|
/* delay uevent until full sysfs population */
|
|
out:
|
|
return err;
|
|
}
|
|
|
|
static int mod_sysfs_setup(struct module *mod,
|
|
const struct load_info *info,
|
|
struct kernel_param *kparam,
|
|
unsigned int num_params)
|
|
{
|
|
int err;
|
|
|
|
err = mod_sysfs_init(mod);
|
|
if (err)
|
|
goto out;
|
|
|
|
mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj);
|
|
if (!mod->holders_dir) {
|
|
err = -ENOMEM;
|
|
goto out_unreg;
|
|
}
|
|
|
|
err = module_param_sysfs_setup(mod, kparam, num_params);
|
|
if (err)
|
|
goto out_unreg_holders;
|
|
|
|
err = module_add_modinfo_attrs(mod);
|
|
if (err)
|
|
goto out_unreg_param;
|
|
|
|
err = add_usage_links(mod);
|
|
if (err)
|
|
goto out_unreg_modinfo_attrs;
|
|
|
|
add_sect_attrs(mod, info);
|
|
add_notes_attrs(mod, info);
|
|
|
|
kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
|
|
return 0;
|
|
|
|
out_unreg_modinfo_attrs:
|
|
module_remove_modinfo_attrs(mod, -1);
|
|
out_unreg_param:
|
|
module_param_sysfs_remove(mod);
|
|
out_unreg_holders:
|
|
kobject_put(mod->holders_dir);
|
|
out_unreg:
|
|
mod_kobject_put(mod);
|
|
out:
|
|
return err;
|
|
}
|
|
|
|
static void mod_sysfs_fini(struct module *mod)
|
|
{
|
|
remove_notes_attrs(mod);
|
|
remove_sect_attrs(mod);
|
|
mod_kobject_put(mod);
|
|
}
|
|
|
|
static void init_param_lock(struct module *mod)
|
|
{
|
|
mutex_init(&mod->param_lock);
|
|
}
|
|
#else /* !CONFIG_SYSFS */
|
|
|
|
static int mod_sysfs_setup(struct module *mod,
|
|
const struct load_info *info,
|
|
struct kernel_param *kparam,
|
|
unsigned int num_params)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void mod_sysfs_fini(struct module *mod)
|
|
{
|
|
}
|
|
|
|
static void module_remove_modinfo_attrs(struct module *mod, int end)
|
|
{
|
|
}
|
|
|
|
static void del_usage_links(struct module *mod)
|
|
{
|
|
}
|
|
|
|
static void init_param_lock(struct module *mod)
|
|
{
|
|
}
|
|
#endif /* CONFIG_SYSFS */
|
|
|
|
static void mod_sysfs_teardown(struct module *mod)
|
|
{
|
|
del_usage_links(mod);
|
|
module_remove_modinfo_attrs(mod, -1);
|
|
module_param_sysfs_remove(mod);
|
|
kobject_put(mod->mkobj.drivers_dir);
|
|
kobject_put(mod->holders_dir);
|
|
mod_sysfs_fini(mod);
|
|
}
|
|
|
|
#ifdef CONFIG_STRICT_MODULE_RWX
|
|
/*
|
|
* LKM RO/NX protection: protect module's text/ro-data
|
|
* from modification and any data from execution.
|
|
*
|
|
* General layout of module is:
|
|
* [text] [read-only-data] [ro-after-init] [writable data]
|
|
* text_size -----^ ^ ^ ^
|
|
* ro_size ------------------------| | |
|
|
* ro_after_init_size -----------------------------| |
|
|
* size -----------------------------------------------------------|
|
|
*
|
|
* These values are always page-aligned (as is base)
|
|
*/
|
|
static void frob_text(const struct module_layout *layout,
|
|
int (*set_memory)(unsigned long start, int num_pages))
|
|
{
|
|
BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
|
|
BUG_ON((unsigned long)layout->text_size & (PAGE_SIZE-1));
|
|
set_memory((unsigned long)layout->base,
|
|
layout->text_size >> PAGE_SHIFT);
|
|
}
|
|
|
|
static void frob_rodata(const struct module_layout *layout,
|
|
int (*set_memory)(unsigned long start, int num_pages))
|
|
{
|
|
BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
|
|
BUG_ON((unsigned long)layout->text_size & (PAGE_SIZE-1));
|
|
BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1));
|
|
set_memory((unsigned long)layout->base + layout->text_size,
|
|
(layout->ro_size - layout->text_size) >> PAGE_SHIFT);
|
|
}
|
|
|
|
static void frob_ro_after_init(const struct module_layout *layout,
|
|
int (*set_memory)(unsigned long start, int num_pages))
|
|
{
|
|
BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
|
|
BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1));
|
|
BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1));
|
|
set_memory((unsigned long)layout->base + layout->ro_size,
|
|
(layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT);
|
|
}
|
|
|
|
static void frob_writable_data(const struct module_layout *layout,
|
|
int (*set_memory)(unsigned long start, int num_pages))
|
|
{
|
|
BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
|
|
BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1));
|
|
BUG_ON((unsigned long)layout->size & (PAGE_SIZE-1));
|
|
set_memory((unsigned long)layout->base + layout->ro_after_init_size,
|
|
(layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
|
|
}
|
|
|
|
/* livepatching wants to disable read-only so it can frob module. */
|
|
void module_disable_ro(const struct module *mod)
|
|
{
|
|
if (!rodata_enabled)
|
|
return;
|
|
|
|
frob_text(&mod->core_layout, set_memory_rw);
|
|
frob_rodata(&mod->core_layout, set_memory_rw);
|
|
frob_ro_after_init(&mod->core_layout, set_memory_rw);
|
|
frob_text(&mod->init_layout, set_memory_rw);
|
|
frob_rodata(&mod->init_layout, set_memory_rw);
|
|
}
|
|
|
|
void module_enable_ro(const struct module *mod, bool after_init)
|
|
{
|
|
if (!rodata_enabled)
|
|
return;
|
|
|
|
frob_text(&mod->core_layout, set_memory_ro);
|
|
frob_rodata(&mod->core_layout, set_memory_ro);
|
|
frob_text(&mod->init_layout, set_memory_ro);
|
|
frob_rodata(&mod->init_layout, set_memory_ro);
|
|
|
|
if (after_init)
|
|
frob_ro_after_init(&mod->core_layout, set_memory_ro);
|
|
}
|
|
|
|
static void module_enable_nx(const struct module *mod)
|
|
{
|
|
frob_rodata(&mod->core_layout, set_memory_nx);
|
|
frob_ro_after_init(&mod->core_layout, set_memory_nx);
|
|
frob_writable_data(&mod->core_layout, set_memory_nx);
|
|
frob_rodata(&mod->init_layout, set_memory_nx);
|
|
frob_writable_data(&mod->init_layout, set_memory_nx);
|
|
}
|
|
|
|
static void module_disable_nx(const struct module *mod)
|
|
{
|
|
frob_rodata(&mod->core_layout, set_memory_x);
|
|
frob_ro_after_init(&mod->core_layout, set_memory_x);
|
|
frob_writable_data(&mod->core_layout, set_memory_x);
|
|
frob_rodata(&mod->init_layout, set_memory_x);
|
|
frob_writable_data(&mod->init_layout, set_memory_x);
|
|
}
|
|
|
|
/* Iterate through all modules and set each module's text as RW */
|
|
void set_all_modules_text_rw(void)
|
|
{
|
|
struct module *mod;
|
|
|
|
if (!rodata_enabled)
|
|
return;
|
|
|
|
mutex_lock(&module_mutex);
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
|
|
frob_text(&mod->core_layout, set_memory_rw);
|
|
frob_text(&mod->init_layout, set_memory_rw);
|
|
}
|
|
mutex_unlock(&module_mutex);
|
|
}
|
|
|
|
/* Iterate through all modules and set each module's text as RO */
|
|
void set_all_modules_text_ro(void)
|
|
{
|
|
struct module *mod;
|
|
|
|
if (!rodata_enabled)
|
|
return;
|
|
|
|
mutex_lock(&module_mutex);
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
/*
|
|
* Ignore going modules since it's possible that ro
|
|
* protection has already been disabled, otherwise we'll
|
|
* run into protection faults at module deallocation.
|
|
*/
|
|
if (mod->state == MODULE_STATE_UNFORMED ||
|
|
mod->state == MODULE_STATE_GOING)
|
|
continue;
|
|
|
|
frob_text(&mod->core_layout, set_memory_ro);
|
|
frob_text(&mod->init_layout, set_memory_ro);
|
|
}
|
|
mutex_unlock(&module_mutex);
|
|
}
|
|
|
|
static void disable_ro_nx(const struct module_layout *layout)
|
|
{
|
|
if (rodata_enabled) {
|
|
frob_text(layout, set_memory_rw);
|
|
frob_rodata(layout, set_memory_rw);
|
|
frob_ro_after_init(layout, set_memory_rw);
|
|
}
|
|
frob_rodata(layout, set_memory_x);
|
|
frob_ro_after_init(layout, set_memory_x);
|
|
frob_writable_data(layout, set_memory_x);
|
|
}
|
|
|
|
#else
|
|
static void disable_ro_nx(const struct module_layout *layout) { }
|
|
static void module_enable_nx(const struct module *mod) { }
|
|
static void module_disable_nx(const struct module *mod) { }
|
|
#endif
|
|
|
|
#ifdef CONFIG_LIVEPATCH
|
|
/*
|
|
* Persist Elf information about a module. Copy the Elf header,
|
|
* section header table, section string table, and symtab section
|
|
* index from info to mod->klp_info.
|
|
*/
|
|
static int copy_module_elf(struct module *mod, struct load_info *info)
|
|
{
|
|
unsigned int size, symndx;
|
|
int ret;
|
|
|
|
size = sizeof(*mod->klp_info);
|
|
mod->klp_info = kmalloc(size, GFP_KERNEL);
|
|
if (mod->klp_info == NULL)
|
|
return -ENOMEM;
|
|
|
|
/* Elf header */
|
|
size = sizeof(mod->klp_info->hdr);
|
|
memcpy(&mod->klp_info->hdr, info->hdr, size);
|
|
|
|
/* Elf section header table */
|
|
size = sizeof(*info->sechdrs) * info->hdr->e_shnum;
|
|
mod->klp_info->sechdrs = kmalloc(size, GFP_KERNEL);
|
|
if (mod->klp_info->sechdrs == NULL) {
|
|
ret = -ENOMEM;
|
|
goto free_info;
|
|
}
|
|
memcpy(mod->klp_info->sechdrs, info->sechdrs, size);
|
|
|
|
/* Elf section name string table */
|
|
size = info->sechdrs[info->hdr->e_shstrndx].sh_size;
|
|
mod->klp_info->secstrings = kmalloc(size, GFP_KERNEL);
|
|
if (mod->klp_info->secstrings == NULL) {
|
|
ret = -ENOMEM;
|
|
goto free_sechdrs;
|
|
}
|
|
memcpy(mod->klp_info->secstrings, info->secstrings, size);
|
|
|
|
/* Elf symbol section index */
|
|
symndx = info->index.sym;
|
|
mod->klp_info->symndx = symndx;
|
|
|
|
/*
|
|
* For livepatch modules, core_kallsyms.symtab is a complete
|
|
* copy of the original symbol table. Adjust sh_addr to point
|
|
* to core_kallsyms.symtab since the copy of the symtab in module
|
|
* init memory is freed at the end of do_init_module().
|
|
*/
|
|
mod->klp_info->sechdrs[symndx].sh_addr = \
|
|
(unsigned long) mod->core_kallsyms.symtab;
|
|
|
|
return 0;
|
|
|
|
free_sechdrs:
|
|
kfree(mod->klp_info->sechdrs);
|
|
free_info:
|
|
kfree(mod->klp_info);
|
|
return ret;
|
|
}
|
|
|
|
static void free_module_elf(struct module *mod)
|
|
{
|
|
kfree(mod->klp_info->sechdrs);
|
|
kfree(mod->klp_info->secstrings);
|
|
kfree(mod->klp_info);
|
|
}
|
|
#else /* !CONFIG_LIVEPATCH */
|
|
static int copy_module_elf(struct module *mod, struct load_info *info)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void free_module_elf(struct module *mod)
|
|
{
|
|
}
|
|
#endif /* CONFIG_LIVEPATCH */
|
|
|
|
void __weak module_memfree(void *module_region)
|
|
{
|
|
vfree(module_region);
|
|
}
|
|
|
|
void __weak module_arch_cleanup(struct module *mod)
|
|
{
|
|
}
|
|
|
|
void __weak module_arch_freeing_init(struct module *mod)
|
|
{
|
|
}
|
|
|
|
static void cfi_cleanup(struct module *mod);
|
|
|
|
/* Free a module, remove from lists, etc. */
|
|
static void free_module(struct module *mod)
|
|
{
|
|
trace_module_free(mod);
|
|
|
|
mod_sysfs_teardown(mod);
|
|
|
|
/* We leave it in list to prevent duplicate loads, but make sure
|
|
* that noone uses it while it's being deconstructed. */
|
|
mutex_lock(&module_mutex);
|
|
mod->state = MODULE_STATE_UNFORMED;
|
|
mutex_unlock(&module_mutex);
|
|
|
|
/* Remove dynamic debug info */
|
|
ddebug_remove_module(mod->name);
|
|
|
|
/* Arch-specific cleanup. */
|
|
module_arch_cleanup(mod);
|
|
|
|
/* Module unload stuff */
|
|
module_unload_free(mod);
|
|
|
|
/* Free any allocated parameters. */
|
|
destroy_params(mod->kp, mod->num_kp);
|
|
|
|
if (is_livepatch_module(mod))
|
|
free_module_elf(mod);
|
|
|
|
/* Now we can delete it from the lists */
|
|
mutex_lock(&module_mutex);
|
|
/* Unlink carefully: kallsyms could be walking list. */
|
|
list_del_rcu(&mod->list);
|
|
mod_tree_remove(mod);
|
|
/* Remove this module from bug list, this uses list_del_rcu */
|
|
module_bug_cleanup(mod);
|
|
/* Wait for RCU-sched synchronizing before releasing mod->list and buglist. */
|
|
synchronize_sched();
|
|
mutex_unlock(&module_mutex);
|
|
|
|
/* This may be empty, but that's OK */
|
|
disable_ro_nx(&mod->init_layout);
|
|
|
|
/* Clean up CFI for the module. */
|
|
cfi_cleanup(mod);
|
|
|
|
module_arch_freeing_init(mod);
|
|
module_memfree(mod->init_layout.base);
|
|
kfree(mod->args);
|
|
percpu_modfree(mod);
|
|
|
|
/* Free lock-classes; relies on the preceding sync_rcu(). */
|
|
lockdep_free_key_range(mod->core_layout.base, mod->core_layout.size);
|
|
|
|
/* Finally, free the core (containing the module structure) */
|
|
disable_ro_nx(&mod->core_layout);
|
|
#ifdef CONFIG_DEBUG_MODULE_LOAD_INFO
|
|
pr_info("Unloaded %s: module core layout address range: 0x%lx-0x%lx\n",
|
|
mod->name, (long)mod->core_layout.base,
|
|
(long)(mod->core_layout.base + mod->core_layout.size - 1));
|
|
#endif
|
|
module_memfree(mod->core_layout.base);
|
|
|
|
#ifdef CONFIG_MPU
|
|
update_protections(current->mm);
|
|
#endif
|
|
}
|
|
|
|
void *__symbol_get(const char *symbol)
|
|
{
|
|
struct module *owner;
|
|
const struct kernel_symbol *sym;
|
|
|
|
preempt_disable();
|
|
sym = find_symbol(symbol, &owner, NULL, true, true);
|
|
if (sym && strong_try_module_get(owner))
|
|
sym = NULL;
|
|
preempt_enable();
|
|
|
|
return sym ? (void *)sym->value : NULL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(__symbol_get);
|
|
|
|
/*
|
|
* Ensure that an exported symbol [global namespace] does not already exist
|
|
* in the kernel or in some other module's exported symbol table.
|
|
*
|
|
* You must hold the module_mutex.
|
|
*/
|
|
static int verify_export_symbols(struct module *mod)
|
|
{
|
|
unsigned int i;
|
|
struct module *owner;
|
|
const struct kernel_symbol *s;
|
|
struct {
|
|
const struct kernel_symbol *sym;
|
|
unsigned int num;
|
|
} arr[] = {
|
|
{ mod->syms, mod->num_syms },
|
|
{ mod->gpl_syms, mod->num_gpl_syms },
|
|
{ mod->gpl_future_syms, mod->num_gpl_future_syms },
|
|
#ifdef CONFIG_UNUSED_SYMBOLS
|
|
{ mod->unused_syms, mod->num_unused_syms },
|
|
{ mod->unused_gpl_syms, mod->num_unused_gpl_syms },
|
|
#endif
|
|
};
|
|
|
|
for (i = 0; i < ARRAY_SIZE(arr); i++) {
|
|
for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
|
|
if (find_symbol(s->name, &owner, NULL, true, false)) {
|
|
pr_err("%s: exports duplicate symbol %s"
|
|
" (owned by %s)\n",
|
|
mod->name, s->name, module_name(owner));
|
|
return -ENOEXEC;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Change all symbols so that st_value encodes the pointer directly. */
|
|
static int simplify_symbols(struct module *mod, const struct load_info *info)
|
|
{
|
|
Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
|
|
Elf_Sym *sym = (void *)symsec->sh_addr;
|
|
unsigned long secbase;
|
|
unsigned int i;
|
|
int ret = 0;
|
|
const struct kernel_symbol *ksym;
|
|
|
|
for (i = 1; i < symsec->sh_size / sizeof(Elf_Sym); i++) {
|
|
const char *name = info->strtab + sym[i].st_name;
|
|
|
|
switch (sym[i].st_shndx) {
|
|
case SHN_COMMON:
|
|
/* Ignore common symbols */
|
|
if (!strncmp(name, "__gnu_lto", 9))
|
|
break;
|
|
|
|
/* We compiled with -fno-common. These are not
|
|
supposed to happen. */
|
|
pr_debug("Common symbol: %s\n", name);
|
|
pr_warn("%s: please compile with -fno-common\n",
|
|
mod->name);
|
|
ret = -ENOEXEC;
|
|
break;
|
|
|
|
case SHN_ABS:
|
|
/* Don't need to do anything */
|
|
pr_debug("Absolute symbol: 0x%08lx\n",
|
|
(long)sym[i].st_value);
|
|
break;
|
|
|
|
case SHN_LIVEPATCH:
|
|
/* Livepatch symbols are resolved by livepatch */
|
|
break;
|
|
|
|
case SHN_UNDEF:
|
|
ksym = resolve_symbol_wait(mod, info, name);
|
|
/* Ok if resolved. */
|
|
if (ksym && !IS_ERR(ksym)) {
|
|
sym[i].st_value = ksym->value;
|
|
break;
|
|
}
|
|
|
|
/* Ok if weak. */
|
|
if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
|
|
break;
|
|
|
|
pr_warn("%s: Unknown symbol %s (err %li)\n",
|
|
mod->name, name, PTR_ERR(ksym));
|
|
ret = PTR_ERR(ksym) ?: -ENOENT;
|
|
break;
|
|
|
|
default:
|
|
/* Divert to percpu allocation if a percpu var. */
|
|
if (sym[i].st_shndx == info->index.pcpu)
|
|
secbase = (unsigned long)mod_percpu(mod);
|
|
else
|
|
secbase = info->sechdrs[sym[i].st_shndx].sh_addr;
|
|
sym[i].st_value += secbase;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int apply_relocations(struct module *mod, const struct load_info *info)
|
|
{
|
|
unsigned int i;
|
|
int err = 0;
|
|
|
|
/* Now do relocations. */
|
|
for (i = 1; i < info->hdr->e_shnum; i++) {
|
|
unsigned int infosec = info->sechdrs[i].sh_info;
|
|
|
|
/* Not a valid relocation section? */
|
|
if (infosec >= info->hdr->e_shnum)
|
|
continue;
|
|
|
|
/* Don't bother with non-allocated sections */
|
|
if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC))
|
|
continue;
|
|
|
|
/* Livepatch relocation sections are applied by livepatch */
|
|
if (info->sechdrs[i].sh_flags & SHF_RELA_LIVEPATCH)
|
|
continue;
|
|
|
|
if (info->sechdrs[i].sh_type == SHT_REL)
|
|
err = apply_relocate(info->sechdrs, info->strtab,
|
|
info->index.sym, i, mod);
|
|
else if (info->sechdrs[i].sh_type == SHT_RELA)
|
|
err = apply_relocate_add(info->sechdrs, info->strtab,
|
|
info->index.sym, i, mod);
|
|
if (err < 0)
|
|
break;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/* Additional bytes needed by arch in front of individual sections */
|
|
unsigned int __weak arch_mod_section_prepend(struct module *mod,
|
|
unsigned int section)
|
|
{
|
|
/* default implementation just returns zero */
|
|
return 0;
|
|
}
|
|
|
|
/* Update size with this section: return offset. */
|
|
static long get_offset(struct module *mod, unsigned int *size,
|
|
Elf_Shdr *sechdr, unsigned int section)
|
|
{
|
|
long ret;
|
|
|
|
*size += arch_mod_section_prepend(mod, section);
|
|
ret = ALIGN(*size, sechdr->sh_addralign ?: 1);
|
|
*size = ret + sechdr->sh_size;
|
|
return ret;
|
|
}
|
|
|
|
/* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld
|
|
might -- code, read-only data, read-write data, small data. Tally
|
|
sizes, and place the offsets into sh_entsize fields: high bit means it
|
|
belongs in init. */
|
|
static void layout_sections(struct module *mod, struct load_info *info)
|
|
{
|
|
static unsigned long const masks[][2] = {
|
|
/* NOTE: all executable code must be the first section
|
|
* in this array; otherwise modify the text_size
|
|
* finder in the two loops below */
|
|
{ SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },
|
|
{ SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },
|
|
{ SHF_RO_AFTER_INIT | SHF_ALLOC, ARCH_SHF_SMALL },
|
|
{ SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },
|
|
{ ARCH_SHF_SMALL | SHF_ALLOC, 0 }
|
|
};
|
|
unsigned int m, i;
|
|
|
|
for (i = 0; i < info->hdr->e_shnum; i++)
|
|
info->sechdrs[i].sh_entsize = ~0UL;
|
|
|
|
pr_debug("Core section allocation order:\n");
|
|
for (m = 0; m < ARRAY_SIZE(masks); ++m) {
|
|
for (i = 0; i < info->hdr->e_shnum; ++i) {
|
|
Elf_Shdr *s = &info->sechdrs[i];
|
|
const char *sname = info->secstrings + s->sh_name;
|
|
|
|
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|
|
|| (s->sh_flags & masks[m][1])
|
|
|| s->sh_entsize != ~0UL
|
|
|| strstarts(sname, ".init"))
|
|
continue;
|
|
s->sh_entsize = get_offset(mod, &mod->core_layout.size, s, i);
|
|
pr_debug("\t%s\n", sname);
|
|
}
|
|
switch (m) {
|
|
case 0: /* executable */
|
|
mod->core_layout.size = debug_align(mod->core_layout.size);
|
|
mod->core_layout.text_size = mod->core_layout.size;
|
|
break;
|
|
case 1: /* RO: text and ro-data */
|
|
mod->core_layout.size = debug_align(mod->core_layout.size);
|
|
mod->core_layout.ro_size = mod->core_layout.size;
|
|
break;
|
|
case 2: /* RO after init */
|
|
mod->core_layout.size = debug_align(mod->core_layout.size);
|
|
mod->core_layout.ro_after_init_size = mod->core_layout.size;
|
|
break;
|
|
case 4: /* whole core */
|
|
mod->core_layout.size = debug_align(mod->core_layout.size);
|
|
break;
|
|
}
|
|
}
|
|
|
|
pr_debug("Init section allocation order:\n");
|
|
for (m = 0; m < ARRAY_SIZE(masks); ++m) {
|
|
for (i = 0; i < info->hdr->e_shnum; ++i) {
|
|
Elf_Shdr *s = &info->sechdrs[i];
|
|
const char *sname = info->secstrings + s->sh_name;
|
|
|
|
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|
|
|| (s->sh_flags & masks[m][1])
|
|
|| s->sh_entsize != ~0UL
|
|
|| !strstarts(sname, ".init"))
|
|
continue;
|
|
s->sh_entsize = (get_offset(mod, &mod->init_layout.size, s, i)
|
|
| INIT_OFFSET_MASK);
|
|
pr_debug("\t%s\n", sname);
|
|
}
|
|
switch (m) {
|
|
case 0: /* executable */
|
|
mod->init_layout.size = debug_align(mod->init_layout.size);
|
|
mod->init_layout.text_size = mod->init_layout.size;
|
|
break;
|
|
case 1: /* RO: text and ro-data */
|
|
mod->init_layout.size = debug_align(mod->init_layout.size);
|
|
mod->init_layout.ro_size = mod->init_layout.size;
|
|
break;
|
|
case 2:
|
|
/*
|
|
* RO after init doesn't apply to init_layout (only
|
|
* core_layout), so it just takes the value of ro_size.
|
|
*/
|
|
mod->init_layout.ro_after_init_size = mod->init_layout.ro_size;
|
|
break;
|
|
case 4: /* whole init */
|
|
mod->init_layout.size = debug_align(mod->init_layout.size);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void set_license(struct module *mod, const char *license)
|
|
{
|
|
if (!license)
|
|
license = "unspecified";
|
|
|
|
if (!license_is_gpl_compatible(license)) {
|
|
if (!test_taint(TAINT_PROPRIETARY_MODULE))
|
|
pr_warn("%s: module license '%s' taints kernel.\n",
|
|
mod->name, license);
|
|
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
|
|
LOCKDEP_NOW_UNRELIABLE);
|
|
}
|
|
}
|
|
|
|
/* Parse tag=value strings from .modinfo section */
|
|
static char *next_string(char *string, unsigned long *secsize)
|
|
{
|
|
/* Skip non-zero chars */
|
|
while (string[0]) {
|
|
string++;
|
|
if ((*secsize)-- <= 1)
|
|
return NULL;
|
|
}
|
|
|
|
/* Skip any zero padding. */
|
|
while (!string[0]) {
|
|
string++;
|
|
if ((*secsize)-- <= 1)
|
|
return NULL;
|
|
}
|
|
return string;
|
|
}
|
|
|
|
static char *get_modinfo(struct load_info *info, const char *tag)
|
|
{
|
|
char *p;
|
|
unsigned int taglen = strlen(tag);
|
|
Elf_Shdr *infosec = &info->sechdrs[info->index.info];
|
|
unsigned long size = infosec->sh_size;
|
|
|
|
for (p = (char *)infosec->sh_addr; p; p = next_string(p, &size)) {
|
|
if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
|
|
return p + taglen + 1;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void setup_modinfo(struct module *mod, struct load_info *info)
|
|
{
|
|
struct module_attribute *attr;
|
|
int i;
|
|
|
|
for (i = 0; (attr = modinfo_attrs[i]); i++) {
|
|
if (attr->setup)
|
|
attr->setup(mod, get_modinfo(info, attr->attr.name));
|
|
}
|
|
}
|
|
|
|
static void free_modinfo(struct module *mod)
|
|
{
|
|
struct module_attribute *attr;
|
|
int i;
|
|
|
|
for (i = 0; (attr = modinfo_attrs[i]); i++) {
|
|
if (attr->free)
|
|
attr->free(mod);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_KALLSYMS
|
|
|
|
/* lookup symbol in given range of kernel_symbols */
|
|
static const struct kernel_symbol *lookup_symbol(const char *name,
|
|
const struct kernel_symbol *start,
|
|
const struct kernel_symbol *stop)
|
|
{
|
|
return bsearch(name, start, stop - start,
|
|
sizeof(struct kernel_symbol), cmp_name);
|
|
}
|
|
|
|
static int is_exported(const char *name, unsigned long value,
|
|
const struct module *mod)
|
|
{
|
|
const struct kernel_symbol *ks;
|
|
if (!mod)
|
|
ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
|
|
else
|
|
ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
|
|
return ks != NULL && ks->value == value;
|
|
}
|
|
|
|
/* As per nm */
|
|
static char elf_type(const Elf_Sym *sym, const struct load_info *info)
|
|
{
|
|
const Elf_Shdr *sechdrs = info->sechdrs;
|
|
|
|
if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
|
|
if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)
|
|
return 'v';
|
|
else
|
|
return 'w';
|
|
}
|
|
if (sym->st_shndx == SHN_UNDEF)
|
|
return 'U';
|
|
if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu)
|
|
return 'a';
|
|
if (sym->st_shndx >= SHN_LORESERVE)
|
|
return '?';
|
|
if (sechdrs[sym->st_shndx].sh_flags & SHF_EXECINSTR)
|
|
return 't';
|
|
if (sechdrs[sym->st_shndx].sh_flags & SHF_ALLOC
|
|
&& sechdrs[sym->st_shndx].sh_type != SHT_NOBITS) {
|
|
if (!(sechdrs[sym->st_shndx].sh_flags & SHF_WRITE))
|
|
return 'r';
|
|
else if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)
|
|
return 'g';
|
|
else
|
|
return 'd';
|
|
}
|
|
if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) {
|
|
if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)
|
|
return 's';
|
|
else
|
|
return 'b';
|
|
}
|
|
if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name,
|
|
".debug")) {
|
|
return 'n';
|
|
}
|
|
return '?';
|
|
}
|
|
|
|
static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
|
|
unsigned int shnum, unsigned int pcpundx)
|
|
{
|
|
const Elf_Shdr *sec;
|
|
|
|
if (src->st_shndx == SHN_UNDEF
|
|
|| src->st_shndx >= shnum
|
|
|| !src->st_name)
|
|
return false;
|
|
|
|
#ifdef CONFIG_KALLSYMS_ALL
|
|
if (src->st_shndx == pcpundx)
|
|
return true;
|
|
#endif
|
|
|
|
sec = sechdrs + src->st_shndx;
|
|
if (!(sec->sh_flags & SHF_ALLOC)
|
|
#ifndef CONFIG_KALLSYMS_ALL
|
|
|| !(sec->sh_flags & SHF_EXECINSTR)
|
|
#endif
|
|
|| (sec->sh_entsize & INIT_OFFSET_MASK))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* We only allocate and copy the strings needed by the parts of symtab
|
|
* we keep. This is simple, but has the effect of making multiple
|
|
* copies of duplicates. We could be more sophisticated, see
|
|
* linux-kernel thread starting with
|
|
* <73defb5e4bca04a6431392cc341112b1@localhost>.
|
|
*/
|
|
static void layout_symtab(struct module *mod, struct load_info *info)
|
|
{
|
|
Elf_Shdr *symsect = info->sechdrs + info->index.sym;
|
|
Elf_Shdr *strsect = info->sechdrs + info->index.str;
|
|
const Elf_Sym *src;
|
|
unsigned int i, nsrc, ndst, strtab_size = 0;
|
|
|
|
/* Put symbol section at end of init part of module. */
|
|
symsect->sh_flags |= SHF_ALLOC;
|
|
symsect->sh_entsize = get_offset(mod, &mod->init_layout.size, symsect,
|
|
info->index.sym) | INIT_OFFSET_MASK;
|
|
pr_debug("\t%s\n", info->secstrings + symsect->sh_name);
|
|
|
|
src = (void *)info->hdr + symsect->sh_offset;
|
|
nsrc = symsect->sh_size / sizeof(*src);
|
|
|
|
/* Compute total space required for the core symbols' strtab. */
|
|
for (ndst = i = 0; i < nsrc; i++) {
|
|
if (i == 0 || is_livepatch_module(mod) ||
|
|
is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
|
|
info->index.pcpu)) {
|
|
strtab_size += strlen(&info->strtab[src[i].st_name])+1;
|
|
ndst++;
|
|
}
|
|
}
|
|
|
|
/* Append room for core symbols at end of core part. */
|
|
info->symoffs = ALIGN(mod->core_layout.size, symsect->sh_addralign ?: 1);
|
|
info->stroffs = mod->core_layout.size = info->symoffs + ndst * sizeof(Elf_Sym);
|
|
mod->core_layout.size += strtab_size;
|
|
mod->core_layout.size = debug_align(mod->core_layout.size);
|
|
|
|
/* Put string table section at end of init part of module. */
|
|
strsect->sh_flags |= SHF_ALLOC;
|
|
strsect->sh_entsize = get_offset(mod, &mod->init_layout.size, strsect,
|
|
info->index.str) | INIT_OFFSET_MASK;
|
|
pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
|
|
|
|
/* We'll tack temporary mod_kallsyms on the end. */
|
|
mod->init_layout.size = ALIGN(mod->init_layout.size,
|
|
__alignof__(struct mod_kallsyms));
|
|
info->mod_kallsyms_init_off = mod->init_layout.size;
|
|
mod->init_layout.size += sizeof(struct mod_kallsyms);
|
|
mod->init_layout.size = debug_align(mod->init_layout.size);
|
|
}
|
|
|
|
/*
|
|
* We use the full symtab and strtab which layout_symtab arranged to
|
|
* be appended to the init section. Later we switch to the cut-down
|
|
* core-only ones.
|
|
*/
|
|
static void add_kallsyms(struct module *mod, const struct load_info *info)
|
|
{
|
|
unsigned int i, ndst;
|
|
const Elf_Sym *src;
|
|
Elf_Sym *dst;
|
|
char *s;
|
|
Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
|
|
|
|
/* Set up to point into init section. */
|
|
mod->kallsyms = mod->init_layout.base + info->mod_kallsyms_init_off;
|
|
|
|
mod->kallsyms->symtab = (void *)symsec->sh_addr;
|
|
mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
|
|
/* Make sure we get permanent strtab: don't use info->strtab. */
|
|
mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
|
|
|
|
/* Set types up while we still have access to sections. */
|
|
for (i = 0; i < mod->kallsyms->num_symtab; i++)
|
|
mod->kallsyms->symtab[i].st_info
|
|
= elf_type(&mod->kallsyms->symtab[i], info);
|
|
|
|
/* Now populate the cut down core kallsyms for after init. */
|
|
mod->core_kallsyms.symtab = dst = mod->core_layout.base + info->symoffs;
|
|
mod->core_kallsyms.strtab = s = mod->core_layout.base + info->stroffs;
|
|
src = mod->kallsyms->symtab;
|
|
for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {
|
|
if (i == 0 || is_livepatch_module(mod) ||
|
|
is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
|
|
info->index.pcpu)) {
|
|
dst[ndst] = src[i];
|
|
dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
|
|
s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],
|
|
KSYM_NAME_LEN) + 1;
|
|
}
|
|
}
|
|
mod->core_kallsyms.num_symtab = ndst;
|
|
}
|
|
#else
|
|
static inline void layout_symtab(struct module *mod, struct load_info *info)
|
|
{
|
|
}
|
|
|
|
static void add_kallsyms(struct module *mod, const struct load_info *info)
|
|
{
|
|
}
|
|
#endif /* CONFIG_KALLSYMS */
|
|
|
|
static void dynamic_debug_setup(struct module *mod, struct _ddebug *debug, unsigned int num)
|
|
{
|
|
if (!debug)
|
|
return;
|
|
#ifdef CONFIG_DYNAMIC_DEBUG
|
|
if (ddebug_add_module(debug, num, mod->name))
|
|
pr_err("dynamic debug error adding module: %s\n",
|
|
debug->modname);
|
|
#endif
|
|
}
|
|
|
|
static void dynamic_debug_remove(struct module *mod, struct _ddebug *debug)
|
|
{
|
|
if (debug)
|
|
ddebug_remove_module(mod->name);
|
|
}
|
|
|
|
void * __weak module_alloc(unsigned long size)
|
|
{
|
|
return vmalloc_exec(size);
|
|
}
|
|
|
|
#ifdef CONFIG_DEBUG_KMEMLEAK
|
|
static void kmemleak_load_module(const struct module *mod,
|
|
const struct load_info *info)
|
|
{
|
|
unsigned int i;
|
|
|
|
/* only scan the sections containing data */
|
|
kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL);
|
|
|
|
for (i = 1; i < info->hdr->e_shnum; i++) {
|
|
/* Scan all writable sections that's not executable */
|
|
if (!(info->sechdrs[i].sh_flags & SHF_ALLOC) ||
|
|
!(info->sechdrs[i].sh_flags & SHF_WRITE) ||
|
|
(info->sechdrs[i].sh_flags & SHF_EXECINSTR))
|
|
continue;
|
|
|
|
kmemleak_scan_area((void *)info->sechdrs[i].sh_addr,
|
|
info->sechdrs[i].sh_size, GFP_KERNEL);
|
|
}
|
|
}
|
|
#else
|
|
static inline void kmemleak_load_module(const struct module *mod,
|
|
const struct load_info *info)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_MODULE_SIG
|
|
static int module_sig_check(struct load_info *info, int flags)
|
|
{
|
|
int err = -ENOKEY;
|
|
const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
|
|
const void *mod = info->hdr;
|
|
|
|
/*
|
|
* Require flags == 0, as a module with version information
|
|
* removed is no longer the module that was signed
|
|
*/
|
|
if (flags == 0 &&
|
|
info->len > markerlen &&
|
|
memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
|
|
/* We truncate the module to discard the signature */
|
|
info->len -= markerlen;
|
|
err = mod_verify_sig(mod, &info->len);
|
|
}
|
|
|
|
if (!err) {
|
|
info->sig_ok = true;
|
|
return 0;
|
|
}
|
|
|
|
/* Not having a signature is only an error if we're strict. */
|
|
if (err == -ENOKEY && !sig_enforce)
|
|
err = 0;
|
|
|
|
return err;
|
|
}
|
|
#else /* !CONFIG_MODULE_SIG */
|
|
static int module_sig_check(struct load_info *info, int flags)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif /* !CONFIG_MODULE_SIG */
|
|
|
|
/* Sanity checks against invalid binaries, wrong arch, weird elf version. */
|
|
static int elf_header_check(struct load_info *info)
|
|
{
|
|
if (info->len < sizeof(*(info->hdr)))
|
|
return -ENOEXEC;
|
|
|
|
if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
|
|
|| info->hdr->e_type != ET_REL
|
|
|| !elf_check_arch(info->hdr)
|
|
|| info->hdr->e_shentsize != sizeof(Elf_Shdr))
|
|
return -ENOEXEC;
|
|
|
|
if (info->hdr->e_shoff >= info->len
|
|
|| (info->hdr->e_shnum * sizeof(Elf_Shdr) >
|
|
info->len - info->hdr->e_shoff))
|
|
return -ENOEXEC;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define COPY_CHUNK_SIZE (16*PAGE_SIZE)
|
|
|
|
static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned long len)
|
|
{
|
|
do {
|
|
unsigned long n = min(len, COPY_CHUNK_SIZE);
|
|
|
|
if (copy_from_user(dst, usrc, n) != 0)
|
|
return -EFAULT;
|
|
cond_resched();
|
|
dst += n;
|
|
usrc += n;
|
|
len -= n;
|
|
} while (len);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_LIVEPATCH
|
|
static int check_modinfo_livepatch(struct module *mod, struct load_info *info)
|
|
{
|
|
if (get_modinfo(info, "livepatch")) {
|
|
mod->klp = true;
|
|
add_taint_module(mod, TAINT_LIVEPATCH, LOCKDEP_STILL_OK);
|
|
pr_notice_once("%s: tainting kernel with TAINT_LIVEPATCH\n",
|
|
mod->name);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#else /* !CONFIG_LIVEPATCH */
|
|
static int check_modinfo_livepatch(struct module *mod, struct load_info *info)
|
|
{
|
|
if (get_modinfo(info, "livepatch")) {
|
|
pr_err("%s: module is marked as livepatch module, but livepatch support is disabled",
|
|
mod->name);
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_LIVEPATCH */
|
|
|
|
static void check_modinfo_retpoline(struct module *mod, struct load_info *info)
|
|
{
|
|
if (retpoline_module_ok(get_modinfo(info, "retpoline")))
|
|
return;
|
|
|
|
pr_warn("%s: loading module not compiled with retpoline compiler.\n",
|
|
mod->name);
|
|
}
|
|
|
|
/* Sets info->hdr and info->len. */
|
|
static int copy_module_from_user(const void __user *umod, unsigned long len,
|
|
struct load_info *info)
|
|
{
|
|
int err;
|
|
|
|
info->len = len;
|
|
if (info->len < sizeof(*(info->hdr)))
|
|
return -ENOEXEC;
|
|
|
|
err = security_kernel_read_file(NULL, READING_MODULE);
|
|
if (err)
|
|
return err;
|
|
|
|
/* Suck in entire file: we'll want most of it. */
|
|
info->hdr = __vmalloc(info->len,
|
|
GFP_KERNEL | __GFP_NOWARN, PAGE_KERNEL);
|
|
if (!info->hdr)
|
|
return -ENOMEM;
|
|
|
|
if (copy_chunked_from_user(info->hdr, umod, info->len) != 0) {
|
|
vfree(info->hdr);
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void free_copy(struct load_info *info)
|
|
{
|
|
vfree(info->hdr);
|
|
}
|
|
|
|
static int rewrite_section_headers(struct load_info *info, int flags)
|
|
{
|
|
unsigned int i;
|
|
|
|
/* This should always be true, but let's be sure. */
|
|
info->sechdrs[0].sh_addr = 0;
|
|
|
|
for (i = 1; i < info->hdr->e_shnum; i++) {
|
|
Elf_Shdr *shdr = &info->sechdrs[i];
|
|
if (shdr->sh_type != SHT_NOBITS
|
|
&& info->len < shdr->sh_offset + shdr->sh_size) {
|
|
pr_err("Module len %lu truncated\n", info->len);
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
/* Mark all sections sh_addr with their address in the
|
|
temporary image. */
|
|
shdr->sh_addr = (size_t)info->hdr + shdr->sh_offset;
|
|
|
|
#ifndef CONFIG_MODULE_UNLOAD
|
|
/* Don't load .exit sections */
|
|
if (strstarts(info->secstrings+shdr->sh_name, ".exit"))
|
|
shdr->sh_flags &= ~(unsigned long)SHF_ALLOC;
|
|
#endif
|
|
}
|
|
|
|
/* Track but don't keep modinfo and version sections. */
|
|
if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
|
|
info->index.vers = 0; /* Pretend no __versions section! */
|
|
else
|
|
info->index.vers = find_sec(info, "__versions");
|
|
info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
|
|
|
|
info->index.info = find_sec(info, ".modinfo");
|
|
if (!info->index.info)
|
|
info->name = "(missing .modinfo section)";
|
|
else
|
|
info->name = get_modinfo(info, "name");
|
|
info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Set up our basic convenience variables (pointers to section headers,
|
|
* search for module section index etc), and do some basic section
|
|
* verification.
|
|
*
|
|
* Return the temporary module pointer (we'll replace it with the final
|
|
* one when we move the module sections around).
|
|
*/
|
|
static struct module *setup_load_info(struct load_info *info, int flags)
|
|
{
|
|
unsigned int i;
|
|
int err;
|
|
struct module *mod;
|
|
|
|
/* Set up the convenience variables */
|
|
info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
|
|
info->secstrings = (void *)info->hdr
|
|
+ info->sechdrs[info->hdr->e_shstrndx].sh_offset;
|
|
|
|
err = rewrite_section_headers(info, flags);
|
|
if (err)
|
|
return ERR_PTR(err);
|
|
|
|
/* Find internal symbols and strings. */
|
|
for (i = 1; i < info->hdr->e_shnum; i++) {
|
|
if (info->sechdrs[i].sh_type == SHT_SYMTAB) {
|
|
info->index.sym = i;
|
|
info->index.str = info->sechdrs[i].sh_link;
|
|
info->strtab = (char *)info->hdr
|
|
+ info->sechdrs[info->index.str].sh_offset;
|
|
break;
|
|
}
|
|
}
|
|
|
|
info->index.mod = find_sec(info, ".gnu.linkonce.this_module");
|
|
if (!info->index.mod) {
|
|
pr_warn("%s: No module found in object\n",
|
|
info->name ?: "(missing .modinfo name field)");
|
|
return ERR_PTR(-ENOEXEC);
|
|
}
|
|
/* This is temporary: point mod into copy of data. */
|
|
mod = (void *)info->sechdrs[info->index.mod].sh_addr;
|
|
|
|
/*
|
|
* If we didn't load the .modinfo 'name' field, fall back to
|
|
* on-disk struct mod 'name' field.
|
|
*/
|
|
if (!info->name)
|
|
info->name = mod->name;
|
|
|
|
if (info->index.sym == 0) {
|
|
pr_warn("%s: module has no symbols (stripped?)\n", info->name);
|
|
return ERR_PTR(-ENOEXEC);
|
|
}
|
|
|
|
info->index.pcpu = find_pcpusec(info);
|
|
|
|
/* Check module struct version now, before we try to use module. */
|
|
if (!check_modstruct_version(info, mod))
|
|
return ERR_PTR(-ENOEXEC);
|
|
|
|
return mod;
|
|
}
|
|
|
|
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
|
|
{
|
|
const char *modmagic = get_modinfo(info, "vermagic");
|
|
int err;
|
|
|
|
if (flags & MODULE_INIT_IGNORE_VERMAGIC)
|
|
modmagic = NULL;
|
|
|
|
/* This is allowed: modprobe --force will invalidate it. */
|
|
if (!modmagic) {
|
|
err = try_to_force_load(mod, "bad vermagic");
|
|
if (err)
|
|
return err;
|
|
} else if (!same_magic(modmagic, vermagic, info->index.vers)) {
|
|
pr_err("%s: version magic '%s' should be '%s'\n",
|
|
info->name, modmagic, vermagic);
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
if (!get_modinfo(info, "intree")) {
|
|
if (!test_taint(TAINT_OOT_MODULE))
|
|
pr_warn("%s: loading out-of-tree module taints kernel.\n",
|
|
mod->name);
|
|
add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);
|
|
}
|
|
|
|
check_modinfo_retpoline(mod, info);
|
|
|
|
if (get_modinfo(info, "staging")) {
|
|
add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK);
|
|
pr_warn("%s: module is from the staging directory, the quality "
|
|
"is unknown, you have been warned.\n", mod->name);
|
|
}
|
|
|
|
err = check_modinfo_livepatch(mod, info);
|
|
if (err)
|
|
return err;
|
|
|
|
/* Set up license info based on the info section */
|
|
set_license(mod, get_modinfo(info, "license"));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int find_module_sections(struct module *mod, struct load_info *info)
|
|
{
|
|
mod->kp = section_objs(info, "__param",
|
|
sizeof(*mod->kp), &mod->num_kp);
|
|
mod->syms = section_objs(info, "__ksymtab",
|
|
sizeof(*mod->syms), &mod->num_syms);
|
|
mod->crcs = section_addr(info, "__kcrctab");
|
|
mod->gpl_syms = section_objs(info, "__ksymtab_gpl",
|
|
sizeof(*mod->gpl_syms),
|
|
&mod->num_gpl_syms);
|
|
mod->gpl_crcs = section_addr(info, "__kcrctab_gpl");
|
|
mod->gpl_future_syms = section_objs(info,
|
|
"__ksymtab_gpl_future",
|
|
sizeof(*mod->gpl_future_syms),
|
|
&mod->num_gpl_future_syms);
|
|
mod->gpl_future_crcs = section_addr(info, "__kcrctab_gpl_future");
|
|
|
|
#ifdef CONFIG_UNUSED_SYMBOLS
|
|
mod->unused_syms = section_objs(info, "__ksymtab_unused",
|
|
sizeof(*mod->unused_syms),
|
|
&mod->num_unused_syms);
|
|
mod->unused_crcs = section_addr(info, "__kcrctab_unused");
|
|
mod->unused_gpl_syms = section_objs(info, "__ksymtab_unused_gpl",
|
|
sizeof(*mod->unused_gpl_syms),
|
|
&mod->num_unused_gpl_syms);
|
|
mod->unused_gpl_crcs = section_addr(info, "__kcrctab_unused_gpl");
|
|
#endif
|
|
#ifdef CONFIG_CONSTRUCTORS
|
|
mod->ctors = section_objs(info, ".ctors",
|
|
sizeof(*mod->ctors), &mod->num_ctors);
|
|
if (!mod->ctors)
|
|
mod->ctors = section_objs(info, ".init_array",
|
|
sizeof(*mod->ctors), &mod->num_ctors);
|
|
else if (find_sec(info, ".init_array")) {
|
|
/*
|
|
* This shouldn't happen with same compiler and binutils
|
|
* building all parts of the module.
|
|
*/
|
|
pr_warn("%s: has both .ctors and .init_array.\n",
|
|
mod->name);
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_TRACEPOINTS
|
|
mod->tracepoints_ptrs = section_objs(info, "__tracepoints_ptrs",
|
|
sizeof(*mod->tracepoints_ptrs),
|
|
&mod->num_tracepoints);
|
|
#endif
|
|
#ifdef HAVE_JUMP_LABEL
|
|
mod->jump_entries = section_objs(info, "__jump_table",
|
|
sizeof(*mod->jump_entries),
|
|
&mod->num_jump_entries);
|
|
#endif
|
|
#ifdef CONFIG_EVENT_TRACING
|
|
mod->trace_events = section_objs(info, "_ftrace_events",
|
|
sizeof(*mod->trace_events),
|
|
&mod->num_trace_events);
|
|
mod->trace_evals = section_objs(info, "_ftrace_eval_map",
|
|
sizeof(*mod->trace_evals),
|
|
&mod->num_trace_evals);
|
|
#endif
|
|
#ifdef CONFIG_TRACING
|
|
mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt",
|
|
sizeof(*mod->trace_bprintk_fmt_start),
|
|
&mod->num_trace_bprintk_fmt);
|
|
#endif
|
|
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
|
/* sechdrs[0].sh_size is always zero */
|
|
mod->ftrace_callsites = section_objs(info, "__mcount_loc",
|
|
sizeof(*mod->ftrace_callsites),
|
|
&mod->num_ftrace_callsites);
|
|
#endif
|
|
|
|
mod->extable = section_objs(info, "__ex_table",
|
|
sizeof(*mod->extable), &mod->num_exentries);
|
|
|
|
if (section_addr(info, "__obsparm"))
|
|
pr_warn("%s: Ignoring obsolete parameters\n", mod->name);
|
|
|
|
info->debug = section_objs(info, "__verbose",
|
|
sizeof(*info->debug), &info->num_debug);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int move_module(struct module *mod, struct load_info *info)
|
|
{
|
|
int i;
|
|
void *ptr;
|
|
|
|
/* Do the allocs. */
|
|
ptr = module_alloc(mod->core_layout.size);
|
|
/*
|
|
* The pointer to this block is stored in the module structure
|
|
* which is inside the block. Just mark it as not being a
|
|
* leak.
|
|
*/
|
|
kmemleak_not_leak(ptr);
|
|
if (!ptr)
|
|
return -ENOMEM;
|
|
|
|
memset(ptr, 0, mod->core_layout.size);
|
|
mod->core_layout.base = ptr;
|
|
|
|
if (mod->init_layout.size) {
|
|
ptr = module_alloc(mod->init_layout.size);
|
|
/*
|
|
* The pointer to this block is stored in the module structure
|
|
* which is inside the block. This block doesn't need to be
|
|
* scanned as it contains data and code that will be freed
|
|
* after the module is initialized.
|
|
*/
|
|
kmemleak_ignore(ptr);
|
|
if (!ptr) {
|
|
module_memfree(mod->core_layout.base);
|
|
return -ENOMEM;
|
|
}
|
|
memset(ptr, 0, mod->init_layout.size);
|
|
mod->init_layout.base = ptr;
|
|
} else
|
|
mod->init_layout.base = NULL;
|
|
|
|
/* Transfer each section which specifies SHF_ALLOC */
|
|
pr_debug("final section addresses:\n");
|
|
for (i = 0; i < info->hdr->e_shnum; i++) {
|
|
void *dest;
|
|
Elf_Shdr *shdr = &info->sechdrs[i];
|
|
|
|
if (!(shdr->sh_flags & SHF_ALLOC))
|
|
continue;
|
|
|
|
if (shdr->sh_entsize & INIT_OFFSET_MASK)
|
|
dest = mod->init_layout.base
|
|
+ (shdr->sh_entsize & ~INIT_OFFSET_MASK);
|
|
else
|
|
dest = mod->core_layout.base + shdr->sh_entsize;
|
|
|
|
if (shdr->sh_type != SHT_NOBITS)
|
|
memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);
|
|
/* Update sh_addr to point to copy in image. */
|
|
shdr->sh_addr = (unsigned long)dest;
|
|
pr_debug("\t0x%lx %s\n",
|
|
(long)shdr->sh_addr, info->secstrings + shdr->sh_name);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int check_module_license_and_versions(struct module *mod)
|
|
{
|
|
int prev_taint = test_taint(TAINT_PROPRIETARY_MODULE);
|
|
|
|
/*
|
|
* ndiswrapper is under GPL by itself, but loads proprietary modules.
|
|
* Don't use add_taint_module(), as it would prevent ndiswrapper from
|
|
* using GPL-only symbols it needs.
|
|
*/
|
|
if (strcmp(mod->name, "ndiswrapper") == 0)
|
|
add_taint(TAINT_PROPRIETARY_MODULE, LOCKDEP_NOW_UNRELIABLE);
|
|
|
|
/* driverloader was caught wrongly pretending to be under GPL */
|
|
if (strcmp(mod->name, "driverloader") == 0)
|
|
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
|
|
LOCKDEP_NOW_UNRELIABLE);
|
|
|
|
/* lve claims to be GPL but upstream won't provide source */
|
|
if (strcmp(mod->name, "lve") == 0)
|
|
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
|
|
LOCKDEP_NOW_UNRELIABLE);
|
|
|
|
if (!prev_taint && test_taint(TAINT_PROPRIETARY_MODULE))
|
|
pr_warn("%s: module license taints kernel.\n", mod->name);
|
|
|
|
#ifdef CONFIG_MODVERSIONS
|
|
if ((mod->num_syms && !mod->crcs)
|
|
|| (mod->num_gpl_syms && !mod->gpl_crcs)
|
|
|| (mod->num_gpl_future_syms && !mod->gpl_future_crcs)
|
|
#ifdef CONFIG_UNUSED_SYMBOLS
|
|
|| (mod->num_unused_syms && !mod->unused_crcs)
|
|
|| (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs)
|
|
#endif
|
|
) {
|
|
return try_to_force_load(mod,
|
|
"no versions for exported symbols");
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static void flush_module_icache(const struct module *mod)
|
|
{
|
|
mm_segment_t old_fs;
|
|
|
|
/* flush the icache in correct context */
|
|
old_fs = get_fs();
|
|
set_fs(KERNEL_DS);
|
|
|
|
/*
|
|
* Flush the instruction cache, since we've played with text.
|
|
* Do it before processing of module parameters, so the module
|
|
* can provide parameter accessor functions of its own.
|
|
*/
|
|
if (mod->init_layout.base)
|
|
flush_icache_range((unsigned long)mod->init_layout.base,
|
|
(unsigned long)mod->init_layout.base
|
|
+ mod->init_layout.size);
|
|
flush_icache_range((unsigned long)mod->core_layout.base,
|
|
(unsigned long)mod->core_layout.base + mod->core_layout.size);
|
|
|
|
set_fs(old_fs);
|
|
}
|
|
|
|
int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
|
|
Elf_Shdr *sechdrs,
|
|
char *secstrings,
|
|
struct module *mod)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* module_blacklist is a comma-separated list of module names */
|
|
static char *module_blacklist;
|
|
static bool blacklisted(const char *module_name)
|
|
{
|
|
const char *p;
|
|
size_t len;
|
|
|
|
if (!module_blacklist)
|
|
return false;
|
|
|
|
for (p = module_blacklist; *p; p += len) {
|
|
len = strcspn(p, ",");
|
|
if (strlen(module_name) == len && !memcmp(module_name, p, len))
|
|
return true;
|
|
if (p[len] == ',')
|
|
len++;
|
|
}
|
|
return false;
|
|
}
|
|
core_param(module_blacklist, module_blacklist, charp, 0400);
|
|
|
|
static struct module *layout_and_allocate(struct load_info *info, int flags)
|
|
{
|
|
/* Module within temporary copy. */
|
|
struct module *mod;
|
|
unsigned int ndx;
|
|
int err;
|
|
|
|
mod = setup_load_info(info, flags);
|
|
if (IS_ERR(mod))
|
|
return mod;
|
|
|
|
if (blacklisted(info->name))
|
|
return ERR_PTR(-EPERM);
|
|
|
|
err = check_modinfo(mod, info, flags);
|
|
if (err)
|
|
return ERR_PTR(err);
|
|
|
|
/* Allow arches to frob section contents and sizes. */
|
|
err = module_frob_arch_sections(info->hdr, info->sechdrs,
|
|
info->secstrings, mod);
|
|
if (err < 0)
|
|
return ERR_PTR(err);
|
|
|
|
/* We will do a special allocation for per-cpu sections later. */
|
|
info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
|
|
|
|
/*
|
|
* Mark ro_after_init section with SHF_RO_AFTER_INIT so that
|
|
* layout_sections() can put it in the right place.
|
|
* Note: ro_after_init sections also have SHF_{WRITE,ALLOC} set.
|
|
*/
|
|
ndx = find_sec(info, ".data..ro_after_init");
|
|
if (ndx)
|
|
info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
|
|
|
|
/* Determine total sizes, and put offsets in sh_entsize. For now
|
|
this is done generically; there doesn't appear to be any
|
|
special cases for the architectures. */
|
|
layout_sections(mod, info);
|
|
layout_symtab(mod, info);
|
|
|
|
/* Allocate and move to the final place */
|
|
err = move_module(mod, info);
|
|
if (err)
|
|
return ERR_PTR(err);
|
|
|
|
/* Module has been copied to its final place now: return it. */
|
|
mod = (void *)info->sechdrs[info->index.mod].sh_addr;
|
|
kmemleak_load_module(mod, info);
|
|
return mod;
|
|
}
|
|
|
|
/* mod is no longer valid after this! */
|
|
static void module_deallocate(struct module *mod, struct load_info *info)
|
|
{
|
|
percpu_modfree(mod);
|
|
module_arch_freeing_init(mod);
|
|
module_memfree(mod->init_layout.base);
|
|
module_memfree(mod->core_layout.base);
|
|
}
|
|
|
|
int __weak module_finalize(const Elf_Ehdr *hdr,
|
|
const Elf_Shdr *sechdrs,
|
|
struct module *me)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void cfi_init(struct module *mod);
|
|
|
|
static int post_relocation(struct module *mod, const struct load_info *info)
|
|
{
|
|
/* Sort exception table now relocations are done. */
|
|
sort_extable(mod->extable, mod->extable + mod->num_exentries);
|
|
|
|
/* Copy relocated percpu area over. */
|
|
percpu_modcopy(mod, (void *)info->sechdrs[info->index.pcpu].sh_addr,
|
|
info->sechdrs[info->index.pcpu].sh_size);
|
|
|
|
/* Setup kallsyms-specific fields. */
|
|
add_kallsyms(mod, info);
|
|
|
|
/* Setup CFI for the module. */
|
|
cfi_init(mod);
|
|
|
|
/* Arch-specific module finalizing. */
|
|
return module_finalize(info->hdr, info->sechdrs, mod);
|
|
}
|
|
|
|
/* Is this module of this name done loading? No locks held. */
|
|
static bool finished_loading(const char *name)
|
|
{
|
|
struct module *mod;
|
|
bool ret;
|
|
|
|
/*
|
|
* The module_mutex should not be a heavily contended lock;
|
|
* if we get the occasional sleep here, we'll go an extra iteration
|
|
* in the wait_event_interruptible(), which is harmless.
|
|
*/
|
|
sched_annotate_sleep();
|
|
mutex_lock(&module_mutex);
|
|
mod = find_module_all(name, strlen(name), true);
|
|
ret = !mod || mod->state == MODULE_STATE_LIVE;
|
|
mutex_unlock(&module_mutex);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Call module constructors. */
|
|
static void do_mod_ctors(struct module *mod)
|
|
{
|
|
#ifdef CONFIG_CONSTRUCTORS
|
|
unsigned long i;
|
|
|
|
for (i = 0; i < mod->num_ctors; i++)
|
|
mod->ctors[i]();
|
|
#endif
|
|
}
|
|
|
|
/* For freeing module_init on success, in case kallsyms traversing */
|
|
struct mod_initfree {
|
|
struct rcu_head rcu;
|
|
void *module_init;
|
|
};
|
|
|
|
static void do_free_init(struct rcu_head *head)
|
|
{
|
|
struct mod_initfree *m = container_of(head, struct mod_initfree, rcu);
|
|
module_memfree(m->module_init);
|
|
kfree(m);
|
|
}
|
|
|
|
/*
|
|
* This is where the real work happens.
|
|
*
|
|
* Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb
|
|
* helper command 'lx-symbols'.
|
|
*/
|
|
static noinline int do_init_module(struct module *mod)
|
|
{
|
|
int ret = 0;
|
|
struct mod_initfree *freeinit;
|
|
|
|
freeinit = kmalloc(sizeof(*freeinit), GFP_KERNEL);
|
|
if (!freeinit) {
|
|
ret = -ENOMEM;
|
|
goto fail;
|
|
}
|
|
freeinit->module_init = mod->init_layout.base;
|
|
|
|
/*
|
|
* We want to find out whether @mod uses async during init. Clear
|
|
* PF_USED_ASYNC. async_schedule*() will set it.
|
|
*/
|
|
current->flags &= ~PF_USED_ASYNC;
|
|
|
|
do_mod_ctors(mod);
|
|
/* Start the module */
|
|
if (mod->init != NULL)
|
|
ret = do_one_initcall(mod->init);
|
|
if (ret < 0) {
|
|
goto fail_free_freeinit;
|
|
}
|
|
if (ret > 0) {
|
|
pr_warn("%s: '%s'->init suspiciously returned %d, it should "
|
|
"follow 0/-E convention\n"
|
|
"%s: loading module anyway...\n",
|
|
__func__, mod->name, ret, __func__);
|
|
dump_stack();
|
|
}
|
|
|
|
/* Now it's a first class citizen! */
|
|
mod->state = MODULE_STATE_LIVE;
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
MODULE_STATE_LIVE, mod);
|
|
|
|
/*
|
|
* We need to finish all async code before the module init sequence
|
|
* is done. This has potential to deadlock. For example, a newly
|
|
* detected block device can trigger request_module() of the
|
|
* default iosched from async probing task. Once userland helper
|
|
* reaches here, async_synchronize_full() will wait on the async
|
|
* task waiting on request_module() and deadlock.
|
|
*
|
|
* This deadlock is avoided by perfomring async_synchronize_full()
|
|
* iff module init queued any async jobs. This isn't a full
|
|
* solution as it will deadlock the same if module loading from
|
|
* async jobs nests more than once; however, due to the various
|
|
* constraints, this hack seems to be the best option for now.
|
|
* Please refer to the following thread for details.
|
|
*
|
|
* http://thread.gmane.org/gmane.linux.kernel/1420814
|
|
*/
|
|
if (!mod->async_probe_requested && (current->flags & PF_USED_ASYNC))
|
|
async_synchronize_full();
|
|
|
|
mutex_lock(&module_mutex);
|
|
/* Drop initial reference. */
|
|
module_put(mod);
|
|
trim_init_extable(mod);
|
|
#ifdef CONFIG_KALLSYMS
|
|
/* Switch to core kallsyms now init is done: kallsyms may be walking! */
|
|
rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
|
|
#endif
|
|
module_enable_ro(mod, true);
|
|
mod_tree_remove_init(mod);
|
|
disable_ro_nx(&mod->init_layout);
|
|
module_arch_freeing_init(mod);
|
|
#ifdef CONFIG_DEBUG_MODULE_LOAD_INFO
|
|
pr_info("Loaded %s: module init layout addresses range: 0x%lx-0x%lx\n",
|
|
mod->name, (long)mod->init_layout.base,
|
|
(long)(mod->init_layout.base + mod->init_layout.size - 1));
|
|
pr_info("%s: core layout addresses range: 0x%lx-0x%lx\n", mod->name,
|
|
(long)mod->core_layout.base,
|
|
(long)(mod->core_layout.base + mod->core_layout.size - 1));
|
|
#endif
|
|
mod->init_layout.base = NULL;
|
|
mod->init_layout.size = 0;
|
|
mod->init_layout.ro_size = 0;
|
|
mod->init_layout.ro_after_init_size = 0;
|
|
mod->init_layout.text_size = 0;
|
|
/*
|
|
* We want to free module_init, but be aware that kallsyms may be
|
|
* walking this with preempt disabled. In all the failure paths, we
|
|
* call synchronize_sched(), but we don't want to slow down the success
|
|
* path, so use actual RCU here.
|
|
* Note that module_alloc() on most architectures creates W+X page
|
|
* mappings which won't be cleaned up until do_free_init() runs. Any
|
|
* code such as mark_rodata_ro() which depends on those mappings to
|
|
* be cleaned up needs to sync with the queued work - ie
|
|
* rcu_barrier_sched()
|
|
*/
|
|
call_rcu_sched(&freeinit->rcu, do_free_init);
|
|
mutex_unlock(&module_mutex);
|
|
wake_up_all(&module_wq);
|
|
|
|
return 0;
|
|
|
|
fail_free_freeinit:
|
|
kfree(freeinit);
|
|
fail:
|
|
/* Try to protect us from buggy refcounters. */
|
|
mod->state = MODULE_STATE_GOING;
|
|
synchronize_sched();
|
|
module_put(mod);
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
MODULE_STATE_GOING, mod);
|
|
klp_module_going(mod);
|
|
ftrace_release_mod(mod);
|
|
free_module(mod);
|
|
wake_up_all(&module_wq);
|
|
return ret;
|
|
}
|
|
|
|
static int may_init_module(void)
|
|
{
|
|
if (!capable(CAP_SYS_MODULE) || modules_disabled)
|
|
return -EPERM;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* We try to place it in the list now to make sure it's unique before
|
|
* we dedicate too many resources. In particular, temporary percpu
|
|
* memory exhaustion.
|
|
*/
|
|
static int add_unformed_module(struct module *mod)
|
|
{
|
|
int err;
|
|
struct module *old;
|
|
|
|
mod->state = MODULE_STATE_UNFORMED;
|
|
|
|
again:
|
|
mutex_lock(&module_mutex);
|
|
old = find_module_all(mod->name, strlen(mod->name), true);
|
|
if (old != NULL) {
|
|
if (old->state != MODULE_STATE_LIVE) {
|
|
/* Wait in case it fails to load. */
|
|
mutex_unlock(&module_mutex);
|
|
err = wait_event_interruptible(module_wq,
|
|
finished_loading(mod->name));
|
|
if (err)
|
|
goto out_unlocked;
|
|
goto again;
|
|
}
|
|
err = -EEXIST;
|
|
goto out;
|
|
}
|
|
mod_update_bounds(mod);
|
|
list_add_rcu(&mod->list, &modules);
|
|
mod_tree_insert(mod);
|
|
err = 0;
|
|
|
|
out:
|
|
mutex_unlock(&module_mutex);
|
|
out_unlocked:
|
|
return err;
|
|
}
|
|
|
|
static int complete_formation(struct module *mod, struct load_info *info)
|
|
{
|
|
int err;
|
|
|
|
mutex_lock(&module_mutex);
|
|
|
|
/* Find duplicate symbols (must be called under lock). */
|
|
err = verify_export_symbols(mod);
|
|
if (err < 0)
|
|
goto out;
|
|
|
|
/* This relies on module_mutex for list integrity. */
|
|
module_bug_finalize(info->hdr, info->sechdrs, mod);
|
|
|
|
module_enable_ro(mod, false);
|
|
module_enable_nx(mod);
|
|
|
|
/* Mark state as coming so strong_try_module_get() ignores us,
|
|
* but kallsyms etc. can see us. */
|
|
mod->state = MODULE_STATE_COMING;
|
|
mutex_unlock(&module_mutex);
|
|
|
|
return 0;
|
|
|
|
out:
|
|
mutex_unlock(&module_mutex);
|
|
return err;
|
|
}
|
|
|
|
static int prepare_coming_module(struct module *mod)
|
|
{
|
|
int err;
|
|
|
|
ftrace_module_enable(mod);
|
|
err = klp_module_coming(mod);
|
|
if (err)
|
|
return err;
|
|
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
MODULE_STATE_COMING, mod);
|
|
return 0;
|
|
}
|
|
|
|
static int unknown_module_param_cb(char *param, char *val, const char *modname,
|
|
void *arg)
|
|
{
|
|
struct module *mod = arg;
|
|
int ret;
|
|
|
|
if (strcmp(param, "async_probe") == 0) {
|
|
mod->async_probe_requested = true;
|
|
return 0;
|
|
}
|
|
|
|
/* Check for magic 'dyndbg' arg */
|
|
ret = ddebug_dyndbg_module_param_cb(param, val, modname);
|
|
if (ret != 0)
|
|
pr_warn("%s: unknown parameter '%s' ignored\n", modname, param);
|
|
return 0;
|
|
}
|
|
|
|
/* Allocate and load the module: note that size of section 0 is always
|
|
zero, and we rely on this for optional sections. */
|
|
static int load_module(struct load_info *info, const char __user *uargs,
|
|
int flags)
|
|
{
|
|
struct module *mod;
|
|
long err;
|
|
char *after_dashes;
|
|
|
|
err = module_sig_check(info, flags);
|
|
if (err)
|
|
goto free_copy;
|
|
|
|
err = elf_header_check(info);
|
|
if (err)
|
|
goto free_copy;
|
|
|
|
/* Figure out module layout, and allocate all the memory. */
|
|
mod = layout_and_allocate(info, flags);
|
|
if (IS_ERR(mod)) {
|
|
err = PTR_ERR(mod);
|
|
goto free_copy;
|
|
}
|
|
|
|
audit_log_kern_module(mod->name);
|
|
|
|
/* Reserve our place in the list. */
|
|
err = add_unformed_module(mod);
|
|
if (err)
|
|
goto free_module;
|
|
|
|
#ifdef CONFIG_MODULE_SIG
|
|
mod->sig_ok = info->sig_ok;
|
|
if (!mod->sig_ok) {
|
|
pr_notice_once("%s: module verification failed: signature "
|
|
"and/or required key missing - tainting "
|
|
"kernel\n", mod->name);
|
|
add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK);
|
|
}
|
|
#endif
|
|
|
|
/* To avoid stressing percpu allocator, do this once we're unique. */
|
|
err = percpu_modalloc(mod, info);
|
|
if (err)
|
|
goto unlink_mod;
|
|
|
|
/* Now module is in final location, initialize linked lists, etc. */
|
|
err = module_unload_init(mod);
|
|
if (err)
|
|
goto unlink_mod;
|
|
|
|
init_param_lock(mod);
|
|
|
|
/* Now we've got everything in the final locations, we can
|
|
* find optional sections. */
|
|
err = find_module_sections(mod, info);
|
|
if (err)
|
|
goto free_unload;
|
|
|
|
err = check_module_license_and_versions(mod);
|
|
if (err)
|
|
goto free_unload;
|
|
|
|
/* Set up MODINFO_ATTR fields */
|
|
setup_modinfo(mod, info);
|
|
|
|
/* Fix up syms, so that st_value is a pointer to location. */
|
|
err = simplify_symbols(mod, info);
|
|
if (err < 0)
|
|
goto free_modinfo;
|
|
|
|
err = apply_relocations(mod, info);
|
|
if (err < 0)
|
|
goto free_modinfo;
|
|
|
|
err = post_relocation(mod, info);
|
|
if (err < 0)
|
|
goto free_modinfo;
|
|
|
|
flush_module_icache(mod);
|
|
|
|
/* Now copy in args */
|
|
mod->args = strndup_user(uargs, ~0UL >> 1);
|
|
if (IS_ERR(mod->args)) {
|
|
err = PTR_ERR(mod->args);
|
|
goto free_arch_cleanup;
|
|
}
|
|
|
|
dynamic_debug_setup(mod, info->debug, info->num_debug);
|
|
|
|
/* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
|
|
ftrace_module_init(mod);
|
|
|
|
/* Finally it's fully formed, ready to start executing. */
|
|
err = complete_formation(mod, info);
|
|
if (err)
|
|
goto ddebug_cleanup;
|
|
|
|
err = prepare_coming_module(mod);
|
|
if (err)
|
|
goto bug_cleanup;
|
|
|
|
/* Module is ready to execute: parsing args may do that. */
|
|
after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
|
|
-32768, 32767, mod,
|
|
unknown_module_param_cb);
|
|
if (IS_ERR(after_dashes)) {
|
|
err = PTR_ERR(after_dashes);
|
|
goto coming_cleanup;
|
|
} else if (after_dashes) {
|
|
pr_warn("%s: parameters '%s' after `--' ignored\n",
|
|
mod->name, after_dashes);
|
|
}
|
|
|
|
/* Link in to sysfs. */
|
|
err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
|
|
if (err < 0)
|
|
goto coming_cleanup;
|
|
|
|
if (is_livepatch_module(mod)) {
|
|
err = copy_module_elf(mod, info);
|
|
if (err < 0)
|
|
goto sysfs_cleanup;
|
|
}
|
|
|
|
/* Get rid of temporary copy. */
|
|
free_copy(info);
|
|
|
|
/* Done! */
|
|
trace_module_load(mod);
|
|
|
|
return do_init_module(mod);
|
|
|
|
sysfs_cleanup:
|
|
mod_sysfs_teardown(mod);
|
|
coming_cleanup:
|
|
mod->state = MODULE_STATE_GOING;
|
|
destroy_params(mod->kp, mod->num_kp);
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
MODULE_STATE_GOING, mod);
|
|
klp_module_going(mod);
|
|
bug_cleanup:
|
|
/* module_bug_cleanup needs module_mutex protection */
|
|
mutex_lock(&module_mutex);
|
|
module_bug_cleanup(mod);
|
|
mutex_unlock(&module_mutex);
|
|
|
|
/* we can't deallocate the module until we clear memory protection */
|
|
module_disable_ro(mod);
|
|
module_disable_nx(mod);
|
|
|
|
ddebug_cleanup:
|
|
dynamic_debug_remove(mod, info->debug);
|
|
synchronize_sched();
|
|
kfree(mod->args);
|
|
free_arch_cleanup:
|
|
module_arch_cleanup(mod);
|
|
free_modinfo:
|
|
free_modinfo(mod);
|
|
free_unload:
|
|
module_unload_free(mod);
|
|
unlink_mod:
|
|
mutex_lock(&module_mutex);
|
|
/* Unlink carefully: kallsyms could be walking list. */
|
|
list_del_rcu(&mod->list);
|
|
mod_tree_remove(mod);
|
|
wake_up_all(&module_wq);
|
|
/* Wait for RCU-sched synchronizing before releasing mod->list. */
|
|
synchronize_sched();
|
|
mutex_unlock(&module_mutex);
|
|
free_module:
|
|
/*
|
|
* Ftrace needs to clean up what it initialized.
|
|
* This does nothing if ftrace_module_init() wasn't called,
|
|
* but it must be called outside of module_mutex.
|
|
*/
|
|
ftrace_release_mod(mod);
|
|
/* Free lock-classes; relies on the preceding sync_rcu() */
|
|
lockdep_free_key_range(mod->core_layout.base, mod->core_layout.size);
|
|
|
|
module_deallocate(mod, info);
|
|
free_copy:
|
|
free_copy(info);
|
|
return err;
|
|
}
|
|
|
|
SYSCALL_DEFINE3(init_module, void __user *, umod,
|
|
unsigned long, len, const char __user *, uargs)
|
|
{
|
|
int err;
|
|
struct load_info info = { };
|
|
|
|
err = may_init_module();
|
|
if (err)
|
|
return err;
|
|
|
|
pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
|
|
umod, len, uargs);
|
|
|
|
err = copy_module_from_user(umod, len, &info);
|
|
if (err)
|
|
return err;
|
|
|
|
return load_module(&info, uargs, 0);
|
|
}
|
|
|
|
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
|
|
{
|
|
struct load_info info = { };
|
|
loff_t size;
|
|
void *hdr;
|
|
int err;
|
|
|
|
err = may_init_module();
|
|
if (err)
|
|
return err;
|
|
|
|
pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags);
|
|
|
|
if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS
|
|
|MODULE_INIT_IGNORE_VERMAGIC))
|
|
return -EINVAL;
|
|
|
|
err = kernel_read_file_from_fd(fd, &hdr, &size, INT_MAX,
|
|
READING_MODULE);
|
|
if (err)
|
|
return err;
|
|
info.hdr = hdr;
|
|
info.len = size;
|
|
|
|
return load_module(&info, uargs, flags);
|
|
}
|
|
|
|
static inline int within(unsigned long addr, void *start, unsigned long size)
|
|
{
|
|
return ((void *)addr >= start && (void *)addr < start + size);
|
|
}
|
|
|
|
#ifdef CONFIG_KALLSYMS
|
|
/*
|
|
* This ignores the intensely annoying "mapping symbols" found
|
|
* in ARM ELF files: $a, $t and $d.
|
|
*/
|
|
static inline int is_arm_mapping_symbol(const char *str)
|
|
{
|
|
if (str[0] == '.' && str[1] == 'L')
|
|
return true;
|
|
return str[0] == '$' && strchr("axtd", str[1])
|
|
&& (str[2] == '\0' || str[2] == '.');
|
|
}
|
|
|
|
static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum)
|
|
{
|
|
return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
|
|
}
|
|
|
|
static const char *get_ksymbol(struct module *mod,
|
|
unsigned long addr,
|
|
unsigned long *size,
|
|
unsigned long *offset)
|
|
{
|
|
unsigned int i, best = 0;
|
|
unsigned long nextval;
|
|
struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
|
|
|
|
/* At worse, next value is at end of module */
|
|
if (within_module_init(addr, mod))
|
|
nextval = (unsigned long)mod->init_layout.base+mod->init_layout.text_size;
|
|
else
|
|
nextval = (unsigned long)mod->core_layout.base+mod->core_layout.text_size;
|
|
|
|
/* Scan for closest preceding symbol, and next symbol. (ELF
|
|
starts real symbols at 1). */
|
|
for (i = 1; i < kallsyms->num_symtab; i++) {
|
|
if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
|
|
continue;
|
|
|
|
/* We ignore unnamed symbols: they're uninformative
|
|
* and inserted at a whim. */
|
|
if (*symname(kallsyms, i) == '\0'
|
|
|| is_arm_mapping_symbol(symname(kallsyms, i)))
|
|
continue;
|
|
|
|
if (kallsyms->symtab[i].st_value <= addr
|
|
&& kallsyms->symtab[i].st_value > kallsyms->symtab[best].st_value)
|
|
best = i;
|
|
if (kallsyms->symtab[i].st_value > addr
|
|
&& kallsyms->symtab[i].st_value < nextval)
|
|
nextval = kallsyms->symtab[i].st_value;
|
|
}
|
|
|
|
if (!best)
|
|
return NULL;
|
|
|
|
if (size)
|
|
*size = nextval - kallsyms->symtab[best].st_value;
|
|
if (offset)
|
|
*offset = addr - kallsyms->symtab[best].st_value;
|
|
return symname(kallsyms, best);
|
|
}
|
|
|
|
/* For kallsyms to ask for address resolution. NULL means not found. Careful
|
|
* not to lock to avoid deadlock on oopses, simply disable preemption. */
|
|
const char *module_address_lookup(unsigned long addr,
|
|
unsigned long *size,
|
|
unsigned long *offset,
|
|
char **modname,
|
|
char *namebuf)
|
|
{
|
|
const char *ret = NULL;
|
|
struct module *mod;
|
|
|
|
preempt_disable();
|
|
mod = __module_address(addr);
|
|
if (mod) {
|
|
if (modname)
|
|
*modname = mod->name;
|
|
ret = get_ksymbol(mod, addr, size, offset);
|
|
}
|
|
/* Make a copy in here where it's safe */
|
|
if (ret) {
|
|
strncpy(namebuf, ret, KSYM_NAME_LEN - 1);
|
|
ret = namebuf;
|
|
}
|
|
preempt_enable();
|
|
|
|
return ret;
|
|
}
|
|
|
|
int lookup_module_symbol_name(unsigned long addr, char *symname)
|
|
{
|
|
struct module *mod;
|
|
|
|
preempt_disable();
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (within_module(addr, mod)) {
|
|
const char *sym;
|
|
|
|
sym = get_ksymbol(mod, addr, NULL, NULL);
|
|
if (!sym)
|
|
goto out;
|
|
strlcpy(symname, sym, KSYM_NAME_LEN);
|
|
preempt_enable();
|
|
return 0;
|
|
}
|
|
}
|
|
out:
|
|
preempt_enable();
|
|
return -ERANGE;
|
|
}
|
|
|
|
int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
|
|
unsigned long *offset, char *modname, char *name)
|
|
{
|
|
struct module *mod;
|
|
|
|
preempt_disable();
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (within_module(addr, mod)) {
|
|
const char *sym;
|
|
|
|
sym = get_ksymbol(mod, addr, size, offset);
|
|
if (!sym)
|
|
goto out;
|
|
if (modname)
|
|
strlcpy(modname, mod->name, MODULE_NAME_LEN);
|
|
if (name)
|
|
strlcpy(name, sym, KSYM_NAME_LEN);
|
|
preempt_enable();
|
|
return 0;
|
|
}
|
|
}
|
|
out:
|
|
preempt_enable();
|
|
return -ERANGE;
|
|
}
|
|
|
|
int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
|
|
char *name, char *module_name, int *exported)
|
|
{
|
|
struct module *mod;
|
|
|
|
preempt_disable();
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
struct mod_kallsyms *kallsyms;
|
|
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
kallsyms = rcu_dereference_sched(mod->kallsyms);
|
|
if (symnum < kallsyms->num_symtab) {
|
|
*value = kallsyms->symtab[symnum].st_value;
|
|
*type = kallsyms->symtab[symnum].st_info;
|
|
strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN);
|
|
strlcpy(module_name, mod->name, MODULE_NAME_LEN);
|
|
*exported = is_exported(name, *value, mod);
|
|
preempt_enable();
|
|
return 0;
|
|
}
|
|
symnum -= kallsyms->num_symtab;
|
|
}
|
|
preempt_enable();
|
|
return -ERANGE;
|
|
}
|
|
|
|
static unsigned long mod_find_symname(struct module *mod, const char *name)
|
|
{
|
|
unsigned int i;
|
|
struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
|
|
|
|
for (i = 0; i < kallsyms->num_symtab; i++)
|
|
if (strcmp(name, symname(kallsyms, i)) == 0 &&
|
|
kallsyms->symtab[i].st_shndx != SHN_UNDEF)
|
|
return kallsyms->symtab[i].st_value;
|
|
return 0;
|
|
}
|
|
|
|
/* Look for this name: can be of form module:name. */
|
|
unsigned long module_kallsyms_lookup_name(const char *name)
|
|
{
|
|
struct module *mod;
|
|
char *colon;
|
|
unsigned long ret = 0;
|
|
|
|
/* Don't lock: we're in enough trouble already. */
|
|
preempt_disable();
|
|
if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) {
|
|
if ((mod = find_module_all(name, colon - name, false)) != NULL)
|
|
ret = mod_find_symname(mod, colon+1);
|
|
} else {
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if ((ret = mod_find_symname(mod, name)) != 0)
|
|
break;
|
|
}
|
|
}
|
|
preempt_enable();
|
|
return ret;
|
|
}
|
|
|
|
int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
|
struct module *, unsigned long),
|
|
void *data)
|
|
{
|
|
struct module *mod;
|
|
unsigned int i;
|
|
int ret;
|
|
|
|
module_assert_mutex();
|
|
|
|
list_for_each_entry(mod, &modules, list) {
|
|
/* We hold module_mutex: no need for rcu_dereference_sched */
|
|
struct mod_kallsyms *kallsyms = mod->kallsyms;
|
|
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
for (i = 0; i < kallsyms->num_symtab; i++) {
|
|
|
|
if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
|
|
continue;
|
|
|
|
ret = fn(data, symname(kallsyms, i),
|
|
mod, kallsyms->symtab[i].st_value);
|
|
if (ret != 0)
|
|
return ret;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_KALLSYMS */
|
|
|
|
static void cfi_init(struct module *mod)
|
|
{
|
|
#ifdef CONFIG_CFI_CLANG
|
|
preempt_disable();
|
|
mod->cfi_check =
|
|
(cfi_check_fn)mod_find_symname(mod, CFI_CHECK_FN_NAME);
|
|
preempt_enable();
|
|
cfi_module_add(mod, module_addr_min, module_addr_max);
|
|
#endif
|
|
}
|
|
|
|
static void cfi_cleanup(struct module *mod)
|
|
{
|
|
#ifdef CONFIG_CFI_CLANG
|
|
cfi_module_remove(mod, module_addr_min, module_addr_max);
|
|
#endif
|
|
}
|
|
|
|
/* Maximum number of characters written by module_flags() */
|
|
#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
|
|
|
|
/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
|
|
static char *module_flags(struct module *mod, char *buf)
|
|
{
|
|
int bx = 0;
|
|
|
|
BUG_ON(mod->state == MODULE_STATE_UNFORMED);
|
|
if (mod->taints ||
|
|
mod->state == MODULE_STATE_GOING ||
|
|
mod->state == MODULE_STATE_COMING) {
|
|
buf[bx++] = '(';
|
|
bx += module_flags_taint(mod, buf + bx);
|
|
/* Show a - for module-is-being-unloaded */
|
|
if (mod->state == MODULE_STATE_GOING)
|
|
buf[bx++] = '-';
|
|
/* Show a + for module-is-being-loaded */
|
|
if (mod->state == MODULE_STATE_COMING)
|
|
buf[bx++] = '+';
|
|
buf[bx++] = ')';
|
|
}
|
|
buf[bx] = '\0';
|
|
|
|
return buf;
|
|
}
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
/* Called by the /proc file system to return a list of modules. */
|
|
static void *m_start(struct seq_file *m, loff_t *pos)
|
|
{
|
|
mutex_lock(&module_mutex);
|
|
return seq_list_start(&modules, *pos);
|
|
}
|
|
|
|
static void *m_next(struct seq_file *m, void *p, loff_t *pos)
|
|
{
|
|
return seq_list_next(p, &modules, pos);
|
|
}
|
|
|
|
static void m_stop(struct seq_file *m, void *p)
|
|
{
|
|
mutex_unlock(&module_mutex);
|
|
}
|
|
|
|
static int m_show(struct seq_file *m, void *p)
|
|
{
|
|
struct module *mod = list_entry(p, struct module, list);
|
|
char buf[MODULE_FLAGS_BUF_SIZE];
|
|
|
|
/* We always ignore unformed modules. */
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
return 0;
|
|
|
|
seq_printf(m, "%s %u",
|
|
mod->name, mod->init_layout.size + mod->core_layout.size);
|
|
print_unload_info(m, mod);
|
|
|
|
/* Informative for users. */
|
|
seq_printf(m, " %s",
|
|
mod->state == MODULE_STATE_GOING ? "Unloading" :
|
|
mod->state == MODULE_STATE_COMING ? "Loading" :
|
|
"Live");
|
|
/* Used by oprofile and other similar tools. */
|
|
seq_printf(m, " 0x%pK", mod->core_layout.base);
|
|
|
|
/* Taints info */
|
|
if (mod->taints)
|
|
seq_printf(m, " %s", module_flags(mod, buf));
|
|
|
|
seq_puts(m, "\n");
|
|
return 0;
|
|
}
|
|
|
|
/* Format: modulename size refcount deps address
|
|
|
|
Where refcount is a number or -, and deps is a comma-separated list
|
|
of depends or -.
|
|
*/
|
|
static const struct seq_operations modules_op = {
|
|
.start = m_start,
|
|
.next = m_next,
|
|
.stop = m_stop,
|
|
.show = m_show
|
|
};
|
|
|
|
static int modules_open(struct inode *inode, struct file *file)
|
|
{
|
|
return seq_open(file, &modules_op);
|
|
}
|
|
|
|
static const struct file_operations proc_modules_operations = {
|
|
.open = modules_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = seq_release,
|
|
};
|
|
|
|
static int __init proc_modules_init(void)
|
|
{
|
|
proc_create("modules", 0, NULL, &proc_modules_operations);
|
|
return 0;
|
|
}
|
|
module_init(proc_modules_init);
|
|
#endif
|
|
|
|
/* Given an address, look for it in the module exception tables. */
|
|
const struct exception_table_entry *search_module_extables(unsigned long addr)
|
|
{
|
|
const struct exception_table_entry *e = NULL;
|
|
struct module *mod;
|
|
|
|
preempt_disable();
|
|
mod = __module_address(addr);
|
|
if (!mod)
|
|
goto out;
|
|
|
|
if (!mod->num_exentries)
|
|
goto out;
|
|
|
|
e = search_extable(mod->extable,
|
|
mod->num_exentries,
|
|
addr);
|
|
out:
|
|
preempt_enable();
|
|
|
|
/*
|
|
* Now, if we found one, we are running inside it now, hence
|
|
* we cannot unload the module, hence no refcnt needed.
|
|
*/
|
|
return e;
|
|
}
|
|
|
|
/*
|
|
* is_module_address - is this address inside a module?
|
|
* @addr: the address to check.
|
|
*
|
|
* See is_module_text_address() if you simply want to see if the address
|
|
* is code (not data).
|
|
*/
|
|
bool is_module_address(unsigned long addr)
|
|
{
|
|
bool ret;
|
|
|
|
preempt_disable();
|
|
ret = __module_address(addr) != NULL;
|
|
preempt_enable();
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* __module_address - get the module which contains an address.
|
|
* @addr: the address.
|
|
*
|
|
* Must be called with preempt disabled or module mutex held so that
|
|
* module doesn't get freed during this.
|
|
*/
|
|
struct module *__module_address(unsigned long addr)
|
|
{
|
|
struct module *mod;
|
|
|
|
if (addr < module_addr_min || addr > module_addr_max)
|
|
return NULL;
|
|
|
|
module_assert_mutex_or_preempt();
|
|
|
|
mod = mod_find(addr);
|
|
if (mod) {
|
|
BUG_ON(!within_module(addr, mod));
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
mod = NULL;
|
|
}
|
|
return mod;
|
|
}
|
|
EXPORT_SYMBOL_GPL(__module_address);
|
|
|
|
/*
|
|
* is_module_text_address - is this address inside module code?
|
|
* @addr: the address to check.
|
|
*
|
|
* See is_module_address() if you simply want to see if the address is
|
|
* anywhere in a module. See kernel_text_address() for testing if an
|
|
* address corresponds to kernel or module code.
|
|
*/
|
|
bool is_module_text_address(unsigned long addr)
|
|
{
|
|
bool ret;
|
|
|
|
preempt_disable();
|
|
ret = __module_text_address(addr) != NULL;
|
|
preempt_enable();
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* __module_text_address - get the module whose code contains an address.
|
|
* @addr: the address.
|
|
*
|
|
* Must be called with preempt disabled or module mutex held so that
|
|
* module doesn't get freed during this.
|
|
*/
|
|
struct module *__module_text_address(unsigned long addr)
|
|
{
|
|
struct module *mod = __module_address(addr);
|
|
if (mod) {
|
|
/* Make sure it's within the text section. */
|
|
if (!within(addr, mod->init_layout.base, mod->init_layout.text_size)
|
|
&& !within(addr, mod->core_layout.base, mod->core_layout.text_size))
|
|
mod = NULL;
|
|
}
|
|
return mod;
|
|
}
|
|
EXPORT_SYMBOL_GPL(__module_text_address);
|
|
|
|
/* Don't grab lock, we're oopsing. */
|
|
void print_modules(void)
|
|
{
|
|
struct module *mod;
|
|
char buf[MODULE_FLAGS_BUF_SIZE];
|
|
|
|
printk(KERN_DEFAULT "Modules linked in:");
|
|
/* Most callers should already have preempt disabled, but make sure */
|
|
preempt_disable();
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
pr_cont(" %s%s", mod->name, module_flags(mod, buf));
|
|
}
|
|
preempt_enable();
|
|
if (last_unloaded_module[0])
|
|
pr_cont(" [last unloaded: %s]", last_unloaded_module);
|
|
pr_cont("\n");
|
|
}
|
|
|
|
#ifdef CONFIG_MODVERSIONS
|
|
/* Generate the signature for all relevant module structures here.
|
|
* If these change, we don't want to try to parse the module. */
|
|
void module_layout(struct module *mod,
|
|
struct modversion_info *ver,
|
|
struct kernel_param *kp,
|
|
struct kernel_symbol *ks,
|
|
struct tracepoint * const *tp)
|
|
{
|
|
}
|
|
EXPORT_SYMBOL(module_layout);
|
|
#endif
|