msm-4.14/lib/test_kasan.c
Srinivasarao P 5f43935f7f Merge android-4.14.171 (998aa7d) into msm-4.14
* refs/heads/tmp-998aa7d:
  Reverting crypto and incrementalfs changes
  ANDROID: cuttlefish_defconfig: Enable CONFIG_NET_NS
  ANDROID: virtio: virtio_input: pass _DIRECT only if the device advertises _DIRECT
  ANDROID: net: bpf: Allow TC programs to call BPF_FUNC_skb_change_head
  ANDROID: Add INIT_STACK_ALL to the list of Clang-specific options
  Linux 4.14.171
  libertas: make lbs_ibss_join_existing() return error code on rates overflow
  libertas: don't exit from lbs_ibss_join_existing() with RCU read lock held
  mwifiex: Fix possible buffer overflows in mwifiex_cmd_append_vsie_tlv()
  mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status()
  serial: uartps: Move the spinlock after the read of the tx empty
  dm: fix potential for q->make_request_fn NULL pointer
  scsi: megaraid_sas: Do not initiate OCR if controller is not in ready state
  pinctrl: sh-pfc: r8a7778: Fix duplicate SDSELF_B and SD1_CLK_B
  media: i2c: adv748x: Fix unsafe macros
  crypto: atmel-sha - fix error handling when setting hmac key
  crypto: artpec6 - return correct error code for failed setkey()
  KVM: arm/arm64: Fix young bit from mmu notifier
  arm64: cpufeature: Fix the type of no FP/SIMD capability
  ARM: 8949/1: mm: mark free_memmap as __init
  KVM: arm/arm64: vgic-its: Fix restoration of unmapped collections
  powerpc/pseries: Allow not having ibm, hypertas-functions::hcall-multi-tce for DDW
  powerpc/pseries/vio: Fix iommu_table use-after-free refcount warning
  tools/power/acpi: fix compilation error
  ARM: dts: at91: sama5d3: define clock rate range for tcb1
  ARM: dts: at91: sama5d3: fix maximum peripheral clock rates
  platform/x86: intel_mid_powerbtn: Take a copy of ddata
  ARC: [plat-axs10x]: Add missing multicast filter number to GMAC node
  rtc: cmos: Stop using shared IRQ
  rtc: hym8563: Return -EINVAL if the time is known to be invalid
  serial: uartps: Add a timeout to the tx empty wait
  NFSv4: try lease recovery on NFS4ERR_EXPIRED
  NFS/pnfs: Fix pnfs_generic_prepare_to_resend_writes()
  nfs: NFS_SWAP should depend on SWAP
  PCI: Don't disable bridge BARs when assigning bus resources
  PCI/switchtec: Fix vep_vector_number ioread width
  scsi: ufs: Fix ufshcd_probe_hba() reture value in case ufshcd_scsi_add_wlus() fails
  RDMA/netlink: Do not always generate an ACK for some netlink operations
  hv_sock: Remove the accept port restriction
  ASoC: pcm: update FE/BE trigger order based on the command
  rxrpc: Fix service call disconnection
  perf/core: Fix mlock accounting in perf_mmap()
  clocksource: Prevent double add_timer_on() for watchdog_timer
  cifs: fail i/o on soft mounts if sessionsetup errors out
  KVM: s390: do not clobber registers during guest reset/store status
  KVM: Play nice with read-only memslots when querying host page size
  KVM: Use vcpu-specific gva->hva translation when querying host page size
  KVM: nVMX: vmread should not set rflags to specify success in case of #PF
  KVM: VMX: Add non-canonical check on writes to RTIT address MSRs
  KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM
  KVM: x86: Fix potential put_fpu() w/o load_fpu() on MPX platform
  btrfs: flush write bio if we loop in extent_write_cache_pages
  KVM: x86: Protect pmu_intel.c from Spectre-v1/L1TF attacks
  drm: atmel-hlcdc: enable clock before configuring timing engine
  Btrfs: fix race between adding and putting tree mod seq elements and nodes
  btrfs: remove trivial locking wrappers of tree mod log
  btrfs: free block groups after free'ing fs trees
  btrfs: use bool argument in free_root_pointers()
  Btrfs: fix missing hole after hole punching and fsync when using NO_HOLES
  Btrfs: fix assertion failure on fsync with NO_HOLES enabled
  btrfs: Get rid of the confusing btrfs_file_extent_inline_len
  ext4: fix deadlock allocating crypto bounce page from mempool
  bonding/alb: properly access headers in bond_alb_xmit()
  net: macb: Limit maximum GEM TX length in TSO
  net: macb: Remove unnecessary alignment check for TSO
  net: systemport: Avoid RBUF stuck in Wake-on-LAN mode
  net_sched: fix a resource leak in tcindex_set_parms()
  net: dsa: bcm_sf2: Only 7278 supports 2Gb/sec IMP port
  mfd: rn5t618: Mark ADC control register volatile
  mfd: da9062: Fix watchdog compatible string
  ubi: Fix an error pointer dereference in error handling code
  ubi: fastmap: Fix inverted logic in seen selfcheck
  nfsd: fix jiffies/time_t mixup in LRU list
  nfsd: fix delay timer on 32-bit architectures
  IB/core: Fix ODP get user pages flow
  IB/mlx5: Fix outstanding_pi index for GSI qps
  net: tulip: Adjust indentation in {dmfe, uli526x}_init_module
  net: smc911x: Adjust indentation in smc911x_phy_configure
  ppp: Adjust indentation into ppp_async_input
  NFC: pn544: Adjust indentation in pn544_hci_check_presence
  powerpc/44x: Adjust indentation in ibm4xx_denali_fixup_memsize
  ext2: Adjust indentation in ext2_fill_super
  phy: qualcomm: Adjust indentation in read_poll_timeout
  scsi: ufs: Recheck bkops level if bkops is disabled
  scsi: qla4xxx: Adjust indentation in qla4xxx_mem_free
  scsi: csiostor: Adjust indentation in csio_device_reset
  scsi: qla2xxx: Fix the endianness of the qla82xx_get_fw_size() return type
  clk: tegra: Mark fuse clock as critical
  KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails
  KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
  KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
  KVM: x86: Protect MSR-based index computations in fixed_msr_to_seg_unit() from Spectre-v1/L1TF attacks
  KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
  KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c
  KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
  KVM: x86: Protect MSR-based index computations in pmu.h from Spectre-v1/L1TF attacks
  KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
  KVM: x86: Protect kvm_hv_msr_[get|set]_crash_data() from Spectre-v1/L1TF attacks
  KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
  KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks
  KVM: x86: Refactor prefix decoding to prevent Spectre-v1/L1TF attacks
  KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
  xen/balloon: Support xend-based toolstack take two
  tools/kvm_stat: Fix kvm_exit filter name
  sunrpc: expiry_time should be seconds not timeval
  mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
  iwlwifi: don't throw error when trying to remove IGTK
  ARM: tegra: Enable PLLP bypass during Tegra124 LP1
  btrfs: set trans->drity in btrfs_commit_transaction
  NFS: Directory page cache pages need to be locked when read
  NFS: Fix memory leaks and corruption in readdir
  scsi: qla2xxx: Fix unbound NVME response length
  crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill
  crypto: api - Fix race condition in crypto_spawn_alg
  crypto: atmel-aes - Fix counter overflow in CTR mode
  crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
  crypto: ccp - set max RSA modulus size for v3 platform devices as well
  samples/bpf: Don't try to remove user's homedir on clean
  ftrace: Protect ftrace_graph_hash with ftrace_sync
  ftrace: Add comment to why rcu_dereference_sched() is open coded
  tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu
  tracing: Annotate ftrace_graph_hash pointer with __rcu
  dm crypt: fix benbi IV constructor crash if used in authenticated mode
  dm space map common: fix to ensure new block isn't already in use
  dm zoned: support zone sizes smaller than 128MiB
  of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
  PM: core: Fix handling of devices deleted during system-wide resume
  f2fs: code cleanup for f2fs_statfs_project()
  f2fs: fix miscounted block limit in f2fs_statfs_project()
  f2fs: choose hardlimit when softlimit is larger than hardlimit in f2fs_statfs_project()
  power: supply: ltc2941-battery-gauge: fix use-after-free
  scsi: qla2xxx: Fix mtcp dump collection failure
  crypto: api - Check spawn->alg under lock in crypto_drop_spawn
  hv_balloon: Balloon up according to request page number
  ubifs: don't trigger assertion on invalid no-key filename
  mmc: sdhci-of-at91: fix memleak on clk_get failure
  PCI: keystone: Fix link training retries initiation
  ubifs: Fix deadlock in concurrent bulk-read and writepage
  ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
  ubifs: Reject unsupported ioctl flags explicitly
  alarmtimer: Unregister wakeup source when module get fails
  ACPI: video: Do not export a non working backlight interface on MSI MS-7721 boards
  mmc: spi: Toggle SPI polarity, do not hardcode it
  powerpc/pseries: Advance pfn if section is not present in lmb_is_removable()
  powerpc/xmon: don't access ASDR in VMs
  s390/mm: fix dynamic pagetable upgrade for hugetlbfs
  MIPS: fix indentation of the 'RELOCS' message
  KVM: arm64: Only sign-extend MMIO up to register width
  platform/x86: intel_scu_ipc: Fix interrupt support
  irqdomain: Fix a memory leak in irq_domain_push_irq()
  lib/test_kasan.c: fix memory leak in kmalloc_oob_krealloc_more()
  media: v4l2-rect.h: fix v4l2_rect_map_inside() top/left adjustments
  media/v4l2-core: set pages dirty upon releasing DMA buffers
  ALSA: dummy: Fix PCM format loop in proc output
  usb: gadget: f_ecm: Use atomic_t to track in-flight request
  usb: gadget: f_ncm: Use atomic_t to track in-flight request
  usb: gadget: legacy: set max_speed to super-speed
  brcmfmac: Fix memory leak in brcmf_usbdev_qinit
  tracing: Fix sched switch start/stop refcount racy updates
  mfd: dln2: More sanity checking for endpoints
  media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors
  rxrpc: Fix NULL pointer deref due to call->conn being cleared on disconnect
  rxrpc: Fix insufficient receive notification generation
  tcp: clear tp->segs_{in|out} in tcp_disconnect()
  tcp: clear tp->data_segs{in|out} in tcp_disconnect()
  tcp: clear tp->delivered in tcp_disconnect()
  tcp: clear tp->total_retrans in tcp_disconnect()
  bnxt_en: Fix TC queue mapping.
  net_sched: fix an OOB access in cls_tcindex
  net: hsr: fix possible NULL deref in hsr_handle_frame()
  l2tp: Allow duplicate session creation with UDP
  gtp: use __GFP_NOWARN to avoid memalloc warning
  cls_rsvp: fix rsvp_policy
  sparc32: fix struct ipc64_perm type definition
  iwlwifi: mvm: fix NVM check for 3168 devices
  x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR
  media: iguanair: fix endpoint sanity check
  kernel/module: Fix memleak in module_add_modinfo_attrs()
  ANDROID: make memory initialization tests panic on failure
  ANDROID: added memory initialization tests to cuttlefish config
  UPSTREAM: lib/test_stackinit: Handle Clang auto-initialization pattern
  UPSTREAM: lib: Introduce test_stackinit module
  FROMLIST: rename missed uaccess .fixup section
  ANDROID: cuttlefish_defconfig: enable heap and stack initialization.
  ANDROID: f2fs: fix missing blk-crypto changes
  ANDROID: update x86_64_cuttlefish_defconfig
  BACKPORT: tracing: Remove unnecessary DEBUG_FS dependency
  BACKPORT: debugfs: Fix !DEBUG_FS debugfs_create_automount
  UPSTREAM: dynamic_debug: allow to work if debugfs is disabled
  UPSTREAM: lib: dynamic_debug: no need to check return value of debugfs_create functions
  ANDROID: f2fs: fix build error on PAGE_KERNEL_RO
  ANDROID: Revert "ANDROID: gki_defconfig: removed CONFIG_PM_WAKELOCKS"
  ANDROID: Set CONFIG_ANDROID_BINDERFS=y
  ANDROID: dm: prevent default-key from being enabled without needed hooks
  ANDROID: cf: disable virtio crypto
  ANDROID: Incremental fs: Fix initialization, use of bitfields
  ANDROID: cuttlefish_defconfig: enable dm-default-key
  ANDROID: dm: add dm-default-key target for metadata encryption
  ANDROID: dm: enable may_passthrough_inline_crypto on some targets
  ANDROID: dm: add support for passing through inline crypto support
  ANDROID: block: Introduce passthrough keyslot manager
  ANDROID: ext4, f2fs: enable direct I/O with inline encryption
  BACKPORT: FROMLIST: scsi: ufs: add program_key() variant op
  ANDROID: block: export symbols needed for modules to use inline crypto
  ANDROID: block: fix some inline crypto bugs
  ANDROID: fscrypt: add support for hardware-wrapped keys
  ANDROID: block: add KSM op to derive software secret from wrapped key
  ANDROID: block: provide key size as input to inline crypto APIs
  ANDROID: ufshcd-crypto: export cap find API
  ANDROID: scsi: ufs-qcom: Enable BROKEN_CRYPTO quirk flag
  ANDROID: scsi: ufs: Add quirk bit for controllers that don't play well with inline crypto
  ANDROID: cuttlefish_defconfig: Enable blk-crypto fallback
  BACKPORT: FROMLIST: Update Inline Encryption from v5 to v6 of patch series
  ANDROID: scsi: ufs: UFS init should not require inline crypto
  ANDROID: scsi: ufs: UFS crypto variant operations API
  ANDROID: cuttlefish_defconfig: enable inline encryption
  BACKPORT: FROMLIST: ext4: add inline encryption support
  BACKPORT: FROMLIST: f2fs: add inline encryption support
  BACKPORT: FROMLIST: fscrypt: add inline encryption support
  BACKPORT: FROMLIST: scsi: ufs: Add inline encryption support to UFS
  BACKPORT: FROMLIST: scsi: ufs: UFS crypto API
  BACKPORT: FROMLIST: scsi: ufs: UFS driver v2.1 spec crypto additions
  BACKPORT: FROMLIST: block: blk-crypto for Inline Encryption
  ANDROID: block: Fix bio_crypt_should_process WARN_ON
  BACKPORT: FROMLIST: block: Add encryption context to struct bio
  BACKPORT: FROMLIST: block: Keyslot Manager for Inline Encryption
  BACKPORT: atomic: Add irqsave variant of atomic_dec_and_lock()
  ANDROID: Incremental fs: Fix crash on failed lookup
  ANDROID: Incremental fs: Make files writeable
  ANDROID: Incremental fs: Remove C++-style comments
  f2fs: fix race conditions in ->d_compare() and ->d_hash()
  f2fs: fix dcache lookup of !casefolded directories
  f2fs: Add f2fs stats to sysfs
  f2fs: delete duplicate information on sysfs nodes
  f2fs: change to use rwsem for gc_mutex
  f2fs: update f2fs document regarding to fsync_mode
  f2fs: add a way to turn off ipu bio cache
  f2fs: code cleanup for f2fs_statfs_project()
  f2fs: fix miscounted block limit in f2fs_statfs_project()
  f2fs: show the CP_PAUSE reason in checkpoint traces
  f2fs: fix deadlock allocating bio_post_read_ctx from mempool
  f2fs: remove unneeded check for error allocating bio_post_read_ctx
  f2fs: convert inline_dir early before starting rename
  f2fs: fix memleak of kobject
  f2fs: fix to add swap extent correctly
  mm: export add_swap_extent()
  f2fs: run fsck when getting bad inode during GC
  f2fs: support data compression
  f2fs: free sysfs kobject
  f2fs: declare nested quota_sem and remove unnecessary sems
  mm: kvmalloc does not fallback to vmalloc for incompatible gfp flags
  f2fs: don't put new_page twice in f2fs_rename
  f2fs: set I_LINKABLE early to avoid wrong access by vfs
  f2fs: don't keep META_MAPPING pages used for moving verity file blocks
  f2fs: introduce private bioset
  f2fs: cleanup duplicate stats for atomic files
  f2fs: set GFP_NOFS when moving inline dentries
  f2fs: should avoid recursive filesystem ops
  f2fs: keep quota data on write_begin failure
  f2fs: call f2fs_balance_fs outside of locked page
  f2fs: preallocate DIO blocks when forcing buffered_io

 Conflicts:
	arch/arm64/configs/cuttlefish_defconfig
	drivers/of/Kconfig
	drivers/scsi/ufs/ufshcd.c
	fs/ext4/page-io.c
	fs/f2fs/data.c
	kernel/time/alarmtimer.c

 Fixed build error:
	fs/f2fs/super.c

Change-Id: Icab37412960fb921b699c0c896c58e3d12db741a
Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
2020-07-27 11:04:03 +05:30

726 lines
14 KiB
C

/*
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* Author: Andrey Ryabinin <a.ryabinin@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#define pr_fmt(fmt) "kasan test: %s " fmt, __func__
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/kasan.h>
/*
* Note: test functions are marked noinline so that their names appear in
* reports.
*/
static noinline void __init kmalloc_oob_right(void)
{
char *ptr;
size_t size = 123;
pr_info("out-of-bounds to right\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
ptr[size] = 'x';
kfree(ptr);
}
static noinline void __init kmalloc_oob_left(void)
{
char *ptr;
size_t size = 15;
pr_info("out-of-bounds to left\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
*ptr = *(ptr - 1);
kfree(ptr);
}
static noinline void __init kmalloc_node_oob_right(void)
{
char *ptr;
size_t size = 4096;
pr_info("kmalloc_node(): out-of-bounds to right\n");
ptr = kmalloc_node(size, GFP_KERNEL, 0);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
ptr[size] = 0;
kfree(ptr);
}
#ifdef CONFIG_SLUB
static noinline void __init kmalloc_pagealloc_oob_right(void)
{
char *ptr;
size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
/* Allocate a chunk that does not fit into a SLUB cache to trigger
* the page allocator fallback.
*/
pr_info("kmalloc pagealloc allocation: out-of-bounds to right\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
ptr[size] = 0;
kfree(ptr);
}
static noinline void __init kmalloc_pagealloc_uaf(void)
{
char *ptr;
size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
pr_info("kmalloc pagealloc allocation: use-after-free\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
kfree(ptr);
ptr[0] = 0;
}
static noinline void __init kmalloc_pagealloc_invalid_free(void)
{
char *ptr;
size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
pr_info("kmalloc pagealloc allocation: invalid-free\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
kfree(ptr + 1);
}
#endif
static noinline void __init kmalloc_large_oob_right(void)
{
char *ptr;
size_t size = KMALLOC_MAX_CACHE_SIZE - 256;
/* Allocate a chunk that is large enough, but still fits into a slab
* and does not trigger the page allocator fallback in SLUB.
*/
pr_info("kmalloc large allocation: out-of-bounds to right\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
ptr[size] = 0;
kfree(ptr);
}
static noinline void __init kmalloc_oob_krealloc_more(void)
{
char *ptr1, *ptr2;
size_t size1 = 17;
size_t size2 = 19;
pr_info("out-of-bounds after krealloc more\n");
ptr1 = kmalloc(size1, GFP_KERNEL);
ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
if (!ptr1 || !ptr2) {
pr_err("Allocation failed\n");
kfree(ptr1);
kfree(ptr2);
return;
}
ptr2[size2] = 'x';
kfree(ptr2);
}
static noinline void __init kmalloc_oob_krealloc_less(void)
{
char *ptr1, *ptr2;
size_t size1 = 17;
size_t size2 = 15;
pr_info("out-of-bounds after krealloc less\n");
ptr1 = kmalloc(size1, GFP_KERNEL);
ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
if (!ptr1 || !ptr2) {
pr_err("Allocation failed\n");
kfree(ptr1);
return;
}
ptr2[size2] = 'x';
kfree(ptr2);
}
static noinline void __init kmalloc_oob_16(void)
{
struct {
u64 words[2];
} *ptr1, *ptr2;
pr_info("kmalloc out-of-bounds for 16-bytes access\n");
ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
if (!ptr1 || !ptr2) {
pr_err("Allocation failed\n");
kfree(ptr1);
kfree(ptr2);
return;
}
*ptr1 = *ptr2;
kfree(ptr1);
kfree(ptr2);
}
static noinline void __init kmalloc_oob_memset_2(void)
{
char *ptr;
size_t size = 8;
pr_info("out-of-bounds in memset2\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
memset(ptr+7, 0, 2);
kfree(ptr);
}
static noinline void __init kmalloc_oob_memset_4(void)
{
char *ptr;
size_t size = 8;
pr_info("out-of-bounds in memset4\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
memset(ptr+5, 0, 4);
kfree(ptr);
}
static noinline void __init kmalloc_oob_memset_8(void)
{
char *ptr;
size_t size = 8;
pr_info("out-of-bounds in memset8\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
memset(ptr+1, 0, 8);
kfree(ptr);
}
static noinline void __init kmalloc_oob_memset_16(void)
{
char *ptr;
size_t size = 16;
pr_info("out-of-bounds in memset16\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
memset(ptr+1, 0, 16);
kfree(ptr);
}
static noinline void __init kmalloc_oob_in_memset(void)
{
char *ptr;
size_t size = 666;
pr_info("out-of-bounds in memset\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
memset(ptr, 0, size+5);
kfree(ptr);
}
static noinline void __init kmalloc_uaf(void)
{
char *ptr;
size_t size = 10;
pr_info("use-after-free\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
kfree(ptr);
*(ptr + 8) = 'x';
}
static noinline void __init kmalloc_uaf_memset(void)
{
char *ptr;
size_t size = 33;
pr_info("use-after-free in memset\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
kfree(ptr);
memset(ptr, 0, size);
}
static noinline void __init kmalloc_uaf2(void)
{
char *ptr1, *ptr2;
size_t size = 43;
pr_info("use-after-free after another kmalloc\n");
ptr1 = kmalloc(size, GFP_KERNEL);
if (!ptr1) {
pr_err("Allocation failed\n");
return;
}
kfree(ptr1);
ptr2 = kmalloc(size, GFP_KERNEL);
if (!ptr2) {
pr_err("Allocation failed\n");
return;
}
ptr1[40] = 'x';
if (ptr1 == ptr2)
pr_err("Could not detect use-after-free: ptr1 == ptr2\n");
kfree(ptr2);
}
static noinline void __init kmem_cache_oob(void)
{
char *p;
size_t size = 200;
struct kmem_cache *cache = kmem_cache_create("test_cache",
size, 0,
0, NULL);
if (!cache) {
pr_err("Cache allocation failed\n");
return;
}
pr_info("out-of-bounds in kmem_cache_alloc\n");
p = kmem_cache_alloc(cache, GFP_KERNEL);
if (!p) {
pr_err("Allocation failed\n");
kmem_cache_destroy(cache);
return;
}
*p = p[size];
kmem_cache_free(cache, p);
kmem_cache_destroy(cache);
}
static noinline void __init memcg_accounted_kmem_cache(void)
{
int i;
char *p;
size_t size = 200;
struct kmem_cache *cache;
cache = kmem_cache_create("test_cache", size, 0, SLAB_ACCOUNT, NULL);
if (!cache) {
pr_err("Cache allocation failed\n");
return;
}
pr_info("allocate memcg accounted object\n");
/*
* Several allocations with a delay to allow for lazy per memcg kmem
* cache creation.
*/
for (i = 0; i < 5; i++) {
p = kmem_cache_alloc(cache, GFP_KERNEL);
if (!p) {
pr_err("Allocation failed\n");
goto free_cache;
}
kmem_cache_free(cache, p);
msleep(100);
}
free_cache:
kmem_cache_destroy(cache);
}
static char global_array[10];
static noinline void __init kasan_global_oob(void)
{
volatile int i = 3;
char *p = &global_array[ARRAY_SIZE(global_array) + i];
pr_info("out-of-bounds global variable\n");
*(volatile char *)p;
}
static noinline void __init kasan_stack_oob(void)
{
char stack_array[10];
volatile int i = 0;
char *p = &stack_array[ARRAY_SIZE(stack_array) + i];
pr_info("out-of-bounds on stack\n");
*(volatile char *)p;
}
static noinline void __init ksize_unpoisons_memory(void)
{
char *ptr;
size_t size = 123, real_size;
pr_info("ksize() unpoisons the whole allocated chunk\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
real_size = ksize(ptr);
/* This access doesn't trigger an error. */
ptr[size] = 'x';
/* This one does. */
ptr[real_size] = 'y';
kfree(ptr);
}
static noinline void __init copy_user_test(void)
{
char *kmem;
char __user *usermem;
size_t size = 10;
int unused;
kmem = kmalloc(size, GFP_KERNEL);
if (!kmem)
return;
usermem = (char __user *)vm_mmap(NULL, 0, PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, 0);
if (IS_ERR(usermem)) {
pr_err("Failed to allocate user memory\n");
kfree(kmem);
return;
}
pr_info("out-of-bounds in copy_from_user()\n");
unused = copy_from_user(kmem, usermem, size + 1);
pr_info("out-of-bounds in copy_to_user()\n");
unused = copy_to_user(usermem, kmem, size + 1);
pr_info("out-of-bounds in __copy_from_user()\n");
unused = __copy_from_user(kmem, usermem, size + 1);
pr_info("out-of-bounds in __copy_to_user()\n");
unused = __copy_to_user(usermem, kmem, size + 1);
pr_info("out-of-bounds in __copy_from_user_inatomic()\n");
unused = __copy_from_user_inatomic(kmem, usermem, size + 1);
pr_info("out-of-bounds in __copy_to_user_inatomic()\n");
unused = __copy_to_user_inatomic(usermem, kmem, size + 1);
pr_info("out-of-bounds in strncpy_from_user()\n");
unused = strncpy_from_user(kmem, usermem, size + 1);
vm_munmap((unsigned long)usermem, PAGE_SIZE);
kfree(kmem);
}
static noinline void __init kasan_alloca_oob_left(void)
{
volatile int i = 10;
char alloca_array[i];
char *p = alloca_array - 1;
pr_info("out-of-bounds to left on alloca\n");
*(volatile char *)p;
}
static noinline void __init kasan_alloca_oob_right(void)
{
volatile int i = 10;
char alloca_array[i];
char *p = alloca_array + i;
pr_info("out-of-bounds to right on alloca\n");
*(volatile char *)p;
}
static noinline void __init kmem_cache_double_free(void)
{
char *p;
size_t size = 200;
struct kmem_cache *cache;
cache = kmem_cache_create("test_cache", size, 0, 0, NULL);
if (!cache) {
pr_err("Cache allocation failed\n");
return;
}
pr_info("double-free on heap object\n");
p = kmem_cache_alloc(cache, GFP_KERNEL);
if (!p) {
pr_err("Allocation failed\n");
kmem_cache_destroy(cache);
return;
}
kmem_cache_free(cache, p);
kmem_cache_free(cache, p);
kmem_cache_destroy(cache);
}
static noinline void __init kmem_cache_invalid_free(void)
{
char *p;
size_t size = 200;
struct kmem_cache *cache;
cache = kmem_cache_create("test_cache", size, 0, SLAB_TYPESAFE_BY_RCU,
NULL);
if (!cache) {
pr_err("Cache allocation failed\n");
return;
}
pr_info("invalid-free of heap object\n");
p = kmem_cache_alloc(cache, GFP_KERNEL);
if (!p) {
pr_err("Allocation failed\n");
kmem_cache_destroy(cache);
return;
}
/* Trigger invalid free, the object doesn't get freed */
kmem_cache_free(cache, p + 1);
/*
* Properly free the object to prevent the "Objects remaining in
* test_cache on __kmem_cache_shutdown" BUG failure.
*/
kmem_cache_free(cache, p);
kmem_cache_destroy(cache);
}
static noinline void __init kasan_memchr(void)
{
char *ptr;
size_t size = 24;
pr_info("out-of-bounds in memchr\n");
ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
if (!ptr)
return;
memchr(ptr, '1', size + 1);
kfree(ptr);
}
static noinline void __init kasan_memcmp(void)
{
char *ptr;
size_t size = 24;
int arr[9];
pr_info("out-of-bounds in memcmp\n");
ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
if (!ptr)
return;
memset(arr, 0, sizeof(arr));
memcmp(ptr, arr, size+1);
kfree(ptr);
}
static noinline void __init kasan_strings(void)
{
char *ptr;
size_t size = 24;
pr_info("use-after-free in strchr\n");
ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
if (!ptr)
return;
kfree(ptr);
/*
* Try to cause only 1 invalid access (less spam in dmesg).
* For that we need ptr to point to zeroed byte.
* Skip metadata that could be stored in freed object so ptr
* will likely point to zeroed byte.
*/
ptr += 16;
strchr(ptr, '1');
pr_info("use-after-free in strrchr\n");
strrchr(ptr, '1');
pr_info("use-after-free in strcmp\n");
strcmp(ptr, "2");
pr_info("use-after-free in strncmp\n");
strncmp(ptr, "2", 1);
pr_info("use-after-free in strlen\n");
strlen(ptr);
pr_info("use-after-free in strnlen\n");
strnlen(ptr, 1);
}
static noinline void __init kmem_cache_double_free(void)
{
char *p;
size_t size = 200;
struct kmem_cache *cache;
cache = kmem_cache_create("test_cache", size, 0, 0, NULL);
if (!cache) {
pr_err("Cache allocation failed\n");
return;
}
pr_info("double-free on heap object\n");
p = kmem_cache_alloc(cache, GFP_KERNEL);
if (!p) {
pr_err("Allocation failed\n");
kmem_cache_destroy(cache);
return;
}
kmem_cache_free(cache, p);
kmem_cache_free(cache, p);
kmem_cache_destroy(cache);
}
static noinline void __init kmem_cache_invalid_free(void)
{
char *p;
size_t size = 200;
struct kmem_cache *cache;
cache = kmem_cache_create("test_cache", size, 0, SLAB_TYPESAFE_BY_RCU,
NULL);
if (!cache) {
pr_err("Cache allocation failed\n");
return;
}
pr_info("invalid-free of heap object\n");
p = kmem_cache_alloc(cache, GFP_KERNEL);
if (!p) {
pr_err("Allocation failed\n");
kmem_cache_destroy(cache);
return;
}
kmem_cache_free(cache, p + 1);
kmem_cache_destroy(cache);
}
static int __init kmalloc_tests_init(void)
{
/*
* Temporarily enable multi-shot mode. Otherwise, we'd only get a
* report for the first case.
*/
bool multishot = kasan_save_enable_multi_shot();
kmalloc_oob_right();
kmalloc_oob_left();
kmalloc_node_oob_right();
#ifdef CONFIG_SLUB
kmalloc_pagealloc_oob_right();
kmalloc_pagealloc_uaf();
kmalloc_pagealloc_invalid_free();
#endif
kmalloc_large_oob_right();
kmalloc_oob_krealloc_more();
kmalloc_oob_krealloc_less();
kmalloc_oob_16();
kmalloc_oob_in_memset();
kmalloc_oob_memset_2();
kmalloc_oob_memset_4();
kmalloc_oob_memset_8();
kmalloc_oob_memset_16();
kmalloc_uaf();
kmalloc_uaf_memset();
kmalloc_uaf2();
kmem_cache_oob();
memcg_accounted_kmem_cache();
kasan_stack_oob();
kasan_global_oob();
kasan_alloca_oob_left();
kasan_alloca_oob_right();
ksize_unpoisons_memory();
copy_user_test();
use_after_scope_test();
kmem_cache_double_free();
kmem_cache_invalid_free();
kasan_memchr();
kasan_memcmp();
kasan_strings();
kasan_restore_multi_shot(multishot);
return -EAGAIN;
}
module_init(kmalloc_tests_init);
MODULE_LICENSE("GPL");