mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
807a44d01a
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJUyuGRAAoJEDjbvchgkmk+7EwQALYPOeh+AManQFB1MQvFuOgZ /4ulpjhGXw/RPTKHMeyHo8vRfUhMOx8UPF62uql+g1l9b/Zt2bs6qXu4QcxRRsQc trSTUpi+U14y1hkgqOVOcFYP2ZaTjNEBQgLJ4eGn46CliLqme+rfoyRYm2GXzcR4 6cbSAr3mufdFIpi9/8Dn62Gv0aws5lIv3qkHJXznyuux3tisPT5y6Ux2KJoivPn/ SqADtRpwo+7lTjl15fE++9AqNsGMorV6toT2OO/7nXP+824psInKLmREAT2qC99b BG61vcYdxOuHtzmwrvCf1jSRjxhvZT0j2xhBr/vCKcxy08AT0vDv68zrV1r6TIuu U7/CKXtFBY95cjfnkTLJuswBSuIA/+sQHV6DaddH0V8fcZ6rQMLrblQ9ZcFFFkmT 2SG6lmlXqZvcEKYGMnL/Dcow1rkRhB5stiGgTkYxjiRSRpzAHISRJ/GGpsT+rRqK HpBs5p9JshvRl7RWKwAu+DNGaEK1X/WYxc4/jw6dZFWX7lEWSMIPlr9zXgZCZ39y V6lV1VVlT9/CSs1swKHUyhHHehlFsnIlQ6Fkiycr/KkuqBLs92Hyb7WhpVa819yX osXdxSm6J54skiOLKYpBWHpnY09Tc+p28VEfMpErTExgp2oE8F34K7kdhoQPQb97 2mHiXNa+J4CLUNQ+sRmw =HDBo -----END PGP SIGNATURE----- Merge commit 'v3.10.67' into LA.BF64.1.2.9 This merge brings us up to date with upstream kernel.org tag v3.10.67. It also contains changes to allow forbidden warnings introduced in the commit 'core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors'. Once upstream has corrected these warnings, the changes to scripts/gcc-wrapper.py, in this commit, can be reverted. * 'v3.10.67' (915 commits): Linux 3.10.67 md/raid5: fetch_block must fetch all the blocks handle_stripe_dirtying wants. ext4: fix warning in ext4_da_update_reserve_space() quota: provide interface for readding allocated space into reserved space crypto: add missing crypto module aliases crypto: include crypto- module prefix in template crypto: prefix module autoloading with "crypto-" drbd: merge_bvec_fn: properly remap bvm->bi_bdev Revert "swiotlb-xen: pass dev_addr to swiotlb_tbl_unmap_single" ipvs: uninitialized data with IP_VS_IPV6 KEYS: close race between key lookup and freeing sata_dwc_460ex: fix resource leak on error path x86/asm/traps: Disable tracing and kprobes in fixup_bad_iret and sync_regs x86, tls: Interpret an all-zero struct user_desc as "no segment" x86, tls, ldt: Stop checking lm in LDT_empty x86/tsc: Change Fast TSC calibration failed from error to info x86, hyperv: Mark the Hyper-V clocksource as being continuous clocksource: exynos_mct: Fix bitmask regression for exynos4_mct_write can: dev: fix crtlmode_supported check bus: mvebu-mbus: fix support of MBus window 13 ARM: dts: imx25: Fix PWM "per" clocks time: adjtimex: Validate the ADJ_FREQUENCY values time: settimeofday: Validate the values of tv from user dm cache: share cache-metadata object across inactive and active DM tables ipr: wait for aborted command responses drm/i915: Fix mutex->owner inspection race under DEBUG_MUTEXES scripts/recordmcount.pl: There is no -m32 gcc option on Super-H anymore ALSA: usb-audio: Add mic volume fix quirk for Logitech Webcam C210 libata: prevent HSM state change race between ISR and PIO pinctrl: Fix two deadlocks gpio: sysfs: fix gpio device-attribute leak gpio: sysfs: fix gpio-chip device-attribute leak Linux 3.10.66 s390/3215: fix tty output containing tabs s390/3215: fix hanging console issue fsnotify: next_i is freed during fsnotify_unmount_inodes. netfilter: ipset: small potential read beyond the end of buffer mmc: sdhci: Fix sleep in atomic after inserting SD card LOCKD: Fix a race when initialising nlmsvc_timeout x86, um: actually mark system call tables readonly um: Skip futex_atomic_cmpxchg_inatomic() test decompress_bunzip2: off by one in get_next_block() ARM: shmobile: sh73a0 legacy: Set .control_parent for all irqpin instances ARM: omap5/dra7xx: Fix frequency typos ARM: clk-imx6q: fix video divider for rev T0 1.0 ARM: imx6q: drop unnecessary semicolon ARM: dts: imx25: Fix the SPI1 clocks Input: I8042 - add Acer Aspire 7738 to the nomux list Input: i8042 - reset keyboard to fix Elantech touchpad detection can: kvaser_usb: Don't send a RESET_CHIP for non-existing channels can: kvaser_usb: Reset all URB tx contexts upon channel close can: kvaser_usb: Don't free packets when tight on URBs USB: keyspan: fix null-deref at probe USB: cp210x: add IDs for CEL USB sticks and MeshWorks devices USB: cp210x: fix ID for production CEL MeshConnect USB Stick usb: dwc3: gadget: Stop TRB preparation after limit is reached usb: dwc3: gadget: Fix TRB preparation during SG OHCI: add a quirk for ULi M5237 blocking on reset gpiolib: of: Correct error handling in of_get_named_gpiod_flags NFSv4.1: Fix client id trunking on Linux ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing vfio-pci: Fix the check on pci device type in vfio_pci_probe() uvcvideo: Fix destruction order in uvc_delete() smiapp: Take mutex during PLL update in sensor initialisation af9005: fix kernel panic on init if compiled without IR smiapp-pll: Correct clock debug prints video/logo: prevent use of logos after they have been freed storvsc: ring buffer failures may result in I/O freeze iscsi-target: Fail connection on short sendmsg writes hp_accel: Add support for HP ZBook 15 cfg80211: Fix 160 MHz channels with 80+80 and 160 MHz drivers ARC: [nsimosci] move peripherals to match model to FPGA drm/i915: Force the CS stall for invalidate flushes drm/i915: Invalidate media caches on gen7 drm/radeon: properly filter DP1.2 4k modes on non-DP1.2 hw drm/radeon: check the right ring in radeon_evict_flags() drm/vmwgfx: Fix fence event code enic: fix rx skb checksum alx: fix alx_poll() tcp: Do not apply TSO segment limit to non-TSO packets tg3: tg3_disable_ints using uninitialized mailbox value to disable interrupts netlink: Don't reorder loads/stores before marking mmap netlink frame as available netlink: Always copy on mmap TX. Linux 3.10.65 mm: Don't count the stack guard page towards RLIMIT_STACK mm: propagate error from stack expansion even for guard page mm, vmscan: prevent kswapd livelock due to pfmemalloc-throttled process being killed perf session: Do not fail on processing out of order event perf: Fix events installation during moving group perf/x86/intel/uncore: Make sure only uncore events are collected Btrfs: don't delay inode ref updates during log replay ARM: mvebu: disable I/O coherency on non-SMP situations on Armada 370/375/38x/XP scripts/kernel-doc: don't eat struct members with __aligned nilfs2: fix the nilfs_iget() vs. nilfs_new_inode() races nfsd4: fix xdr4 inclusion of escaped char fs: nfsd: Fix signedness bug in compare_blob serial: samsung: wait for transfer completion before clock disable writeback: fix a subtle race condition in I_DIRTY clearing cdc-acm: memory leak in error case genhd: check for int overflow in disk_expand_part_tbl() USB: cdc-acm: check for valid interfaces ALSA: hda - Fix wrong gpio_dir & gpio_mask hint setups for IDT/STAC codecs ALSA: hda - using uninitialized data ALSA: usb-audio: extend KEF X300A FU 10 tweak to Arcam rPAC driver core: Fix unbalanced device reference in drivers_probe x86, vdso: Use asm volatile in __getcpu x86_64, vdso: Fix the vdso address randomization algorithm HID: Add a new id 0x501a for Genius MousePen i608X HID: add battery quirk for USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO keyboard HID: roccat: potential out of bounds in pyra_sysfs_write_settings() HID: i2c-hid: prevent buffer overflow in early IRQ HID: i2c-hid: fix race condition reading reports iommu/vt-d: Fix an off-by-one bug in __domain_mapping() UBI: Fix double free after do_sync_erase() UBI: Fix invalid vfree() pstore-ram: Allow optional mapping with pgprot_noncached pstore-ram: Fix hangs by using write-combine mappings PCI: Restore detection of read-only BARs ASoC: dwc: Ensure FIFOs are flushed to prevent channel swap ASoC: max98090: Fix ill-defined sidetone route ASoC: sigmadsp: Refuse to load firmware files with a non-supported version ath5k: fix hardware queue index assignment swiotlb-xen: pass dev_addr to swiotlb_tbl_unmap_single can: peak_usb: fix memset() usage can: peak_usb: fix cleanup sequence order in case of error during init ath9k: fix BE/BK queue order ath9k_hw: fix hardware queue allocation ocfs2: fix journal commit deadlock Linux 3.10.64 Btrfs: fix fs corruption on transaction abort if device supports discard Btrfs: do not move em to modified list when unpinning eCryptfs: Remove buggy and unnecessary write in file name decode routine eCryptfs: Force RO mount when encrypted view is enabled udf: Verify symlink size before loading it exit: pidns: alloc_pid() leaks pid_namespace if child_reaper is exiting ncpfs: return proper error from NCP_IOC_SETROOT ioctl crypto: af_alg - fix backlog handling userns: Unbreak the unprivileged remount tests userns: Allow setting gid_maps without privilege when setgroups is disabled userns: Add a knob to disable setgroups on a per user namespace basis userns: Rename id_map_mutex to userns_state_mutex userns: Only allow the creator of the userns unprivileged mappings userns: Check euid no fsuid when establishing an unprivileged uid mapping userns: Don't allow unprivileged creation of gid mappings userns: Don't allow setgroups until a gid mapping has been setablished userns: Document what the invariant required for safe unprivileged mappings. groups: Consolidate the setgroups permission checks umount: Disallow unprivileged mount force mnt: Update unprivileged remount test mnt: Implicitly add MNT_NODEV on remount when it was implicitly added by mount mac80211: free management frame keys when removing station mac80211: fix multicast LED blinking and counter KEYS: Fix stale key registration at error path isofs: Fix unchecked printing of ER records x86/tls: Don't validate lm in set_thread_area() after all dm space map metadata: fix sm_bootstrap_get_nr_blocks() dm bufio: fix memleak when using a dm_buffer's inline bio nfs41: fix nfs4_proc_layoutget error handling megaraid_sas: corrected return of wait_event from abort frame path mmc: block: add newline to sysfs display of force_ro mfd: tc6393xb: Fail ohci suspend if full state restore is required md/bitmap: always wait for writes on unplug. x86, kvm: Clear paravirt_enabled on KVM guests for espfix32's benefit x86_64, switch_to(): Load TLS descriptors before switching DS and ES x86/tls: Disallow unusual TLS segments x86/tls: Validate TLS entries to protect espfix isofs: Fix infinite looping over CE entries Linux 3.10.63 ALSA: usb-audio: Don't resubmit pending URBs at MIDI error recovery powerpc: 32 bit getcpu VDSO function uses 64 bit instructions ARM: sched_clock: Load cycle count after epoch stabilizes igb: bring link up when PHY is powered up ext2: Fix oops in ext2_get_block() called from ext2_quota_write() nEPT: Nested INVEPT net: sctp: use MAX_HEADER for headroom reserve in output path net: mvneta: fix Tx interrupt delay rtnetlink: release net refcnt on error in do_setlink() net/mlx4_core: Limit count field to 24 bits in qp_alloc_res tg3: fix ring init when there are more TX than RX channels ipv6: gre: fix wrong skb->protocol in WCCP sata_fsl: fix error handling of irq_of_parse_and_map ahci: disable MSI on SAMSUNG 0xa800 SSD AHCI: Add DeviceIDs for Sunrise Point-LP SATA controller media: smiapp: Only some selection targets are settable drm/i915: Unlock panel even when LVDS is disabled drm/radeon: kernel panic in drm_calc_vbltimestamp_from_scanoutpos with 3.18.0-rc6 i2c: davinci: generate STP always when NACK is received i2c: omap: fix i207 errata handling i2c: omap: fix NACK and Arbitration Lost irq handling xen-netfront: Remove BUGs on paged skb data which crosses a page boundary mm: fix swapoff hang after page migration and fork mm: frontswap: invalidate expired data on a dup-store failure Linux 3.10.62 nfsd: Fix ACL null pointer deref powerpc/powernv: Honor the generic "no_64bit_msi" flag bnx2fc: do not add shared skbs to the fcoe_rx_list nfsd4: fix leak of inode reference on delegation failure nfsd: Fix slot wake up race in the nfsv4.1 callback code rt2x00: do not align payload on modern H/W can: dev: avoid calling kfree_skb() from interrupt context spi: dw: Fix dynamic speed change. iser-target: Handle DEVICE_REMOVAL event on network portal listener correctly target: Don't call TFO->write_pending if data_length == 0 srp-target: Retry when QP creation fails with ENOMEM Input: xpad - use proper endpoint type ARM: 8222/1: mvebu: enable strex backoff delay ARM: 8216/1: xscale: correct auxiliary register in suspend/resume ALSA: usb-audio: Add ctrl message delay quirk for Marantz/Denon devices can: esd_usb2: fix memory leak on disconnect USB: xhci: don't start a halted endpoint before its new dequeue is set usb-quirks: Add reset-resume quirk for MS Wireless Laser Mouse 6000 usb: serial: ftdi_sio: add PIDs for Matrix Orbital products USB: serial: cp210x: add IDs for CEL MeshConnect USB Stick USB: keyspan: fix tty line-status reporting USB: keyspan: fix overrun-error reporting USB: ssu100: fix overrun-error reporting iio: Fix IIO_EVENT_CODE_EXTRACT_DIR bit mask powerpc/pseries: Fix endiannes issue in RTAS call from xmon powerpc/pseries: Honor the generic "no_64bit_msi" flag of/base: Fix PowerPC address parsing hack ASoC: wm_adsp: Avoid attempt to free buffers that might still be in use ASoC: sgtl5000: Fix SMALL_POP bit definition PCI/MSI: Add device flag indicating that 64-bit MSIs don't work ipx: fix locking regression in ipx_sendmsg and ipx_recvmsg pptp: fix stack info leak in pptp_getname() qmi_wwan: Add support for HP lt4112 LTE/HSPA+ Gobi 4G Modem ieee802154: fix error handling in ieee802154fake_probe() ipv4: Fix incorrect error code when adding an unreachable route inetdevice: fixed signed integer overflow sparc64: Fix constraints on swab helpers. uprobes, x86: Fix _TIF_UPROBE vs _TIF_NOTIFY_RESUME x86, mm: Set NX across entire PMD at boot x86: Require exact match for 'noxsave' command line option x86_64, traps: Rework bad_iret x86_64, traps: Stop using IST for #SS x86_64, traps: Fix the espfix64 #DF fixup and rewrite it in C MIPS: Loongson: Make platform serial setup always built-in. MIPS: oprofile: Fix backtrace on 64-bit kernel Linux 3.10.61 mm: memcg: handle non-error OOM situations more gracefully mm: memcg: do not trap chargers with full callstack on OOM mm: memcg: rework and document OOM waiting and wakeup mm: memcg: enable memcg OOM killer only for user faults x86: finish user fault error path with fatal signal arch: mm: pass userspace fault flag to generic fault handler arch: mm: do not invoke OOM killer on kernel fault OOM arch: mm: remove obsolete init OOM protection mm: invoke oom-killer from remaining unconverted page fault handlers net: sctp: fix skb_over_panic when receiving malformed ASCONF chunks net: sctp: fix panic on duplicate ASCONF chunks net: sctp: fix remote memory pressure from excessive queueing KVM: x86: Don't report guest userspace emulation error to userspace SCSI: hpsa: fix a race in cmd_free/scsi_done net/mlx4_en: Fix BlueFlame race ARM: Correct BUG() assembly to ensure it is endian-agnostic perf/x86/intel: Use proper dTLB-load-misses event on IvyBridge mei: bus: fix possible boundaries violation perf: Handle compat ioctl MIPS: Fix forgotten preempt_enable() when CPU has inclusive pcaches dell-wmi: Fix access out of memory ARM: probes: fix instruction fetch order with <asm/opcodes.h> br: fix use of ->rx_handler_data in code executed on non-rx_handler path netfilter: nf_nat: fix oops on netns removal netfilter: xt_bpf: add mising opaque struct sk_filter definition netfilter: nf_log: release skbuff on nlmsg put failure netfilter: nfnetlink_log: fix maximum packet length logged to userspace netfilter: nf_log: account for size of NLMSG_DONE attribute ipc: always handle a new value of auto_msgmni clocksource: Remove "weak" from clocksource_default_clock() declaration kgdb: Remove "weak" from kgdb_arch_pc() declaration media: ttusb-dec: buffer overflow in ioctl NFSv4: Fix races between nfs_remove_bad_delegation() and delegation return nfs: Fix use of uninitialized variable in nfs_getattr() NFS: Don't try to reclaim delegation open state if recovery failed NFSv4: Ensure that we remove NFSv4.0 delegations when state has expired Input: alps - allow up to 2 invalid packets without resetting device Input: alps - ignore potential bare packets when device is out of sync dm raid: ensure superblock's size matches device's logical block size dm btree: fix a recursion depth bug in btree walking code block: Fix computation of merged request priority parisc: Use compat layer for msgctl, shmat, shmctl and semtimedop syscalls scsi: only re-lock door after EH on devices that were reset nfs: fix pnfs direct write memory leak firewire: cdev: prevent kernel stack leaking into ioctl arguments arm64: __clear_user: handle exceptions on strb ARM: 8198/1: make kuser helpers depend on MMU drm/radeon: add missing crtc unlock when setting up the MC mac80211: fix use-after-free in defragmentation macvtap: Fix csum_start when VLAN tags are present iwlwifi: configure the LTR libceph: do not crash on large auth tickets xtensa: re-wire umount syscall to sys_oldumount ALSA: usb-audio: Fix memory leak in FTU quirk ahci: disable MSI instead of NCQ on Samsung pci-e SSDs on macbooks ahci: Add Device IDs for Intel Sunrise Point PCH audit: keep inode pinned x86, x32, audit: Fix x32's AUDIT_ARCH wrt audit sparc32: Implement xchg and atomic_xchg using ATOMIC_HASH locks sparc64: Do irq_{enter,exit}() around generic_smp_call_function*(). sparc64: Fix crashes in schizo_pcierr_intr_other(). sunvdc: don't call VD_OP_GET_VTOC vio: fix reuse of vio_dring slot sunvdc: limit each sg segment to a page sunvdc: compute vdisk geometry from capacity sunvdc: add cdrom and v1.1 protocol support net: sctp: fix memory leak in auth key management net: sctp: fix NULL pointer dereference in af->from_addr_param on malformed packet gre6: Move the setting of dev->iflink into the ndo_init functions. ip6_tunnel: Use ip6_tnl_dev_init as the ndo_init function. Linux 3.10.60 libceph: ceph-msgr workqueue needs a resque worker Btrfs: fix kfree on list_head in btrfs_lookup_csums_range error cleanup of: Fix overflow bug in string property parsing functions sysfs: driver core: Fix glue dir race condition by gdp_mutex i2c: at91: don't account as iowait acer-wmi: Add acpi_backlight=video quirk for the Acer KAV80 rbd: Fix error recovery in rbd_obj_read_sync() drm/radeon: remove invalid pci id usb: gadget: udc: core: fix kernel oops with soft-connect usb: gadget: function: acm: make f_acm pass USB20CV Chapter9 usb: dwc3: gadget: fix set_halt() bug with pending transfers crypto: algif - avoid excessive use of socket buffer in skcipher mm: Remove false WARN_ON from pagecache_isize_extended() x86, apic: Handle a bad TSC more gracefully posix-timers: Fix stack info leak in timer_create() mac80211: fix typo in starting baserate for rts_cts_rate_idx PM / Sleep: fix recovery during resuming from hibernation tty: Fix high cpu load if tty is unreleaseable quota: Properly return errors from dquot_writeback_dquots() ext3: Don't check quota format when there are no quota files nfsd4: fix crash on unknown operation number cpc925_edac: Report UE events properly e7xxx_edac: Report CE events properly i3200_edac: Report CE events properly i82860_edac: Report CE events properly scsi: Fix error handling in SCSI_IOCTL_SEND_COMMAND lib/bitmap.c: fix undefined shift in __bitmap_shift_{left|right}() cgroup/kmemleak: add kmemleak_free() for cgroup deallocations. usb: Do not allow usb_alloc_streams on unconfigured devices USB: opticon: fix non-atomic allocation in write path usb-storage: handle a skipped data phase spi: pxa2xx: toggle clocks on suspend if not disabled by runtime PM spi: pl022: Fix incorrect dma_unmap_sg usb: dwc3: gadget: Properly initialize LINK TRB wireless: rt2x00: add new rt2800usb device USB: option: add Haier CE81B CDMA modem usb: option: add support for Telit LE910 USB: cdc-acm: only raise DTR on transitions from B0 USB: cdc-acm: add device id for GW Instek AFG-2225 usb: serial: ftdi_sio: add "bricked" FTDI device PID usb: serial: ftdi_sio: add Awinda Station and Dongle products USB: serial: cp210x: add Silicon Labs 358x VID and PID serial: Fix divide-by-zero fault in uart_get_divisor() staging:iio:ade7758: Remove "raw" from channel name staging:iio:ade7758: Fix check if channels are enabled in prenable staging:iio:ade7758: Fix NULL pointer deref when enabling buffer staging:iio:ad5933: Drop "raw" from channel names staging:iio:ad5933: Fix NULL pointer deref when enabling buffer OOM, PM: OOM killed task shouldn't escape PM suspend freezer: Do not freeze tasks killed by OOM killer ext4: fix oops when loading block bitmap failed cpufreq: intel_pstate: Fix setting max_perf_pct in performance policy ext4: fix overflow when updating superblock backups after resize ext4: check s_chksum_driver when looking for bg csum presence ext4: fix reservation overflow in ext4_da_write_begin ext4: add ext4_iget_normal() which is to be used for dir tree lookups ext4: grab missed write_count for EXT4_IOC_SWAP_BOOT ext4: don't check quota format when there are no quota files ext4: check EA value offset when loading jbd2: free bh when descriptor block checksum fails MIPS: tlbex: Properly fix HUGE TLB Refill exception handler target: Fix APTPL metadata handling for dynamic MappedLUNs target: Fix queue full status NULL pointer for SCF_TRANSPORT_TASK_SENSE qla_target: don't delete changed nacls ARC: Update order of registers in KGDB to match GDB 7.5 ARC: [nsimosci] Allow "headless" models to boot KVM: x86: Emulator fixes for eip canonical checks on near branches KVM: x86: Fix wrong masking on relative jump/call kvm: x86: don't kill guest on unknown exit reason KVM: x86: Check non-canonical addresses upon WRMSR KVM: x86: Improve thread safety in pit KVM: x86: Prevent host from panicking on shared MSR writes. kvm: fix excessive pages un-pinning in kvm_iommu_map error path. media: tda7432: Fix setting TDA7432_MUTE bit for TDA7432_RF register media: ds3000: fix LNB supply voltage on Tevii S480 on initialization media: em28xx-v4l: give back all active video buffers to the vb2 core properly on streaming stop media: v4l2-common: fix overflow in v4l_bound_align_image() drm/nouveau/bios: memset dcb struct to zero before parsing drm/tilcdc: Fix the error path in tilcdc_load() drm/ast: Fix HW cursor image Input: i8042 - quirks for Fujitsu Lifebook A544 and Lifebook AH544 Input: i8042 - add noloop quirk for Asus X750LN framebuffer: fix border color modules, lock around setting of MODULE_STATE_UNFORMED dm log userspace: fix memory leak in dm_ulog_tfr_init failure path block: fix alignment_offset math that assumes io_min is a power-of-2 drbd: compute the end before rb_insert_augmented() dm bufio: update last_accessed when relinking a buffer virtio_pci: fix virtio spec compliance on restore selinux: fix inode security list corruption pstore: Fix duplicate {console,ftrace}-efi entries mfd: rtsx_pcr: Fix MSI enable error handling mnt: Prevent pivot_root from creating a loop in the mount tree UBI: add missing kmem_cache_free() in process_pool_aeb error path random: add and use memzero_explicit() for clearing data crypto: more robust crypto_memneq fix misuses of f_count() in ppp and netlink kill wbuf_queued/wbuf_dwork_lock ALSA: pcm: Zero-clear reserved fields of PCM status ioctl in compat mode evm: check xattr value length and type in evm_inode_setxattr() x86, pageattr: Prevent overflow in slow_virt_to_phys() for X86_PAE x86_64, entry: Fix out of bounds read on sysenter x86_64, entry: Filter RFLAGS.NT on entry from userspace x86, flags: Rename X86_EFLAGS_BIT1 to X86_EFLAGS_FIXED x86, fpu: shift drop_init_fpu() from save_xstate_sig() to handle_signal() x86, fpu: __restore_xstate_sig()->math_state_restore() needs preempt_disable() x86: Reject x32 executables if x32 ABI not supported vfs: fix data corruption when blocksize < pagesize for mmaped data UBIFS: fix free log space calculation UBIFS: fix a race condition UBIFS: remove mst_mutex fs: Fix theoretical division by 0 in super_cache_scan(). fs: make cont_expand_zero interruptible mmc: rtsx_pci_sdmmc: fix incorrect last byte in R2 response libata-sff: Fix controllers with no ctl port pata_serverworks: disable 64-KB DMA transfers on Broadcom OSB4 IDE Controller Revert "percpu: free percpu allocation info for uniprocessor system" lockd: Try to reconnect if statd has moved drivers/net: macvtap and tun depend on INET ipv4: dst_entry leak in ip_send_unicast_reply() ax88179_178a: fix bonding failure ipv4: fix nexthop attlen check in fib_nh_match tracing/syscalls: Ignore numbers outside NR_syscalls' range Linux 3.10.59 ecryptfs: avoid to access NULL pointer when write metadata in xattr ARM: at91/PMC: don't forget to write PMC_PCDR register to disable clocks ALSA: usb-audio: Add support for Steinberg UR22 USB interface ALSA: emu10k1: Fix deadlock in synth voice lookup ALSA: pcm: use the same dma mmap codepath both for arm and arm64 arm64: compat: fix compat types affecting struct compat_elf_prpsinfo spi: dw-mid: terminate ongoing transfers at exit kernel: add support for gcc 5 fanotify: enable close-on-exec on events' fd when requested in fanotify_init() mm: clear __GFP_FS when PF_MEMALLOC_NOIO is set Bluetooth: Fix issue with USB suspend in btusb driver Bluetooth: Fix HCI H5 corrupted ack value rt2800: correct BBP1_TX_POWER_CTRL mask PCI: Generate uppercase hex for modalias interface class PCI: Increase IBM ipr SAS Crocodile BARs to at least system page size iwlwifi: Add missing PCI IDs for the 7260 series NFSv4.1: Fix an NFSv4.1 state renewal regression NFSv4: fix open/lock state recovery error handling NFSv4: Fix lock recovery when CREATE_SESSION/SETCLIENTID_CONFIRM fails lzo: check for length overrun in variable length encoding. Revert "lzo: properly check for overruns" Documentation: lzo: document part of the encoding m68k: Disable/restore interrupts in hwreg_present()/hwreg_write() Drivers: hv: vmbus: Fix a bug in vmbus_open() Drivers: hv: vmbus: Cleanup vmbus_establish_gpadl() Drivers: hv: vmbus: Cleanup vmbus_teardown_gpadl() Drivers: hv: vmbus: Cleanup vmbus_post_msg() firmware_class: make sure fw requests contain a name qla2xxx: Use correct offset to req-q-out for reserve calculation mptfusion: enable no_write_same for vmware scsi disks be2iscsi: check ip buffer before copying regmap: fix NULL pointer dereference in _regmap_write/read regmap: debugfs: fix possbile NULL pointer dereference spi: dw-mid: check that DMA was inited before exit spi: dw-mid: respect 8 bit mode x86/intel/quark: Switch off CR4.PGE so TLB flush uses CR3 instead kvm: don't take vcpu mutex for obviously invalid vcpu ioctls KVM: s390: unintended fallthrough for external call kvm: x86: fix stale mmio cache bug fs: Add a missing permission check to do_umount Btrfs: fix race in WAIT_SYNC ioctl Btrfs: fix build_backref_tree issue with multiple shared blocks Btrfs: try not to ENOSPC on log replay Linux 3.10.58 USB: cp210x: add support for Seluxit USB dongle USB: serial: cp210x: added Ketra N1 wireless interface support USB: Add device quirk for ASUS T100 Base Station keyboard ipv6: reallocate addrconf router for ipv6 address when lo device up tcp: fixing TLP's FIN recovery sctp: handle association restarts when the socket is closed. ip6_gre: fix flowi6_proto value in xmit path hyperv: Fix a bug in netvsc_start_xmit() tg3: Allow for recieve of full-size 8021AD frames tg3: Work around HW/FW limitations with vlan encapsulated frames l2tp: fix race while getting PMTU on PPP pseudo-wire openvswitch: fix panic with multiple vlan headers packet: handle too big packets for PACKET_V3 tcp: fix tcp_release_cb() to dispatch via address family for mtu_reduced() sit: Fix ipip6_tunnel_lookup device matching criteria myri10ge: check for DMA mapping errors Linux 3.10.57 cpufreq: ondemand: Change the calculation of target frequency cpufreq: Fix wrong time unit conversion nl80211: clear skb cb before passing to netlink drbd: fix regression 'out of mem, failed to invoke fence-peer helper' jiffies: Fix timeval conversion to jiffies md/raid5: disable 'DISCARD' by default due to safety concerns. media: vb2: fix VBI/poll regression mm: numa: Do not mark PTEs pte_numa when splitting huge pages mm, thp: move invariant bug check out of loop in __split_huge_page_map ring-buffer: Fix infinite spin in reading buffer init/Kconfig: Fix HAVE_FUTEX_CMPXCHG to not break up the EXPERT menu perf: fix perf bug in fork() udf: Avoid infinite loop when processing indirect ICBs Linux 3.10.56 vm_is_stack: use for_each_thread() rather then buggy while_each_thread() oom_kill: add rcu_read_lock() into find_lock_task_mm() oom_kill: has_intersects_mems_allowed() needs rcu_read_lock() oom_kill: change oom_kill.c to use for_each_thread() introduce for_each_thread() to replace the buggy while_each_thread() kernel/fork.c:copy_process(): unify CLONE_THREAD-or-thread_group_leader code arm: multi_v7_defconfig: Enable Zynq UART driver ext2: Fix fs corruption in ext2_get_xip_mem() serial: 8250_dma: check the result of TX buffer mapping ARM: 7748/1: oabi: handle faults when loading swi instruction from userspace netfilter: nf_conntrack: avoid large timeout for mid-stream pickup PM / sleep: Use valid_state() for platform-dependent sleep states only PM / sleep: Add state field to pm_states[] entries ipvs: fix ipv6 hook registration for local replies ipvs: Maintain all DSCP and ECN bits for ipv6 tun forwarding ipvs: avoid netns exit crash on ip_vs_conn_drop_conntrack md/raid1: fix_read_error should act on all non-faulty devices. media: cx18: fix kernel oops with tda8290 tuner Fix nasty 32-bit overflow bug in buffer i/o code. perf kmem: Make it work again on non NUMA machines perf: Fix a race condition in perf_remove_from_context() alarmtimer: Lock k_itimer during timer callback alarmtimer: Do not signal SIGEV_NONE timers parisc: Only use -mfast-indirect-calls option for 32-bit kernel builds powerpc/perf: Fix ABIv2 kernel backtraces sched: Fix unreleased llc_shared_mask bit during CPU hotplug ocfs2/dlm: do not get resource spinlock if lockres is new nilfs2: fix data loss with mmap() fs/notify: don't show f_handle if exportfs_encode_inode_fh failed fsnotify/fdinfo: use named constants instead of hardcoded values kcmp: fix standard comparison bug Revert "mac80211: disable uAPSD if all ACs are under ACM" usb: dwc3: core: fix ordering for PHY suspend usb: dwc3: core: fix order of PM runtime calls usb: host: xhci: fix compliance mode workaround genhd: fix leftover might_sleep() in blk_free_devt() lockd: fix rpcbind crash on lockd startup failure rtlwifi: rtl8192cu: Add new ID percpu: perform tlb flush after pcpu_map_pages() failure percpu: fix pcpu_alloc_pages() failure path percpu: free percpu allocation info for uniprocessor system ata_piix: Add Device IDs for Intel 9 Series PCH Input: i8042 - add nomux quirk for Avatar AVIU-145A6 Input: i8042 - add Fujitsu U574 to no_timeout dmi table Input: atkbd - do not try 'deactivate' keyboard on any LG laptops Input: elantech - fix detection of touchpad on ASUS s301l Input: synaptics - add support for ForcePads Input: serport - add compat handling for SPIOCSTYPE ioctl dm crypt: fix access beyond the end of allocated space block: Fix dev_t minor allocation lifetime workqueue: apply __WQ_ORDERED to create_singlethread_workqueue() Revert "iwlwifi: dvm: don't enable CTS to self" SCSI: libiscsi: fix potential buffer overrun in __iscsi_conn_send_pdu NFC: microread: Potential overflows in microread_target_discovered() iscsi-target: Fix memory corruption in iscsit_logout_post_handler_diffcid iscsi-target: avoid NULL pointer in iscsi_copy_param_list failure Target/iser: Don't put isert_conn inside disconnected handler Target/iser: Get isert_conn reference once got to connected_handler iio:inkern: fix overwritten -EPROBE_DEFER in of_iio_channel_get_by_name iio:magnetometer: bugfix magnetometers gain values iio: adc: ad_sigma_delta: Fix indio_dev->trig assignment iio: st_sensors: Fix indio_dev->trig assignment iio: meter: ade7758: Fix indio_dev->trig assignment iio: inv_mpu6050: Fix indio_dev->trig assignment iio: gyro: itg3200: Fix indio_dev->trig assignment iio:trigger: modify return value for iio_trigger_get CIFS: Fix SMB2 readdir error handling CIFS: Fix directory rename error ASoC: davinci-mcasp: Correct rx format unit configuration shmem: fix nlink for rename overwrite directory x86 early_ioremap: Increase FIX_BTMAPS_SLOTS to 8 KVM: x86: handle idiv overflow at kvm_write_tsc regmap: Fix handling of volatile registers for format_write() chips ACPICA: Update to GPIO region handler interface. MIPS: mcount: Adjust stack pointer for static trace in MIPS32 MIPS: ZBOOT: add missing <linux/string.h> include ARM: 8165/1: alignment: don't break misaligned NEON load/store ARM: 7897/1: kexec: Use the right ISA for relocate_new_kernel ARM: 8133/1: use irq_set_affinity with force=false when migrating irqs ARM: 8128/1: abort: don't clear the exclusive monitors NFSv4: Fix another bug in the close/open_downgrade code NFSv4: nfs4_state_manager() vs. nfs_server_remove_lists() usb:hub set hub->change_bits when over-current happens usb: dwc3: omap: fix ordering for runtime pm calls USB: EHCI: unlink QHs even after the controller has stopped USB: storage: Add quirks for Entrega/Xircom USB to SCSI converters USB: storage: Add quirk for Ariston Technologies iConnect USB to SCSI adapter USB: storage: Add quirk for Adaptec USBConnect 2000 USB-to-SCSI Adapter storage: Add single-LUN quirk for Jaz USB Adapter usb: hub: take hub->hdev reference when processing from eventlist xhci: fix oops when xhci resumes from hibernate with hw lpm capable devices xhci: Fix null pointer dereference if xhci initialization fails USB: zte_ev: fix removed PIDs USB: ftdi_sio: add support for NOVITUS Bono E thermal printer USB: sierra: add 1199:68AA device ID USB: sierra: avoid CDC class functions on "68A3" devices USB: zte_ev: remove duplicate Qualcom PID USB: zte_ev: remove duplicate Gobi PID Revert "USB: option,zte_ev: move most ZTE CDMA devices to zte_ev" USB: option: add VIA Telecom CDS7 chipset device id USB: option: reduce interrupt-urb logging verbosity USB: serial: fix potential heap buffer overflow USB: sisusb: add device id for Magic Control USB video USB: serial: fix potential stack buffer overflow USB: serial: pl2303: add device id for ztek device xtensa: fix a6 and a7 handling in fast_syscall_xtensa xtensa: fix TLBTEMP_BASE_2 region handling in fast_second_level_miss xtensa: fix access to THREAD_RA/THREAD_SP/THREAD_DS xtensa: fix address checks in dma_{alloc,free}_coherent xtensa: replace IOCTL code definitions with constants drm/radeon: add connector quirk for fujitsu board drm/vmwgfx: Fix a potential infinite spin waiting for fifo idle drm/ast: AST2000 cannot be detected correctly drm/i915: Wait for vblank before enabling the TV encoder drm/i915: Remove bogus __init annotation from DMI callbacks HID: logitech-dj: prevent false errors to be shown HID: magicmouse: sanity check report size in raw_event() callback HID: picolcd: sanity check report size in raw_event() callback cfq-iosched: Fix wrong children_weight calculation ALSA: pcm: fix fifo_size frame calculation ALSA: hda - Fix invalid pin powermap without jack detection ALSA: hda - Fix COEF setups for ALC1150 codec ALSA: core: fix buffer overflow in snd_info_get_line() arm64: ptrace: fix compat hardware watchpoint reporting trace: Fix epoll hang when we race with new entries i2c: at91: Fix a race condition during signal handling in at91_do_twi_xfer. i2c: at91: add bound checking on SMBus block length bytes arm64: flush TLS registers during exec ibmveth: Fix endian issues with rx_no_buffer statistic ahci: add pcid for Marvel 0x9182 controller ahci: Add Device IDs for Intel 9 Series PCH pata_scc: propagate return value of scc_wait_after_reset drm/i915: read HEAD register back in init_ring_common() to enforce ordering drm/radeon: load the lm63 driver for an lm64 thermal chip. drm/ttm: Choose a pool to shrink correctly in ttm_dma_pool_shrink_scan(). drm/ttm: Fix possible division by 0 in ttm_dma_pool_shrink_scan(). drm/tilcdc: fix double kfree drm/tilcdc: fix release order on exit drm/tilcdc: panel: fix leak when unloading the module drm/tilcdc: tfp410: fix dangling sysfs connector node drm/tilcdc: slave: fix dangling sysfs connector node drm/tilcdc: panel: fix dangling sysfs connector node carl9170: fix sending URBs with wrong type when using full-speed Linux 3.10.55 libceph: gracefully handle large reply messages from the mon libceph: rename ceph_msg::front_max to front_alloc_len tpm: Provide a generic means to override the chip returned timeouts vfs: fix bad hashing of dentries dcache.c: get rid of pointless macros IB/srp: Fix deadlock between host removal and multipathd blkcg: don't call into policy draining if root_blkg is already gone mtd: nand: omap: Fix 1-bit Hamming code scheme, omap_calculate_ecc() mtd/ftl: fix the double free of the buffers allocated in build_maps() CIFS: Fix wrong restart readdir for SMB1 CIFS: Fix wrong filename length for SMB2 CIFS: Fix wrong directory attributes after rename CIFS: Possible null ptr deref in SMB2_tcon CIFS: Fix async reading on reconnects CIFS: Fix STATUS_CANNOT_DELETE error mapping for SMB2 libceph: do not hard code max auth ticket len libceph: add process_one_ticket() helper libceph: set last_piece in ceph_msg_data_pages_cursor_init() correctly md/raid1,raid10: always abort recover on write error. xfs: don't zero partial page cache pages during O_DIRECT writes xfs: don't zero partial page cache pages during O_DIRECT writes xfs: don't dirty buffers beyond EOF xfs: quotacheck leaves dquot buffers without verifiers RDMA/iwcm: Use a default listen backlog if needed md/raid10: Fix memory leak when raid10 reshape completes. md/raid10: fix memory leak when reshaping a RAID10. md/raid6: avoid data corruption during recovery of double-degraded RAID6 Bluetooth: Avoid use of session socket after the session gets freed Bluetooth: never linger on process exit mnt: Add tests for unprivileged remount cases that have found to be faulty mnt: Change the default remount atime from relatime to the existing value mnt: Correct permission checks in do_remount mnt: Move the test for MNT_LOCK_READONLY from change_mount_flags into do_remount mnt: Only change user settable mount flags in remount ring-buffer: Up rb_iter_peek() loop count to 3 ring-buffer: Always reset iterator to reader page ACPI / cpuidle: fix deadlock between cpuidle_lock and cpu_hotplug.lock ACPI: Run fixed event device notifications in process context ACPICA: Utilities: Fix memory leak in acpi_ut_copy_iobject_to_iobject bfa: Fix undefined bit shift on big-endian architectures with 32-bit DMA address ASoC: pxa-ssp: drop SNDRV_PCM_FMTBIT_S24_LE ASoC: max98090: Fix missing free_irq ASoC: samsung: Correct I2S DAI suspend/resume ops ASoC: wm_adsp: Add missing MODULE_LICENSE ASoC: pcm: fix dpcm_path_put in dpcm runtime update openrisc: Rework signal handling MIPS: Fix accessing to per-cpu data when flushing the cache MIPS: OCTEON: make get_system_type() thread-safe MIPS: asm: thread_info: Add _TIF_SECCOMP flag MIPS: Cleanup flags in syscall flags handlers. MIPS: asm/reg.h: Make 32- and 64-bit definitions available at the same time MIPS: Remove BUG_ON(!is_fpu_owner()) in do_ade() MIPS: tlbex: Fix a missing statement for HUGETLB MIPS: Prevent user from setting FCSR cause bits MIPS: GIC: Prevent array overrun drivers: scsi: storvsc: Correctly handle TEST_UNIT_READY failure Drivers: scsi: storvsc: Implement a eh_timed_out handler powerpc/pseries: Failure on removing device node powerpc/mm: Use read barrier when creating real_pte powerpc/mm/numa: Fix break placement regulator: arizona-ldo1: remove bypass functionality mfd: omap-usb-host: Fix improper mask use. kernel/smp.c:on_each_cpu_cond(): fix warning in fallback path CAPABILITIES: remove undefined caps from all processes tpm: missing tpm_chip_put in tpm_get_random() firmware: Do not use WARN_ON(!spin_is_locked()) spi: omap2-mcspi: Configure hardware when slave driver changes mode spi: orion: fix incorrect handling of cell-index DT property iommu/amd: Fix cleanup_domain for mass device removal media: media-device: Remove duplicated memset() in media_enum_entities() media: au0828: Only alt setting logic when needed media: xc4000: Fix get_frequency() media: xc5000: Fix get_frequency() Linux 3.10.54 USB: fix build error with CONFIG_PM_RUNTIME disabled NFSv4: Fix problems with close in the presence of a delegation NFSv3: Fix another acl regression svcrdma: Select NFSv4.1 backchannel transport based on forward channel NFSD: Decrease nfsd_users in nfsd_startup_generic fail usb: hub: Prevent hub autosuspend if usbcore.autosuspend is -1 USB: whiteheat: Added bounds checking for bulk command response USB: ftdi_sio: Added PID for new ekey device USB: ftdi_sio: add Basic Micro ATOM Nano USB2Serial PID ARM: OMAP2+: hwmod: Rearm wake-up interrupts for DT when MUSB is idled usb: xhci: amd chipset also needs short TX quirk xhci: Treat not finding the event_seg on COMP_STOP the same as COMP_STOP_INVAL Staging: speakup: Update __speakup_paste_selection() tty (ab)usage to match vt jbd2: fix infinite loop when recovering corrupt journal blocks mei: nfc: fix memory leak in error path mei: reset client state on queued connect request Btrfs: fix csum tree corruption, duplicate and outdated checksums hpsa: fix bad -ENOMEM return value in hpsa_big_passthru_ioctl x86/efi: Enforce CONFIG_RELOCATABLE for EFI boot stub x86_64/vsyscall: Fix warn_bad_vsyscall log output x86: don't exclude low BIOS area when allocating address space for non-PCI cards drm/radeon: add additional SI pci ids ext4: fix BUG_ON in mb_free_blocks() kvm: iommu: fix the third parameter of kvm_iommu_put_pages (CVE-2014-3601) Revert "KVM: x86: Increase the number of fixed MTRR regs to 10" KVM: nVMX: fix "acknowledge interrupt on exit" when APICv is in use KVM: x86: always exit on EOIs for interrupts listed in the IOAPIC redir table KVM: x86: Inter-privilege level ret emulation is not implemeneted crypto: ux500 - make interrupt mode plausible serial: core: Preserve termios c_cflag for console resume ext4: fix ext4_discard_allocated_blocks() if we can't allocate the pa struct drivers/i2c/busses: use correct type for dma_map/unmap hwmon: (dme1737) Prevent overflow problem when writing large limits hwmon: (ads1015) Fix out-of-bounds array access hwmon: (lm85) Fix various errors on attribute writes hwmon: (ads1015) Fix off-by-one for valid channel index checking hwmon: (gpio-fan) Prevent overflow problem when writing large limits hwmon: (lm78) Fix overflow problems seen when writing large temperature limits hwmon: (sis5595) Prevent overflow problem when writing large limits drm: omapdrm: fix compiler errors ARM: OMAP3: Fix choice of omap3_restore_es function in OMAP34XX rev3.1.2 case. mei: start disconnect request timer consistently ALSA: hda/realtek - Avoid setting wrong COEF on ALC269 & co ALSA: hda/ca0132 - Don't try loading firmware at resume when already failed ALSA: virtuoso: add Xonar Essence STX II support ALSA: hda - fix an external mic jack problem on a HP machine USB: Fix persist resume of some SS USB devices USB: ehci-pci: USB host controller support for Intel Quark X1000 USB: serial: ftdi_sio: Add support for new Xsens devices USB: serial: ftdi_sio: Annotate the current Xsens PID assignments USB: OHCI: don't lose track of EDs when a controller dies isofs: Fix unbounded recursion when processing relocated directories HID: fix a couple of off-by-ones HID: logitech: perform bounds checking on device_id early enough stable_kernel_rules: Add pointer to netdev-FAQ for network patches Linux 3.10.53 arch/sparc/math-emu/math_32.c: drop stray break operator sparc64: ldc_connect() should not return EINVAL when handshake is in progress. sunsab: Fix detection of BREAK on sunsab serial console bbc-i2c: Fix BBC I2C envctrl on SunBlade 2000 sparc64: Guard against flushing openfirmware mappings. sparc64: Do not insert non-valid PTEs into the TSB hash table. sparc64: Add membar to Niagara2 memcpy code. sparc64: Fix huge TSB mapping on pre-UltraSPARC-III cpus. sparc64: Don't bark so loudly about 32-bit tasks generating 64-bit fault addresses. sparc64: Fix top-level fault handling bugs. sparc64: Handle 32-bit tasks properly in compute_effective_address(). sparc64: Make itc_sync_lock raw sparc64: Fix argument sign extension for compat_sys_futex(). sctp: fix possible seqlock seadlock in sctp_packet_transmit() iovec: make sure the caller actually wants anything in memcpy_fromiovecend net: Correctly set segment mac_len in skb_segment(). macvlan: Initialize vlan_features to turn on offload support. net: sctp: inherit auth_capable on INIT collisions tcp: Fix integer-overflow in TCP vegas tcp: Fix integer-overflows in TCP veno net: sendmsg: fix NULL pointer dereference ip: make IP identifiers less predictable inetpeer: get rid of ip_id_count bnx2x: fix crash during TSO tunneling Linux 3.10.52 x86/espfix/xen: Fix allocation of pages for paravirt page tables lib/btree.c: fix leak of whole btree nodes net/l2tp: don't fall back on UDP [get|set]sockopt net: mvneta: replace Tx timer with a real interrupt net: mvneta: add missing bit descriptions for interrupt masks and causes net: mvneta: do not schedule in mvneta_tx_timeout net: mvneta: use per_cpu stats to fix an SMP lock up net: mvneta: increase the 64-bit rx/tx stats out of the hot path Revert "mac80211: move "bufferable MMPDU" check to fix AP mode scan" staging: vt6655: Fix Warning on boot handle_irq_event_percpu. x86_64/entry/xen: Do not invoke espfix64 on Xen x86, espfix: Make it possible to disable 16-bit support x86, espfix: Make espfix64 a Kconfig option, fix UML x86, espfix: Fix broken header guard x86, espfix: Move espfix definitions into a separate header file x86-64, espfix: Don't leak bits 31:16 of %esp returning to 16-bit stack Revert "x86-64, modify_ldt: Make support for 16-bit segments a runtime option" timer: Fix lock inversion between hrtimer_bases.lock and scheduler locks printk: rename printk_sched to printk_deferred iio: buffer: Fix demux table creation staging: vt6655: Fix disassociated messages every 10 seconds mm, thp: do not allow thp faults to avoid cpuset restrictions scsi: handle flush errors properly rapidio/tsi721_dma: fix failure to obtain transaction descriptor cfg80211: fix mic_failure tracing ARM: 8115/1: LPAE: reduce damage caused by idmap to virtual memory layout crypto: af_alg - properly label AF_ALG socket Linux 3.10.51 core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors x86/efi: Include a .bss section within the PE/COFF headers s390/ptrace: fix PSW mask check Fix gcc-4.9.0 miscompilation of load_balance() in scheduler mm: hugetlb: fix copy_hugetlb_page_range() x86_32, entry: Store badsys error code in %eax hwmon: (smsc47m192) Fix temperature limit and vrm write operations parisc: Remove SA_RESTORER define coredump: fix the setting of PF_DUMPCORE Input: fix defuzzing logic slab_common: fix the check for duplicate slab names slab_common: Do not check for duplicate slab names tracing: Fix wraparound problems in "uptime" trace clock blkcg: don't call into policy draining if root_blkg is already gone ahci: add support for the Promise FastTrak TX8660 SATA HBA (ahci mode) libata: introduce ata_host->n_tags to avoid oops on SAS controllers libata: support the ata host which implements a queue depth less than 32 block: don't assume last put of shared tags is for the host block: provide compat ioctl for BLKZEROOUT media: tda10071: force modulation to QPSK on DVB-S media: hdpvr: fix two audio bugs Linux 3.10.50 ARC: Implement ptrace(PTRACE_GET_THREAD_AREA) sched: Fix possible divide by zero in avg_atom() calculation locking/mutex: Disable optimistic spinning on some architectures PM / sleep: Fix request_firmware() error at resume dm cache metadata: do not allow the data block size to change dm thin metadata: do not allow the data block size to change alarmtimer: Fix bug where relative alarm timers were treated as absolute drm/radeon: avoid leaking edid data drm/qxl: return IRQ_NONE if it was not our irq drm/radeon: set default bl level to something reasonable irqchip: gic: Fix core ID calculation when topology is read from DT irqchip: gic: Add support for cortex a7 compatible string ring-buffer: Fix polling on trace_pipe mwifiex: fix Tx timeout issue perf/x86/intel: ignore CondChgd bit to avoid false NMI handling ipv4: fix buffer overflow in ip_options_compile() dns_resolver: Null-terminate the right string dns_resolver: assure that dns_query() result is null-terminated sunvnet: clean up objects created in vnet_new() on vnet_exit() net: pppoe: use correct channel MTU when using Multilink PPP net: sctp: fix information leaks in ulpevent layer tipc: clear 'next'-pointer of message fragments before reassembly be2net: set EQ DB clear-intr bit in be_open() netlink: Fix handling of error from netlink_dump(). net: mvneta: Fix big endian issue in mvneta_txq_desc_csum() net: mvneta: fix operation in 10 Mbit/s mode appletalk: Fix socket referencing in skb tcp: fix false undo corner cases igmp: fix the problem when mc leave group net: qmi_wwan: add two Sierra Wireless/Netgear devices net: qmi_wwan: Add ID for Telewell TW-LTE 4G v2 ipv4: icmp: Fix pMTU handling for rare case tcp: Fix divide by zero when pushing during tcp-repair bnx2x: fix possible panic under memory stress net: fix sparse warning in sk_dst_set() ipv4: irq safe sk_dst_[re]set() and ipv4_sk_update_pmtu() fix ipv4: fix dst race in sk_dst_get() 8021q: fix a potential memory leak net: sctp: check proc_dointvec result in proc_sctp_do_auth tcp: fix tcp_match_skb_to_sack() for unaligned SACK at end of an skb ip_tunnel: fix ip_tunnel_lookup shmem: fix splicing from a hole while it's punched shmem: fix faulting into a hole, not taking i_mutex shmem: fix faulting into a hole while it's punched iwlwifi: dvm: don't enable CTS to self igb: do a reset on SR-IOV re-init if device is down hwmon: (adt7470) Fix writes to temperature limit registers hwmon: (da9052) Don't use dash in the name attribute hwmon: (da9055) Don't use dash in the name attribute tracing: Add ftrace_trace_stack into __trace_puts/__trace_bputs tracing: Fix graph tracer with stack tracer on other archs fuse: handle large user and group ID Bluetooth: Ignore H5 non-link packets in non-active state Drivers: hv: util: Fix a bug in the KVP code media: gspca_pac7302: Add new usb-id for Genius i-Look 317 usb: Check if port status is equal to RxDetect Signed-off-by: Ian Maund <imaund@codeaurora.org>
3858 lines
97 KiB
C
3858 lines
97 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/moduleloader.h>
|
|
#include <linux/ftrace_event.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/stop_machine.h>
|
|
#include <linux/device.h>
|
|
#include <linux/string.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/rculist.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/mmu_context.h>
|
|
#include <linux/license.h>
|
|
#include <asm/sections.h>
|
|
#include <linux/tracepoint.h>
|
|
#include <linux/ftrace.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/fips.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_DEBUG_SET_MODULE_RONX=y
|
|
*/
|
|
#ifdef CONFIG_DEBUG_SET_MODULE_RONX
|
|
# define debug_align(X) ALIGN(X, PAGE_SIZE)
|
|
#else
|
|
# define debug_align(X) (X)
|
|
#endif
|
|
|
|
/*
|
|
* Given BASE and SIZE this macro calculates the number of pages the
|
|
* memory regions occupies
|
|
*/
|
|
#define MOD_NUMBER_OF_PAGES(BASE, SIZE) (((SIZE) > 0) ? \
|
|
(PFN_DOWN((unsigned long)(BASE) + (SIZE) - 1) - \
|
|
PFN_DOWN((unsigned long)BASE) + 1) \
|
|
: (0UL))
|
|
|
|
/* 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 uses stop_machine/add uses RCU list operations). */
|
|
DEFINE_MUTEX(module_mutex);
|
|
EXPORT_SYMBOL_GPL(module_mutex);
|
|
static LIST_HEAD(modules);
|
|
#ifdef CONFIG_KGDB_KDB
|
|
struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
|
|
#endif /* CONFIG_KGDB_KDB */
|
|
|
|
#ifdef CONFIG_MODULE_SIG
|
|
#ifdef CONFIG_MODULE_SIG_FORCE
|
|
static bool sig_enforce = true;
|
|
#else
|
|
static bool sig_enforce = false;
|
|
|
|
static int param_set_bool_enable_only(const char *val,
|
|
const struct kernel_param *kp)
|
|
{
|
|
int err;
|
|
bool test;
|
|
struct kernel_param dummy_kp = *kp;
|
|
|
|
dummy_kp.arg = &test;
|
|
|
|
err = param_set_bool(val, &dummy_kp);
|
|
if (err)
|
|
return err;
|
|
|
|
/* Don't let them unset it once it's set! */
|
|
if (!test && sig_enforce)
|
|
return -EROFS;
|
|
|
|
if (test)
|
|
sig_enforce = true;
|
|
return 0;
|
|
}
|
|
|
|
static const struct kernel_param_ops param_ops_bool_enable_only = {
|
|
.set = param_set_bool_enable_only,
|
|
.get = param_get_bool,
|
|
};
|
|
#define param_check_bool_enable_only param_check_bool
|
|
|
|
module_param(sig_enforce, bool_enable_only, 0644);
|
|
#endif /* !CONFIG_MODULE_SIG_FORCE */
|
|
#endif /* CONFIG_MODULE_SIG */
|
|
|
|
/* 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);
|
|
|
|
/* Bounds of module allocation, for speeding __module_address.
|
|
* Protected by module_mutex. */
|
|
static unsigned long module_addr_min = -1UL, module_addr_max = 0;
|
|
|
|
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 {
|
|
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;
|
|
struct {
|
|
unsigned int sym, str, mod, vers, info, pcpu;
|
|
} index;
|
|
};
|
|
|
|
/* We require a truly strong try_module_get(): 0 means failure 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);
|
|
mod->taints |= (1U << flag);
|
|
}
|
|
|
|
/*
|
|
* 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 __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 unsigned long __start___kcrctab[];
|
|
extern const unsigned long __start___kcrctab_gpl[];
|
|
extern const unsigned long __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 unsigned long __start___kcrctab_unused[];
|
|
extern const unsigned long __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
|
|
};
|
|
|
|
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 unsigned long *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) {
|
|
printk(KERN_WARNING "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) {
|
|
printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
|
|
"however this module is using it.\n", fsa->name);
|
|
printk(KERN_WARNING
|
|
"This symbol will go away in the future.\n");
|
|
printk(KERN_WARNING
|
|
"Please evalute if this is the right api to use and if "
|
|
"it really is, submit a report the linux kernel "
|
|
"mailinglist 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 unsigned long **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. */
|
|
static struct module *find_module_all(const char *name,
|
|
bool even_unformed)
|
|
{
|
|
struct module *mod;
|
|
|
|
list_for_each_entry(mod, &modules, list) {
|
|
if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (strcmp(mod->name, name) == 0)
|
|
return mod;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
struct module *find_module(const char *name)
|
|
{
|
|
return find_module_all(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,
|
|
unsigned long size, unsigned long align)
|
|
{
|
|
if (align > PAGE_SIZE) {
|
|
printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
|
|
mod->name, align, PAGE_SIZE);
|
|
align = PAGE_SIZE;
|
|
}
|
|
|
|
mod->percpu = __alloc_reserved_percpu(size, align);
|
|
if (!mod->percpu) {
|
|
printk(KERN_WARNING
|
|
"%s: Could not allocate %lu bytes percpu data\n",
|
|
mod->name, size);
|
|
return -ENOMEM;
|
|
}
|
|
mod->percpu_size = 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);
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
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);
|
|
|
|
if ((void *)addr >= start &&
|
|
(void *)addr < start + mod->percpu_size) {
|
|
preempt_enable();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
preempt_enable();
|
|
return false;
|
|
}
|
|
|
|
#else /* ... !CONFIG_SMP */
|
|
|
|
static inline void __percpu *mod_percpu(struct module *mod)
|
|
{
|
|
return NULL;
|
|
}
|
|
static inline int percpu_modalloc(struct module *mod,
|
|
unsigned long size, unsigned long align)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
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;
|
|
}
|
|
|
|
#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 sprintf(buffer, "%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);
|
|
|
|
/* Init the unload section of the module. */
|
|
static int module_unload_init(struct module *mod)
|
|
{
|
|
mod->refptr = alloc_percpu(struct module_ref);
|
|
if (!mod->refptr)
|
|
return -ENOMEM;
|
|
|
|
INIT_LIST_HEAD(&mod->source_list);
|
|
INIT_LIST_HEAD(&mod->target_list);
|
|
|
|
/* Hold reference count during initialization. */
|
|
__this_cpu_write(mod->refptr->incs, 1);
|
|
/* Backwards compatibility macros put refcount during init. */
|
|
mod->waiter = current;
|
|
|
|
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) {
|
|
printk(KERN_WARNING "%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);
|
|
|
|
free_percpu(mod->refptr);
|
|
}
|
|
|
|
#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 */
|
|
|
|
struct stopref
|
|
{
|
|
struct module *mod;
|
|
int flags;
|
|
int *forced;
|
|
};
|
|
|
|
/* Whole machine is stopped with interrupts off when this runs. */
|
|
static int __try_stop_module(void *_sref)
|
|
{
|
|
struct stopref *sref = _sref;
|
|
|
|
/* If it's not unused, quit unless we're forcing. */
|
|
if (module_refcount(sref->mod) != 0) {
|
|
if (!(*sref->forced = try_force_unload(sref->flags)))
|
|
return -EWOULDBLOCK;
|
|
}
|
|
|
|
/* Mark it as dying. */
|
|
sref->mod->state = MODULE_STATE_GOING;
|
|
return 0;
|
|
}
|
|
|
|
static int try_stop_module(struct module *mod, int flags, int *forced)
|
|
{
|
|
if (flags & O_NONBLOCK) {
|
|
struct stopref sref = { mod, flags, forced };
|
|
|
|
return stop_machine(__try_stop_module, &sref, NULL);
|
|
} else {
|
|
/* We don't need to stop the machine for this. */
|
|
mod->state = MODULE_STATE_GOING;
|
|
synchronize_sched();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
unsigned long module_refcount(struct module *mod)
|
|
{
|
|
unsigned long incs = 0, decs = 0;
|
|
int cpu;
|
|
|
|
for_each_possible_cpu(cpu)
|
|
decs += per_cpu_ptr(mod->refptr, cpu)->decs;
|
|
/*
|
|
* ensure the incs are added up after the decs.
|
|
* module_put ensures incs are visible before decs with smp_wmb.
|
|
*
|
|
* This 2-count scheme avoids the situation where the refcount
|
|
* for CPU0 is read, then CPU0 increments the module refcount,
|
|
* then CPU1 drops that refcount, then the refcount for CPU1 is
|
|
* read. We would record a decrement but not its corresponding
|
|
* increment so we would see a low count (disaster).
|
|
*
|
|
* Rare situation? But module_refcount can be preempted, and we
|
|
* might be tallying up 4096+ CPUs. So it is not impossible.
|
|
*/
|
|
smp_rmb();
|
|
for_each_possible_cpu(cpu)
|
|
incs += per_cpu_ptr(mod->refptr, cpu)->incs;
|
|
return incs - decs;
|
|
}
|
|
EXPORT_SYMBOL(module_refcount);
|
|
|
|
/* This exists whether we can unload or not */
|
|
static void free_module(struct module *mod);
|
|
|
|
static void wait_for_zero_refcount(struct module *mod)
|
|
{
|
|
/* Since we might sleep for some time, release the mutex first */
|
|
mutex_unlock(&module_mutex);
|
|
for (;;) {
|
|
pr_debug("Looking at refcount...\n");
|
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
|
if (module_refcount(mod) == 0)
|
|
break;
|
|
schedule();
|
|
}
|
|
current->state = TASK_RUNNING;
|
|
mutex_lock(&module_mutex);
|
|
}
|
|
|
|
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';
|
|
|
|
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 and wake up
|
|
waiter --RR */
|
|
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;
|
|
}
|
|
}
|
|
|
|
/* Set this up before setting mod->state */
|
|
mod->waiter = current;
|
|
|
|
/* Stop the machine so refcounts can't move and disable module. */
|
|
ret = try_stop_module(mod, flags, &forced);
|
|
if (ret != 0)
|
|
goto out;
|
|
|
|
/* Never wait if forced. */
|
|
if (!forced && module_refcount(mod) != 0)
|
|
wait_for_zero_refcount(mod);
|
|
|
|
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);
|
|
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);
|
|
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, " %lu ", 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_printf(m, "[permanent],");
|
|
}
|
|
|
|
if (!printed_something)
|
|
seq_printf(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;
|
|
|
|
/* module_text_address is safe here: we're supposed to have reference
|
|
* to module from symbol_get, so it can't go away. */
|
|
modaddr = __module_text_address(a);
|
|
BUG_ON(!modaddr);
|
|
module_put(modaddr);
|
|
}
|
|
EXPORT_SYMBOL_GPL(symbol_put_addr);
|
|
|
|
static ssize_t show_refcnt(struct module_attribute *mattr,
|
|
struct module_kobject *mk, char *buffer)
|
|
{
|
|
return sprintf(buffer, "%lu\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();
|
|
__this_cpu_inc(module->refptr->incs);
|
|
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();
|
|
|
|
if (likely(module_is_live(module))) {
|
|
__this_cpu_inc(module->refptr->incs);
|
|
trace_module_get(module, _RET_IP_);
|
|
} else
|
|
ret = false;
|
|
|
|
preempt_enable();
|
|
}
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(try_module_get);
|
|
|
|
void module_put(struct module *module)
|
|
{
|
|
if (module) {
|
|
preempt_disable();
|
|
smp_wmb(); /* see comment in module_refcount */
|
|
__this_cpu_inc(module->refptr->decs);
|
|
|
|
trace_module_put(module, _RET_IP_);
|
|
/* Maybe they're waiting for us to drop reference? */
|
|
if (unlikely(!module_is_live(module)))
|
|
wake_up_process(module->waiter);
|
|
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_printf(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;
|
|
|
|
if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
|
|
buf[l++] = 'P';
|
|
if (mod->taints & (1 << TAINT_OOT_MODULE))
|
|
buf[l++] = 'O';
|
|
if (mod->taints & (1 << TAINT_FORCED_MODULE))
|
|
buf[l++] = 'F';
|
|
if (mod->taints & (1 << TAINT_CRAP))
|
|
buf[l++] = 'C';
|
|
/*
|
|
* TAINT_FORCED_RMMOD: could be added.
|
|
* TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
|
|
* apply to modules.
|
|
*/
|
|
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)
|
|
{
|
|
enum kobject_action action;
|
|
|
|
if (kobject_action_type(buffer, count, &action) == 0)
|
|
kobject_uevent(&mk->kobj, action);
|
|
return 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_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_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))
|
|
printk(KERN_WARNING "%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
|
|
/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */
|
|
static unsigned long maybe_relocated(unsigned long crc,
|
|
const struct module *crc_owner)
|
|
{
|
|
#ifdef ARCH_RELOCATES_KCRCTAB
|
|
if (crc_owner == NULL)
|
|
return crc - (unsigned long)reloc_start;
|
|
#endif
|
|
return crc;
|
|
}
|
|
|
|
static int check_version(Elf_Shdr *sechdrs,
|
|
unsigned int versindex,
|
|
const char *symname,
|
|
struct module *mod,
|
|
const unsigned long *crc,
|
|
const struct module *crc_owner)
|
|
{
|
|
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++) {
|
|
if (strcmp(versions[i].name, symname) != 0)
|
|
continue;
|
|
|
|
if (versions[i].crc == maybe_relocated(*crc, crc_owner))
|
|
return 1;
|
|
pr_debug("Found checksum %lX vs module %lX\n",
|
|
maybe_relocated(*crc, crc_owner), versions[i].crc);
|
|
goto bad_version;
|
|
}
|
|
|
|
printk(KERN_WARNING "%s: no symbol version for %s\n",
|
|
mod->name, symname);
|
|
return 0;
|
|
|
|
bad_version:
|
|
printk("%s: disagrees about version of symbol %s\n",
|
|
mod->name, symname);
|
|
return 0;
|
|
}
|
|
|
|
static inline int check_modstruct_version(Elf_Shdr *sechdrs,
|
|
unsigned int versindex,
|
|
struct module *mod)
|
|
{
|
|
const unsigned long *crc;
|
|
|
|
/* Since this should be found in kernel (which can't be removed),
|
|
* no locking is necessary. */
|
|
if (!find_symbol(VMLINUX_SYMBOL_STR(module_layout), NULL,
|
|
&crc, true, false))
|
|
BUG();
|
|
return check_version(sechdrs, versindex,
|
|
VMLINUX_SYMBOL_STR(module_layout), mod, crc,
|
|
NULL);
|
|
}
|
|
|
|
/* 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(Elf_Shdr *sechdrs,
|
|
unsigned int versindex,
|
|
const char *symname,
|
|
struct module *mod,
|
|
const unsigned long *crc,
|
|
const struct module *crc_owner)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static inline int check_modstruct_version(Elf_Shdr *sechdrs,
|
|
unsigned int versindex,
|
|
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 unsigned long *crc;
|
|
int err;
|
|
|
|
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->sechdrs, info->index.vers, name, mod, crc,
|
|
owner)) {
|
|
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) {
|
|
printk(KERN_WARNING "%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 add_usage_links(struct module *mod)
|
|
{
|
|
#ifdef CONFIG_MODULE_UNLOAD
|
|
struct module_use *use;
|
|
int nowarn;
|
|
|
|
mutex_lock(&module_mutex);
|
|
list_for_each_entry(use, &mod->target_list, target_list) {
|
|
nowarn = sysfs_create_link(use->target->holders_dir,
|
|
&mod->mkobj.kobj, mod->name);
|
|
}
|
|
mutex_unlock(&module_mutex);
|
|
#endif
|
|
}
|
|
|
|
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 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]) && !error; i++) {
|
|
if (!attr->test ||
|
|
(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);
|
|
++temp_attr;
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
|
|
static void module_remove_modinfo_attrs(struct module *mod)
|
|
{
|
|
struct module_attribute *attr;
|
|
int i;
|
|
|
|
for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
|
|
/* 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 int mod_sysfs_init(struct module *mod)
|
|
{
|
|
int err;
|
|
struct kobject *kobj;
|
|
|
|
if (!module_sysfs_initialized) {
|
|
printk(KERN_ERR "%s: module sysfs not initialized\n",
|
|
mod->name);
|
|
err = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
kobj = kset_find_obj(module_kset, mod->name);
|
|
if (kobj) {
|
|
printk(KERN_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)
|
|
kobject_put(&mod->mkobj.kobj);
|
|
|
|
/* 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;
|
|
|
|
add_usage_links(mod);
|
|
add_sect_attrs(mod, info);
|
|
add_notes_attrs(mod, info);
|
|
|
|
kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
|
|
return 0;
|
|
|
|
out_unreg_param:
|
|
module_param_sysfs_remove(mod);
|
|
out_unreg_holders:
|
|
kobject_put(mod->holders_dir);
|
|
out_unreg:
|
|
kobject_put(&mod->mkobj.kobj);
|
|
out:
|
|
return err;
|
|
}
|
|
|
|
static void mod_sysfs_fini(struct module *mod)
|
|
{
|
|
remove_notes_attrs(mod);
|
|
remove_sect_attrs(mod);
|
|
kobject_put(&mod->mkobj.kobj);
|
|
}
|
|
|
|
#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)
|
|
{
|
|
}
|
|
|
|
static void del_usage_links(struct module *mod)
|
|
{
|
|
}
|
|
|
|
#endif /* CONFIG_SYSFS */
|
|
|
|
static void mod_sysfs_teardown(struct module *mod)
|
|
{
|
|
del_usage_links(mod);
|
|
module_remove_modinfo_attrs(mod);
|
|
module_param_sysfs_remove(mod);
|
|
kobject_put(mod->mkobj.drivers_dir);
|
|
kobject_put(mod->holders_dir);
|
|
mod_sysfs_fini(mod);
|
|
}
|
|
|
|
/*
|
|
* unlink the module with the whole machine is stopped with interrupts off
|
|
* - this defends against kallsyms not taking locks
|
|
*/
|
|
static int __unlink_module(void *_mod)
|
|
{
|
|
struct module *mod = _mod;
|
|
list_del(&mod->list);
|
|
module_bug_cleanup(mod);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_DEBUG_SET_MODULE_RONX
|
|
/*
|
|
* LKM RO/NX protection: protect module's text/ro-data
|
|
* from modification and any data from execution.
|
|
*/
|
|
void set_page_attributes(void *start, void *end, int (*set)(unsigned long start, int num_pages))
|
|
{
|
|
unsigned long begin_pfn = PFN_DOWN((unsigned long)start);
|
|
unsigned long end_pfn = PFN_DOWN((unsigned long)end);
|
|
|
|
if (end_pfn > begin_pfn)
|
|
set(begin_pfn << PAGE_SHIFT, end_pfn - begin_pfn);
|
|
}
|
|
|
|
static void set_section_ro_nx(void *base,
|
|
unsigned long text_size,
|
|
unsigned long ro_size,
|
|
unsigned long total_size)
|
|
{
|
|
/* begin and end PFNs of the current subsection */
|
|
unsigned long begin_pfn;
|
|
unsigned long end_pfn;
|
|
|
|
/*
|
|
* Set RO for module text and RO-data:
|
|
* - Always protect first page.
|
|
* - Do not protect last partial page.
|
|
*/
|
|
if (ro_size > 0)
|
|
set_page_attributes(base, base + ro_size, set_memory_ro);
|
|
|
|
/*
|
|
* Set NX permissions for module data:
|
|
* - Do not protect first partial page.
|
|
* - Always protect last page.
|
|
*/
|
|
if (total_size > text_size) {
|
|
begin_pfn = PFN_UP((unsigned long)base + text_size);
|
|
end_pfn = PFN_UP((unsigned long)base + total_size);
|
|
if (end_pfn > begin_pfn)
|
|
set_memory_nx(begin_pfn << PAGE_SHIFT, end_pfn - begin_pfn);
|
|
}
|
|
}
|
|
|
|
static void unset_module_core_ro_nx(struct module *mod)
|
|
{
|
|
set_page_attributes(mod->module_core + mod->core_text_size,
|
|
mod->module_core + mod->core_size,
|
|
set_memory_x);
|
|
set_page_attributes(mod->module_core,
|
|
mod->module_core + mod->core_ro_size,
|
|
set_memory_rw);
|
|
}
|
|
|
|
static void unset_module_init_ro_nx(struct module *mod)
|
|
{
|
|
set_page_attributes(mod->module_init + mod->init_text_size,
|
|
mod->module_init + mod->init_size,
|
|
set_memory_x);
|
|
set_page_attributes(mod->module_init,
|
|
mod->module_init + mod->init_ro_size,
|
|
set_memory_rw);
|
|
}
|
|
|
|
/* Iterate through all modules and set each module's text as RW */
|
|
void set_all_modules_text_rw(void)
|
|
{
|
|
struct module *mod;
|
|
|
|
mutex_lock(&module_mutex);
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if ((mod->module_core) && (mod->core_text_size)) {
|
|
set_page_attributes(mod->module_core,
|
|
mod->module_core + mod->core_text_size,
|
|
set_memory_rw);
|
|
}
|
|
if ((mod->module_init) && (mod->init_text_size)) {
|
|
set_page_attributes(mod->module_init,
|
|
mod->module_init + mod->init_text_size,
|
|
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;
|
|
|
|
mutex_lock(&module_mutex);
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if ((mod->module_core) && (mod->core_text_size)) {
|
|
set_page_attributes(mod->module_core,
|
|
mod->module_core + mod->core_text_size,
|
|
set_memory_ro);
|
|
}
|
|
if ((mod->module_init) && (mod->init_text_size)) {
|
|
set_page_attributes(mod->module_init,
|
|
mod->module_init + mod->init_text_size,
|
|
set_memory_ro);
|
|
}
|
|
}
|
|
mutex_unlock(&module_mutex);
|
|
}
|
|
#else
|
|
static inline void set_section_ro_nx(void *base, unsigned long text_size, unsigned long ro_size, unsigned long total_size) { }
|
|
static void unset_module_core_ro_nx(struct module *mod) { }
|
|
static void unset_module_init_ro_nx(struct module *mod) { }
|
|
#endif
|
|
|
|
void __weak module_free(struct module *mod, void *module_region)
|
|
{
|
|
vfree(module_region);
|
|
}
|
|
|
|
void __weak module_arch_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);
|
|
|
|
/* Now we can delete it from the lists */
|
|
mutex_lock(&module_mutex);
|
|
stop_machine(__unlink_module, mod, NULL);
|
|
mutex_unlock(&module_mutex);
|
|
|
|
/* This may be NULL, but that's OK */
|
|
unset_module_init_ro_nx(mod);
|
|
module_free(mod, mod->module_init);
|
|
kfree(mod->args);
|
|
percpu_modfree(mod);
|
|
|
|
/* Free lock-classes: */
|
|
lockdep_free_key_range(mod->module_core, mod->core_size);
|
|
|
|
/* Finally, free the core (containing the module structure) */
|
|
unset_module_core_ro_nx(mod);
|
|
module_free(mod, mod->module_core);
|
|
|
|
#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)) {
|
|
printk(KERN_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:
|
|
/* We compiled with -fno-common. These are not
|
|
supposed to happen. */
|
|
pr_debug("Common symbol: %s\n", name);
|
|
printk("%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_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;
|
|
|
|
printk(KERN_WARNING "%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;
|
|
|
|
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_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_size, s, i);
|
|
pr_debug("\t%s\n", sname);
|
|
}
|
|
switch (m) {
|
|
case 0: /* executable */
|
|
mod->core_size = debug_align(mod->core_size);
|
|
mod->core_text_size = mod->core_size;
|
|
break;
|
|
case 1: /* RO: text and ro-data */
|
|
mod->core_size = debug_align(mod->core_size);
|
|
mod->core_ro_size = mod->core_size;
|
|
break;
|
|
case 3: /* whole core */
|
|
mod->core_size = debug_align(mod->core_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_size, s, i)
|
|
| INIT_OFFSET_MASK);
|
|
pr_debug("\t%s\n", sname);
|
|
}
|
|
switch (m) {
|
|
case 0: /* executable */
|
|
mod->init_size = debug_align(mod->init_size);
|
|
mod->init_text_size = mod->init_size;
|
|
break;
|
|
case 1: /* RO: text and ro-data */
|
|
mod->init_size = debug_align(mod->init_size);
|
|
mod->init_ro_size = mod->init_size;
|
|
break;
|
|
case 3: /* whole init */
|
|
mod->init_size = debug_align(mod->init_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))
|
|
printk(KERN_WARNING "%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)
|
|
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)
|
|
{
|
|
const Elf_Shdr *sec;
|
|
|
|
if (src->st_shndx == SHN_UNDEF
|
|
|| src->st_shndx >= shnum
|
|
|| !src->st_name)
|
|
return false;
|
|
|
|
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_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_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
|
|
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_size, symsect->sh_addralign ?: 1);
|
|
info->stroffs = mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym);
|
|
mod->core_size += strtab_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_size, strsect,
|
|
info->index.str) | INIT_OFFSET_MASK;
|
|
pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
|
|
}
|
|
|
|
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];
|
|
|
|
mod->symtab = (void *)symsec->sh_addr;
|
|
mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
|
|
/* Make sure we get permanent strtab: don't use info->strtab. */
|
|
mod->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
|
|
|
|
/* Set types up while we still have access to sections. */
|
|
for (i = 0; i < mod->num_symtab; i++)
|
|
mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
|
|
|
|
mod->core_symtab = dst = mod->module_core + info->symoffs;
|
|
mod->core_strtab = s = mod->module_core + info->stroffs;
|
|
src = mod->symtab;
|
|
for (ndst = i = 0; i < mod->num_symtab; i++) {
|
|
if (i == 0 ||
|
|
is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
|
|
dst[ndst] = src[i];
|
|
dst[ndst++].st_name = s - mod->core_strtab;
|
|
s += strlcpy(s, &mod->strtab[src[i].st_name],
|
|
KSYM_NAME_LEN) + 1;
|
|
}
|
|
}
|
|
mod->core_num_syms = 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 _ddebug *debug, unsigned int num)
|
|
{
|
|
if (!debug)
|
|
return;
|
|
#ifdef CONFIG_DYNAMIC_DEBUG
|
|
if (ddebug_add_module(debug, num, debug->modname))
|
|
printk(KERN_ERR "dynamic debug error adding module: %s\n",
|
|
debug->modname);
|
|
#endif
|
|
}
|
|
|
|
static void dynamic_debug_remove(struct _ddebug *debug)
|
|
{
|
|
if (debug)
|
|
ddebug_remove_module(debug->modname);
|
|
}
|
|
|
|
void * __weak module_alloc(unsigned long size)
|
|
{
|
|
return vmalloc_exec(size);
|
|
}
|
|
|
|
static void *module_alloc_update_bounds(unsigned long size)
|
|
{
|
|
void *ret = module_alloc(size);
|
|
|
|
if (ret) {
|
|
mutex_lock(&module_mutex);
|
|
/* Update module bounds. */
|
|
if ((unsigned long)ret < module_addr_min)
|
|
module_addr_min = (unsigned long)ret;
|
|
if ((unsigned long)ret + size > module_addr_max)
|
|
module_addr_max = (unsigned long)ret + size;
|
|
mutex_unlock(&module_mutex);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#if defined(CONFIG_DEBUG_KMEMLEAK) && defined(CONFIG_DEBUG_MODULE_SCAN_OFF)
|
|
static void kmemleak_load_module(const struct module *mod,
|
|
const struct load_info *info)
|
|
{
|
|
kmemleak_no_scan(mod->module_core);
|
|
}
|
|
#elif defined(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 err = -ENOKEY;
|
|
const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
|
|
const void *mod = info->hdr;
|
|
|
|
if (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 < 0 && fips_enabled)
|
|
panic("Module verification failed with error %d in FIPS mode\n",
|
|
err);
|
|
if (err == -ENOKEY && !sig_enforce)
|
|
err = 0;
|
|
|
|
return err;
|
|
}
|
|
#else /* !CONFIG_MODULE_SIG */
|
|
static int module_sig_check(struct load_info *info)
|
|
{
|
|
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;
|
|
}
|
|
|
|
/* 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_module_from_file(NULL);
|
|
if (err)
|
|
return err;
|
|
|
|
/* Suck in entire file: we'll want most of it. */
|
|
info->hdr = vmalloc(info->len);
|
|
if (!info->hdr)
|
|
return -ENOMEM;
|
|
|
|
if (copy_from_user(info->hdr, umod, info->len) != 0) {
|
|
vfree(info->hdr);
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sets info->hdr and info->len. */
|
|
static int copy_module_from_fd(int fd, struct load_info *info)
|
|
{
|
|
struct file *file;
|
|
int err;
|
|
struct kstat stat;
|
|
loff_t pos;
|
|
ssize_t bytes = 0;
|
|
|
|
file = fget(fd);
|
|
if (!file)
|
|
return -ENOEXEC;
|
|
|
|
err = security_kernel_module_from_file(file);
|
|
if (err)
|
|
goto out;
|
|
|
|
err = vfs_getattr(&file->f_path, &stat);
|
|
if (err)
|
|
goto out;
|
|
|
|
if (stat.size > INT_MAX) {
|
|
err = -EFBIG;
|
|
goto out;
|
|
}
|
|
|
|
/* Don't hand 0 to vmalloc, it whines. */
|
|
if (stat.size == 0) {
|
|
err = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
info->hdr = vmalloc(stat.size);
|
|
if (!info->hdr) {
|
|
err = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
pos = 0;
|
|
while (pos < stat.size) {
|
|
bytes = kernel_read(file, pos, (char *)(info->hdr) + pos,
|
|
stat.size - pos);
|
|
if (bytes < 0) {
|
|
vfree(info->hdr);
|
|
err = bytes;
|
|
goto out;
|
|
}
|
|
if (bytes == 0)
|
|
break;
|
|
pos += bytes;
|
|
}
|
|
info->len = pos;
|
|
|
|
out:
|
|
fput(file);
|
|
return err;
|
|
}
|
|
|
|
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) {
|
|
printk(KERN_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->index.info = find_sec(info, ".modinfo");
|
|
info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
|
|
info->sechdrs[info->index.vers].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) {
|
|
printk(KERN_WARNING "No module found in object\n");
|
|
return ERR_PTR(-ENOEXEC);
|
|
}
|
|
/* This is temporary: point mod into copy of data. */
|
|
mod = (void *)info->sechdrs[info->index.mod].sh_addr;
|
|
|
|
if (info->index.sym == 0) {
|
|
printk(KERN_WARNING "%s: module has no symbols (stripped?)\n",
|
|
mod->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->sechdrs, info->index.vers, 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)) {
|
|
printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
|
|
mod->name, modmagic, vermagic);
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
if (!get_modinfo(info, "intree"))
|
|
add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);
|
|
|
|
if (get_modinfo(info, "staging")) {
|
|
add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK);
|
|
printk(KERN_WARNING "%s: module is from the staging directory,"
|
|
" the quality is unknown, you have been warned.\n",
|
|
mod->name);
|
|
}
|
|
|
|
/* Set up license info based on the info section */
|
|
set_license(mod, get_modinfo(info, "license"));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void 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);
|
|
#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);
|
|
#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"))
|
|
printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
|
|
mod->name);
|
|
|
|
info->debug = section_objs(info, "__verbose",
|
|
sizeof(*info->debug), &info->num_debug);
|
|
}
|
|
|
|
static int move_module(struct module *mod, struct load_info *info)
|
|
{
|
|
int i;
|
|
void *ptr;
|
|
|
|
/* Do the allocs. */
|
|
ptr = module_alloc_update_bounds(mod->core_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_size);
|
|
mod->module_core = ptr;
|
|
|
|
if (mod->init_size) {
|
|
ptr = module_alloc_update_bounds(mod->init_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_free(mod, mod->module_core);
|
|
return -ENOMEM;
|
|
}
|
|
memset(ptr, 0, mod->init_size);
|
|
mod->module_init = ptr;
|
|
} else
|
|
mod->module_init = 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->module_init
|
|
+ (shdr->sh_entsize & ~INIT_OFFSET_MASK);
|
|
else
|
|
dest = mod->module_core + 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)
|
|
{
|
|
/*
|
|
* 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);
|
|
|
|
#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->module_init)
|
|
flush_icache_range((unsigned long)mod->module_init,
|
|
(unsigned long)mod->module_init
|
|
+ mod->init_size);
|
|
flush_icache_range((unsigned long)mod->module_core,
|
|
(unsigned long)mod->module_core + mod->core_size);
|
|
|
|
set_fs(old_fs);
|
|
}
|
|
|
|
int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
|
|
Elf_Shdr *sechdrs,
|
|
char *secstrings,
|
|
struct module *mod)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static struct module *layout_and_allocate(struct load_info *info, int flags)
|
|
{
|
|
/* Module within temporary copy. */
|
|
struct module *mod;
|
|
int err;
|
|
|
|
mod = setup_load_info(info, flags);
|
|
if (IS_ERR(mod))
|
|
return mod;
|
|
|
|
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;
|
|
|
|
/* 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;
|
|
}
|
|
|
|
static int alloc_module_percpu(struct module *mod, struct load_info *info)
|
|
{
|
|
Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu];
|
|
if (!pcpusec->sh_size)
|
|
return 0;
|
|
|
|
/* We have a special allocation for this section. */
|
|
return percpu_modalloc(mod, pcpusec->sh_size, pcpusec->sh_addralign);
|
|
}
|
|
|
|
/* mod is no longer valid after this! */
|
|
static void module_deallocate(struct module *mod, struct load_info *info)
|
|
{
|
|
percpu_modfree(mod);
|
|
module_free(mod, mod->module_init);
|
|
module_free(mod, mod->module_core);
|
|
}
|
|
|
|
int __weak module_finalize(const Elf_Ehdr *hdr,
|
|
const Elf_Shdr *sechdrs,
|
|
struct module *me)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
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);
|
|
|
|
/* 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;
|
|
|
|
mutex_lock(&module_mutex);
|
|
mod = find_module_all(name, true);
|
|
ret = !mod || mod->state == MODULE_STATE_LIVE
|
|
|| mod->state == MODULE_STATE_GOING;
|
|
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
|
|
}
|
|
|
|
/* This is where the real work happens */
|
|
static int do_init_module(struct module *mod)
|
|
{
|
|
int ret = 0;
|
|
|
|
/*
|
|
* 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;
|
|
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
MODULE_STATE_COMING, mod);
|
|
|
|
/* Set RO and NX regions for core */
|
|
set_section_ro_nx(mod->module_core,
|
|
mod->core_text_size,
|
|
mod->core_ro_size,
|
|
mod->core_size);
|
|
|
|
/* Set RO and NX regions for init */
|
|
set_section_ro_nx(mod->module_init,
|
|
mod->init_text_size,
|
|
mod->init_ro_size,
|
|
mod->init_size);
|
|
|
|
do_mod_ctors(mod);
|
|
/* Start the module */
|
|
if (mod->init != NULL)
|
|
ret = do_one_initcall(mod->init);
|
|
if (ret < 0) {
|
|
/* Init routine failed: abort. 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);
|
|
free_module(mod);
|
|
wake_up_all(&module_wq);
|
|
return ret;
|
|
}
|
|
if (ret > 0) {
|
|
printk(KERN_WARNING
|
|
"%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 (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
|
|
mod->num_symtab = mod->core_num_syms;
|
|
mod->symtab = mod->core_symtab;
|
|
mod->strtab = mod->core_strtab;
|
|
#endif
|
|
unset_module_init_ro_nx(mod);
|
|
module_free(mod, mod->module_init);
|
|
mod->module_init = NULL;
|
|
mod->init_size = 0;
|
|
mod->init_ro_size = 0;
|
|
mod->init_text_size = 0;
|
|
mutex_unlock(&module_mutex);
|
|
wake_up_all(&module_wq);
|
|
|
|
return 0;
|
|
}
|
|
|
|
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);
|
|
if ((old = find_module_all(mod->name, true)) != NULL) {
|
|
if (old->state == MODULE_STATE_COMING
|
|
|| old->state == MODULE_STATE_UNFORMED) {
|
|
/* 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;
|
|
}
|
|
list_add_rcu(&mod->list, &modules);
|
|
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);
|
|
|
|
/* Mark state as coming so strong_try_module_get() ignores us,
|
|
* but kallsyms etc. can see us. */
|
|
mod->state = MODULE_STATE_COMING;
|
|
|
|
out:
|
|
mutex_unlock(&module_mutex);
|
|
return err;
|
|
}
|
|
|
|
/* 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;
|
|
|
|
err = module_sig_check(info);
|
|
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;
|
|
}
|
|
|
|
/* 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) {
|
|
printk_once(KERN_NOTICE
|
|
"%s: module verification failed: signature and/or"
|
|
" required key missing - tainting kernel\n",
|
|
mod->name);
|
|
add_taint_module(mod, TAINT_FORCED_MODULE, LOCKDEP_STILL_OK);
|
|
}
|
|
#endif
|
|
|
|
/* To avoid stressing percpu allocator, do this once we're unique. */
|
|
err = alloc_module_percpu(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;
|
|
|
|
/* Now we've got everything in the final locations, we can
|
|
* find optional sections. */
|
|
find_module_sections(mod, info);
|
|
|
|
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(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;
|
|
|
|
/* Module is ready to execute: parsing args may do that. */
|
|
err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
|
|
-32768, 32767, &ddebug_dyndbg_module_param_cb);
|
|
if (err < 0)
|
|
goto bug_cleanup;
|
|
|
|
/* Link in to syfs. */
|
|
err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
|
|
if (err < 0)
|
|
goto bug_cleanup;
|
|
|
|
/* Get rid of temporary copy. */
|
|
free_copy(info);
|
|
|
|
/* Done! */
|
|
trace_module_load(mod);
|
|
|
|
return do_init_module(mod);
|
|
|
|
bug_cleanup:
|
|
/* module_bug_cleanup needs module_mutex protection */
|
|
mutex_lock(&module_mutex);
|
|
module_bug_cleanup(mod);
|
|
mutex_unlock(&module_mutex);
|
|
ddebug_cleanup:
|
|
dynamic_debug_remove(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);
|
|
wake_up_all(&module_wq);
|
|
mutex_unlock(&module_mutex);
|
|
free_module:
|
|
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)
|
|
{
|
|
int err;
|
|
struct load_info info = { };
|
|
|
|
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 = copy_module_from_fd(fd, &info);
|
|
if (err)
|
|
return err;
|
|
|
|
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)
|
|
{
|
|
return str[0] == '$' && strchr("atd", str[1])
|
|
&& (str[2] == '\0' || str[2] == '.');
|
|
}
|
|
|
|
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;
|
|
|
|
/* At worse, next value is at end of module */
|
|
if (within_module_init(addr, mod))
|
|
nextval = (unsigned long)mod->module_init+mod->init_text_size;
|
|
else
|
|
nextval = (unsigned long)mod->module_core+mod->core_text_size;
|
|
|
|
/* Scan for closest preceding symbol, and next symbol. (ELF
|
|
starts real symbols at 1). */
|
|
for (i = 1; i < mod->num_symtab; i++) {
|
|
if (mod->symtab[i].st_shndx == SHN_UNDEF)
|
|
continue;
|
|
|
|
/* We ignore unnamed symbols: they're uninformative
|
|
* and inserted at a whim. */
|
|
if (mod->symtab[i].st_value <= addr
|
|
&& mod->symtab[i].st_value > mod->symtab[best].st_value
|
|
&& *(mod->strtab + mod->symtab[i].st_name) != '\0'
|
|
&& !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
|
|
best = i;
|
|
if (mod->symtab[i].st_value > addr
|
|
&& mod->symtab[i].st_value < nextval
|
|
&& *(mod->strtab + mod->symtab[i].st_name) != '\0'
|
|
&& !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
|
|
nextval = mod->symtab[i].st_value;
|
|
}
|
|
|
|
if (!best)
|
|
return NULL;
|
|
|
|
if (size)
|
|
*size = nextval - mod->symtab[best].st_value;
|
|
if (offset)
|
|
*offset = addr - mod->symtab[best].st_value;
|
|
return mod->strtab + mod->symtab[best].st_name;
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
struct module *mod;
|
|
const char *ret = NULL;
|
|
|
|
preempt_disable();
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (within_module_init(addr, mod) ||
|
|
within_module_core(addr, mod)) {
|
|
if (modname)
|
|
*modname = mod->name;
|
|
ret = get_ksymbol(mod, addr, size, offset);
|
|
break;
|
|
}
|
|
}
|
|
/* 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_init(addr, mod) ||
|
|
within_module_core(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_init(addr, mod) ||
|
|
within_module_core(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) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (symnum < mod->num_symtab) {
|
|
*value = mod->symtab[symnum].st_value;
|
|
*type = mod->symtab[symnum].st_info;
|
|
strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
|
|
KSYM_NAME_LEN);
|
|
strlcpy(module_name, mod->name, MODULE_NAME_LEN);
|
|
*exported = is_exported(name, *value, mod);
|
|
preempt_enable();
|
|
return 0;
|
|
}
|
|
symnum -= mod->num_symtab;
|
|
}
|
|
preempt_enable();
|
|
return -ERANGE;
|
|
}
|
|
|
|
static unsigned long mod_find_symname(struct module *mod, const char *name)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < mod->num_symtab; i++)
|
|
if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0 &&
|
|
mod->symtab[i].st_info != 'U')
|
|
return mod->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 = strchr(name, ':')) != NULL) {
|
|
*colon = '\0';
|
|
if ((mod = find_module(name)) != NULL)
|
|
ret = mod_find_symname(mod, colon+1);
|
|
*colon = ':';
|
|
} 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;
|
|
|
|
list_for_each_entry(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
for (i = 0; i < mod->num_symtab; i++) {
|
|
ret = fn(data, mod->strtab + mod->symtab[i].st_name,
|
|
mod, mod->symtab[i].st_value);
|
|
if (ret != 0)
|
|
return ret;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_KALLSYMS */
|
|
|
|
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[8];
|
|
|
|
/* We always ignore unformed modules. */
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
return 0;
|
|
|
|
seq_printf(m, "%s %u",
|
|
mod->name, mod->init_size + mod->core_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->module_core);
|
|
|
|
/* Taints info */
|
|
if (mod->taints)
|
|
seq_printf(m, " %s", module_flags(mod, buf));
|
|
|
|
seq_printf(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();
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (mod->num_exentries == 0)
|
|
continue;
|
|
|
|
e = search_extable(mod->extable,
|
|
mod->extable + mod->num_exentries - 1,
|
|
addr);
|
|
if (e)
|
|
break;
|
|
}
|
|
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;
|
|
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
if (within_module_core(addr, mod)
|
|
|| within_module_init(addr, mod))
|
|
return mod;
|
|
}
|
|
return NULL;
|
|
}
|
|
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->module_init, mod->init_text_size)
|
|
&& !within(addr, mod->module_core, mod->core_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[8];
|
|
|
|
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;
|
|
printk(" %s%s", mod->name, module_flags(mod, buf));
|
|
}
|
|
preempt_enable();
|
|
if (last_unloaded_module[0])
|
|
printk(" [last unloaded: %s]", last_unloaded_module);
|
|
printk("\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
|