android_kernel_xiaomi_sm8350/lib/test_stackinit.c
Greg Kroah-Hartman c4f92aff87 This is the 5.4.148 stable release
-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmFLBPMACgkQONu9yGCS
 aT6BIQ//Wb4ZQJtEVvaKnda7vFwe8BoZzPGYZA4Imn9KERDRgHuavEuRfMQtKc2y
 YHwe/PD2JreuDHcd+Wz32xsdMe045xNvgiE1oGcxq0jNBvhJqANSmVTWpdqAquON
 cTmwsK3roa7ELC2g1WjrYZDv6CrCggqvbuM9AJ/cLITtd8zerhLdZo+CCDG/28cH
 EosrWvkBcaGmX+r/IBC86Rt6K2OFQ/3LLbb79L4vjKi5lopsm5CTAmfOfIk8p1gB
 mGB3PkQZnIqphBfqGXLGuljl4e+zb1SONrugUh78Egom393Ex34oo+RjWEGe9dV2
 Stkuqo0GTi85X7JA7SGCA/xgF8A8yvaaLjQBsJsL9+2ji+GW+J7hfn4mE5h8H3Di
 UBjeLMFJA8Mge8Ng9xUSttvjRdwSTm0jWTS9SOl07w24b0pKYbMrQdWt2eI6CT+/
 ytq3nCxNJZKeVcAVH+OJNrbSLYvMy/PgYvGTbzASkNmpAeyNiHOyBz1sRcoiAM9U
 QCWDdZyaqDKktqEyKHxK3opqPzbnHfZFFlCxR7Gw7vvR+itIGJEh/50RNv2F6vnu
 wzowrVxe+Bf1h7JiNEqLLVHdiuygRqjH1ygepGM4+3TVF4jYHzDISyrqlA/Se3Pg
 Hhvlzsbv7PH+KiApwBFjSeHTs5WOrokGMFQ7ZYFDpPkleWiywS0=
 =50Hk
 -----END PGP SIGNATURE-----

Merge 5.4.148 into android11-5.4-lts

Changes in 5.4.148
	rtc: tps65910: Correct driver module alias
	btrfs: wake up async_delalloc_pages waiters after submit
	btrfs: reset replace target device to allocation state on close
	blk-zoned: allow zone management send operations without CAP_SYS_ADMIN
	blk-zoned: allow BLKREPORTZONE without CAP_SYS_ADMIN
	PCI/MSI: Skip masking MSI-X on Xen PV
	powerpc/perf/hv-gpci: Fix counter value parsing
	xen: fix setting of max_pfn in shared_info
	include/linux/list.h: add a macro to test if entry is pointing to the head
	9p/xen: Fix end of loop tests for list_for_each_entry
	tools/thermal/tmon: Add cross compiling support
	pinctrl: stmfx: Fix hazardous u8[] to unsigned long cast
	pinctrl: ingenic: Fix incorrect pull up/down info
	soc: qcom: aoss: Fix the out of bound usage of cooling_devs
	soc: aspeed: lpc-ctrl: Fix boundary check for mmap
	soc: aspeed: p2a-ctrl: Fix boundary check for mmap
	arm64: head: avoid over-mapping in map_memory
	crypto: public_key: fix overflow during implicit conversion
	block: bfq: fix bfq_set_next_ioprio_data()
	power: supply: max17042: handle fails of reading status register
	dm crypt: Avoid percpu_counter spinlock contention in crypt_page_alloc()
	VMCI: fix NULL pointer dereference when unmapping queue pair
	media: uvc: don't do DMA on stack
	media: rc-loopback: return number of emitters rather than error
	Revert "dmaengine: imx-sdma: refine to load context only once"
	dmaengine: imx-sdma: remove duplicated sdma_load_context
	libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
	ARM: 9105/1: atags_to_fdt: don't warn about stack size
	PCI/portdrv: Enable Bandwidth Notification only if port supports it
	PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
	PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
	PCI: xilinx-nwl: Enable the clock through CCF
	PCI: aardvark: Fix checking for PIO status
	PCI: aardvark: Increase polling delay to 1.5s while waiting for PIO response
	PCI: aardvark: Fix masking and unmasking legacy INTx interrupts
	HID: input: do not report stylus battery state as "full"
	f2fs: quota: fix potential deadlock
	scsi: bsg: Remove support for SCSI_IOCTL_SEND_COMMAND
	IB/hfi1: Adjust pkey entry in index 0
	RDMA/iwcm: Release resources if iw_cm module initialization fails
	docs: Fix infiniband uverbs minor number
	pinctrl: samsung: Fix pinctrl bank pin count
	vfio: Use config not menuconfig for VFIO_NOIOMMU
	powerpc/stacktrace: Include linux/delay.h
	RDMA/efa: Remove double QP type assignment
	f2fs: show f2fs instance in printk_ratelimited
	f2fs: reduce the scope of setting fsck tag when de->name_len is zero
	openrisc: don't printk() unconditionally
	dma-debug: fix debugfs initialization order
	SUNRPC: Fix potential memory corruption
	scsi: fdomain: Fix error return code in fdomain_probe()
	pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
	scsi: smartpqi: Fix an error code in pqi_get_raid_map()
	scsi: qedi: Fix error codes in qedi_alloc_global_queues()
	scsi: qedf: Fix error codes in qedf_alloc_global_queues()
	powerpc/config: Renable MTD_PHYSMAP_OF
	scsi: target: avoid per-loop XCOPY buffer allocations
	HID: i2c-hid: Fix Elan touchpad regression
	KVM: PPC: Book3S HV Nested: Reflect guest PMU in-use to L0 when guest SPRs are live
	platform/x86: dell-smbios-wmi: Add missing kfree in error-exit from run_smbios_call
	fscache: Fix cookie key hashing
	clk: at91: sam9x60: Don't use audio PLL
	clk: at91: clk-generated: pass the id of changeable parent at registration
	clk: at91: clk-generated: Limit the requested rate to our range
	KVM: PPC: Fix clearing never mapped TCEs in realmode
	f2fs: fix to account missing .skipped_gc_rwsem
	f2fs: fix unexpected ENOENT comes from f2fs_map_blocks()
	f2fs: fix to unmap pages from userspace process in punch_hole()
	MIPS: Malta: fix alignment of the devicetree buffer
	kbuild: Fix 'no symbols' warning when CONFIG_TRIM_UNUSD_KSYMS=y
	userfaultfd: prevent concurrent API initialization
	drm/amdgpu: Fix amdgpu_ras_eeprom_init()
	ASoC: atmel: ATMEL drivers don't need HAS_DMA
	media: dib8000: rewrite the init prbs logic
	crypto: mxs-dcp - Use sg_mapping_iter to copy data
	PCI: Use pci_update_current_state() in pci_enable_device_flags()
	tipc: keep the skb in rcv queue until the whole data is read
	iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
	iavf: do not override the adapter state in the watchdog task
	iavf: fix locking of critical sections
	ARM: dts: qcom: apq8064: correct clock names
	video: fbdev: kyro: fix a DoS bug by restricting user input
	netlink: Deal with ESRCH error in nlmsg_notify()
	Smack: Fix wrong semantics in smk_access_entry()
	drm: avoid blocking in drm_clients_info's rcu section
	igc: Check if num of q_vectors is smaller than max before array access
	usb: host: fotg210: fix the endpoint's transactional opportunities calculation
	usb: host: fotg210: fix the actual_length of an iso packet
	usb: gadget: u_ether: fix a potential null pointer dereference
	USB: EHCI: ehci-mv: improve error handling in mv_ehci_enable()
	usb: gadget: composite: Allow bMaxPower=0 if self-powered
	staging: board: Fix uninitialized spinlock when attaching genpd
	tty: serial: jsm: hold port lock when reporting modem line changes
	drm/amd/display: Fix timer_per_pixel unit error
	drm/amd/amdgpu: Update debugfs link_settings output link_rate field in hex
	bpf/tests: Fix copy-and-paste error in double word test
	bpf/tests: Do not PASS tests without actually testing the result
	video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
	video: fbdev: kyro: Error out if 'pixclock' equals zero
	video: fbdev: riva: Error out if 'pixclock' equals zero
	ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
	flow_dissector: Fix out-of-bounds warnings
	s390/jump_label: print real address in a case of a jump label bug
	s390: make PCI mio support a machine flag
	serial: 8250: Define RX trigger levels for OxSemi 950 devices
	xtensa: ISS: don't panic in rs_init
	hvsi: don't panic on tty_register_driver failure
	serial: 8250_pci: make setup_port() parameters explicitly unsigned
	staging: ks7010: Fix the initialization of the 'sleep_status' structure
	samples: bpf: Fix tracex7 error raised on the missing argument
	ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init()
	Bluetooth: skip invalid hci_sync_conn_complete_evt
	workqueue: Fix possible memory leaks in wq_numa_init()
	bonding: 3ad: fix the concurrency between __bond_release_one() and bond_3ad_state_machine_handler()
	arm64: tegra: Fix Tegra194 PCIe EP compatible string
	ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the matching in-/output
	media: imx258: Rectify mismatch of VTS value
	media: imx258: Limit the max analogue gain to 480
	media: v4l2-dv-timings.c: fix wrong condition in two for-loops
	media: TDA1997x: fix tda1997x_query_dv_timings() return value
	media: tegra-cec: Handle errors of clk_prepare_enable()
	ARM: dts: imx53-ppd: Fix ACHC entry
	arm64: dts: qcom: sdm660: use reg value for memory node
	net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe()
	drm/msm: mdp4: drop vblank get/put from prepare/complete_commit
	selftests/bpf: Fix xdp_tx.c prog section name
	Bluetooth: schedule SCO timeouts with delayed_work
	Bluetooth: avoid circular locks in sco_sock_connect
	net/mlx5: Fix variable type to match 64bit
	gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable access in amdgpu_i2c_router_select_ddc_port()
	drm/display: fix possible null-pointer dereference in dcn10_set_clock()
	mac80211: Fix monitor MTU limit so that A-MSDUs get through
	ARM: tegra: tamonten: Fix UART pad setting
	arm64: tegra: Fix compatible string for Tegra132 CPUs
	arm64: dts: ls1046a: fix eeprom entries
	nvme-tcp: don't check blk_mq_tag_to_rq when receiving pdu data
	Bluetooth: Fix handling of LE Enhanced Connection Complete
	opp: Don't print an error if required-opps is missing
	serial: sh-sci: fix break handling for sysrq
	tcp: enable data-less, empty-cookie SYN with TFO_SERVER_COOKIE_NOT_REQD
	rpc: fix gss_svc_init cleanup on failure
	staging: rts5208: Fix get_ms_information() heap buffer size
	gfs2: Don't call dlm after protocol is unmounted
	usb: chipidea: host: fix port index underflow and UBSAN complains
	lockd: lockd server-side shouldn't set fl_ops
	drm/exynos: Always initialize mapping in exynos_drm_register_dma()
	m68knommu: only set CONFIG_ISA_DMA_API for ColdFire sub-arch
	btrfs: tree-log: check btrfs_lookup_data_extent return value
	ASoC: Intel: Skylake: Fix module configuration for KPB and MIXER
	ASoC: Intel: Skylake: Fix passing loadable flag for module
	of: Don't allow __of_attached_node_sysfs() without CONFIG_SYSFS
	mmc: sdhci-of-arasan: Check return value of non-void funtions
	mmc: rtsx_pci: Fix long reads when clock is prescaled
	selftests/bpf: Enlarge select() timeout for test_maps
	mmc: core: Return correct emmc response in case of ioctl error
	cifs: fix wrong release in sess_alloc_buffer() failed path
	Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set"
	usb: musb: musb_dsps: request_irq() after initializing musb
	usbip: give back URBs for unsent unlink requests during cleanup
	usbip:vhci_hcd USB port can get stuck in the disabled state
	ASoC: rockchip: i2s: Fix regmap_ops hang
	ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B
	drm/amdkfd: Account for SH/SE count when setting up cu masks.
	iwlwifi: mvm: fix a memory leak in iwl_mvm_mac_ctxt_beacon_changed
	iwlwifi: mvm: avoid static queue number aliasing
	iwlwifi: mvm: fix access to BSS elements
	net/mlx5: DR, Enable QP retransmission
	parport: remove non-zero check on count
	ath9k: fix OOB read ar9300_eeprom_restore_internal
	ath9k: fix sleeping in atomic context
	net: fix NULL pointer reference in cipso_v4_doi_free
	fix array-index-out-of-bounds in taprio_change
	net: w5100: check return value after calling platform_get_resource()
	parisc: fix crash with signals and alloca
	ovl: fix BUG_ON() in may_delete() when called from ovl_cleanup()
	scsi: BusLogic: Fix missing pr_cont() use
	scsi: qla2xxx: Changes to support kdump kernel
	scsi: qla2xxx: Sync queue idx with queue_pair_map idx
	cpufreq: powernv: Fix init_chip_info initialization in numa=off
	s390/pv: fix the forcing of the swiotlb
	mm/hugetlb: initialize hugetlb_usage in mm_init
	mm,vmscan: fix divide by zero in get_scan_count
	memcg: enable accounting for pids in nested pid namespaces
	platform/chrome: cros_ec_proto: Send command again when timeout occurs
	lib/test_stackinit: Fix static initializer test
	net: dsa: lantiq_gswip: fix maximum frame length
	drm/msi/mdp4: populate priv->kms in mdp4_kms_init
	drm/amdgpu: Fix BUG_ON assert
	drm/panfrost: Simplify lock_region calculation
	drm/panfrost: Use u64 for size in lock_region
	drm/panfrost: Clamp lock region to Bifrost minimum
	btrfs: fix upper limit for max_inline for page size 64K
	xen: reset legacy rtc flag for PV domU
	bnx2x: Fix enabling network interfaces without VFs
	arm64/sve: Use correct size when reinitialising SVE state
	PM: base: power: don't try to use non-existing RTC for storing data
	PCI: Add AMD GPU multi-function power dependencies
	drm/amd/amdgpu: Increase HWIP_MAX_INSTANCE to 10
	drm/etnaviv: return context from etnaviv_iommu_context_get
	drm/etnaviv: put submit prev MMU context when it exists
	drm/etnaviv: stop abusing mmu_context as FE running marker
	drm/etnaviv: keep MMU context across runtime suspend/resume
	drm/etnaviv: exec and MMU state is lost when resetting the GPU
	drm/etnaviv: fix MMU context leak on GPU reset
	drm/etnaviv: reference MMU context when setting up hardware state
	drm/etnaviv: add missing MMU context put when reaping MMU mapping
	s390/sclp: fix Secure-IPL facility detection
	x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
	tipc: fix an use-after-free issue in tipc_recvmsg
	net-caif: avoid user-triggerable WARN_ON(1)
	ptp: dp83640: don't define PAGE0
	dccp: don't duplicate ccid when cloning dccp sock
	net/l2tp: Fix reference count leak in l2tp_udp_recv_core
	r6040: Restore MDIO clock frequency after MAC reset
	tipc: increase timeout in tipc_sk_enqueue()
	perf machine: Initialize srcline string member in add_location struct
	net/mlx5: FWTrace, cancel work on alloc pd error flow
	net/mlx5: Fix potential sleeping in atomic context
	events: Reuse value read using READ_ONCE instead of re-reading it
	vhost_net: fix OoB on sendmsg() failure.
	net/af_unix: fix a data-race in unix_dgram_poll
	net: dsa: destroy the phylink instance on any error in dsa_slave_phy_setup
	tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
	qed: Handle management FW error
	dt-bindings: arm: Fix Toradex compatible typo
	ibmvnic: check failover_pending in login response
	KVM: PPC: Book3S HV: Tolerate treclaim. in fake-suspend mode changing registers
	net: hns3: pad the short tunnel frame before sending to hardware
	net: hns3: change affinity_mask to numa node range
	net: hns3: disable mac in flr process
	net: hns3: fix the timing issue of VF clearing interrupt sources
	mm/memory_hotplug: use "unsigned long" for PFN in zone_for_pfn_range()
	dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
	mfd: db8500-prcmu: Adjust map to reality
	PCI: Add ACS quirks for NXP LX2xx0 and LX2xx2 platforms
	fuse: fix use after free in fuse_read_interrupt()
	mfd: Don't use irq_create_mapping() to resolve a mapping
	tracing/probes: Reject events which have the same name of existing one
	PCI: Add ACS quirks for Cavium multi-function devices
	Set fc_nlinfo in nh_create_ipv4, nh_create_ipv6
	net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920
	block, bfq: honor already-setup queue merges
	PCI: ibmphp: Fix double unmap of io_mem
	ethtool: Fix an error code in cxgb2.c
	NTB: Fix an error code in ntb_msit_probe()
	NTB: perf: Fix an error code in perf_setup_inbuf()
	mfd: axp20x: Update AXP288 volatile ranges
	PCI: Fix pci_dev_str_match_path() alloc while atomic bug
	mfd: tqmx86: Clear GPIO IRQ resource when no IRQ is set
	KVM: arm64: Handle PSCI resets before userspace touches vCPU state
	PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
	mtd: rawnand: cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()'
	ARC: export clear_user_page() for modules
	perf unwind: Do not overwrite FEATURE_CHECK_LDFLAGS-libunwind-{x86,aarch64}
	net: dsa: b53: Fix calculating number of switch ports
	netfilter: socket: icmp6: fix use-after-scope
	fq_codel: reject silly quantum parameters
	qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
	ip_gre: validate csum_start only on pull
	net: renesas: sh_eth: Fix freeing wrong tx descriptor
	s390/bpf: Fix optimizing out zero-extensions
	s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant
	Linux 5.4.148

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I8613b511cb543a7ce0d1623663fc1306aaa45af1
2021-09-25 14:41:58 +02:00

390 lines
11 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Test cases for compiler-based stack variable zeroing via future
* compiler flags or CONFIG_GCC_PLUGIN_STRUCTLEAK*.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
/* Exfiltration buffer. */
#define MAX_VAR_SIZE 128
static u8 check_buf[MAX_VAR_SIZE];
/* Character array to trigger stack protector in all functions. */
#define VAR_BUFFER 32
/* Volatile mask to convince compiler to copy memory with 0xff. */
static volatile u8 forced_mask = 0xff;
/* Location and size tracking to validate fill and test are colocated. */
static void *fill_start, *target_start;
static size_t fill_size, target_size;
static bool range_contains(char *haystack_start, size_t haystack_size,
char *needle_start, size_t needle_size)
{
if (needle_start >= haystack_start &&
needle_start + needle_size <= haystack_start + haystack_size)
return true;
return false;
}
#define DO_NOTHING_TYPE_SCALAR(var_type) var_type
#define DO_NOTHING_TYPE_STRING(var_type) void
#define DO_NOTHING_TYPE_STRUCT(var_type) void
#define DO_NOTHING_RETURN_SCALAR(ptr) *(ptr)
#define DO_NOTHING_RETURN_STRING(ptr) /**/
#define DO_NOTHING_RETURN_STRUCT(ptr) /**/
#define DO_NOTHING_CALL_SCALAR(var, name) \
(var) = do_nothing_ ## name(&(var))
#define DO_NOTHING_CALL_STRING(var, name) \
do_nothing_ ## name(var)
#define DO_NOTHING_CALL_STRUCT(var, name) \
do_nothing_ ## name(&(var))
#define FETCH_ARG_SCALAR(var) &var
#define FETCH_ARG_STRING(var) var
#define FETCH_ARG_STRUCT(var) &var
#define FILL_SIZE_STRING 16
#define INIT_CLONE_SCALAR /**/
#define INIT_CLONE_STRING [FILL_SIZE_STRING]
#define INIT_CLONE_STRUCT /**/
#define INIT_SCALAR_none /**/
#define INIT_SCALAR_zero = 0
#define INIT_STRING_none [FILL_SIZE_STRING] /**/
#define INIT_STRING_zero [FILL_SIZE_STRING] = { }
#define INIT_STRUCT_none /**/
#define INIT_STRUCT_zero = { }
#define INIT_STRUCT_static_partial = { .two = 0, }
#define INIT_STRUCT_static_all = { .one = 0, \
.two = 0, \
.three = 0, \
.four = 0, \
}
#define INIT_STRUCT_dynamic_partial = { .two = arg->two, }
#define INIT_STRUCT_dynamic_all = { .one = arg->one, \
.two = arg->two, \
.three = arg->three, \
.four = arg->four, \
}
#define INIT_STRUCT_runtime_partial ; \
var.two = 0
#define INIT_STRUCT_runtime_all ; \
var.one = 0; \
var.two = 0; \
var.three = 0; \
var.four = 0
/*
* @name: unique string name for the test
* @var_type: type to be tested for zeroing initialization
* @which: is this a SCALAR, STRING, or STRUCT type?
* @init_level: what kind of initialization is performed
* @xfail: is this test expected to fail?
*/
#define DEFINE_TEST_DRIVER(name, var_type, which, xfail) \
/* Returns 0 on success, 1 on failure. */ \
static noinline __init int test_ ## name (void) \
{ \
var_type zero INIT_CLONE_ ## which; \
int ignored; \
u8 sum = 0, i; \
\
/* Notice when a new test is larger than expected. */ \
BUILD_BUG_ON(sizeof(zero) > MAX_VAR_SIZE); \
\
/* Fill clone type with zero for per-field init. */ \
memset(&zero, 0x00, sizeof(zero)); \
/* Clear entire check buffer for 0xFF overlap test. */ \
memset(check_buf, 0x00, sizeof(check_buf)); \
/* Fill stack with 0xFF. */ \
ignored = leaf_ ##name((unsigned long)&ignored, 1, \
FETCH_ARG_ ## which(zero)); \
/* Verify all bytes overwritten with 0xFF. */ \
for (sum = 0, i = 0; i < target_size; i++) \
sum += (check_buf[i] != 0xFF); \
if (sum) { \
pr_err(#name ": leaf fill was not 0xFF!?\n"); \
return 1; \
} \
/* Clear entire check buffer for later bit tests. */ \
memset(check_buf, 0x00, sizeof(check_buf)); \
/* Extract stack-defined variable contents. */ \
ignored = leaf_ ##name((unsigned long)&ignored, 0, \
FETCH_ARG_ ## which(zero)); \
\
/* Validate that compiler lined up fill and target. */ \
if (!range_contains(fill_start, fill_size, \
target_start, target_size)) { \
pr_err(#name ": stack fill missed target!?\n"); \
pr_err(#name ": fill %zu wide\n", fill_size); \
pr_err(#name ": target offset by %d\n", \
(int)((ssize_t)(uintptr_t)fill_start - \
(ssize_t)(uintptr_t)target_start)); \
return 1; \
} \
\
/* Look for any bytes still 0xFF in check region. */ \
for (sum = 0, i = 0; i < target_size; i++) \
sum += (check_buf[i] == 0xFF); \
\
if (sum == 0) { \
pr_info(#name " ok\n"); \
return 0; \
} else { \
pr_warn(#name " %sFAIL (uninit bytes: %d)\n", \
(xfail) ? "X" : "", sum); \
return (xfail) ? 0 : 1; \
} \
}
#define DEFINE_TEST(name, var_type, which, init_level) \
/* no-op to force compiler into ignoring "uninitialized" vars */\
static noinline __init DO_NOTHING_TYPE_ ## which(var_type) \
do_nothing_ ## name(var_type *ptr) \
{ \
/* Will always be true, but compiler doesn't know. */ \
if ((unsigned long)ptr > 0x2) \
return DO_NOTHING_RETURN_ ## which(ptr); \
else \
return DO_NOTHING_RETURN_ ## which(ptr + 1); \
} \
static noinline __init int leaf_ ## name(unsigned long sp, \
bool fill, \
var_type *arg) \
{ \
char buf[VAR_BUFFER]; \
var_type var INIT_ ## which ## _ ## init_level; \
\
target_start = &var; \
target_size = sizeof(var); \
/* \
* Keep this buffer around to make sure we've got a \
* stack frame of SOME kind... \
*/ \
memset(buf, (char)(sp & 0xff), sizeof(buf)); \
/* Fill variable with 0xFF. */ \
if (fill) { \
fill_start = &var; \
fill_size = sizeof(var); \
memset(fill_start, \
(char)((sp & 0xff) | forced_mask), \
fill_size); \
} \
\
/* Silence "never initialized" warnings. */ \
DO_NOTHING_CALL_ ## which(var, name); \
\
/* Exfiltrate "var". */ \
memcpy(check_buf, target_start, target_size); \
\
return (int)buf[0] | (int)buf[sizeof(buf) - 1]; \
} \
DEFINE_TEST_DRIVER(name, var_type, which, 0)
/* Structure with no padding. */
struct test_packed {
unsigned long one;
unsigned long two;
unsigned long three;
unsigned long four;
};
/* Simple structure with padding likely to be covered by compiler. */
struct test_small_hole {
size_t one;
char two;
/* 3 byte padding hole here. */
int three;
unsigned long four;
};
/* Trigger unhandled padding in a structure. */
struct test_big_hole {
u8 one;
u8 two;
u8 three;
/* 61 byte padding hole here. */
u8 four __aligned(64);
} __aligned(64);
struct test_trailing_hole {
char *one;
char *two;
char *three;
char four;
/* "sizeof(unsigned long) - 1" byte padding hole here. */
};
/* Test if STRUCTLEAK is clearing structs with __user fields. */
struct test_user {
u8 one;
unsigned long two;
char __user *three;
unsigned long four;
};
#define DEFINE_SCALAR_TEST(name, init) \
DEFINE_TEST(name ## _ ## init, name, SCALAR, init)
#define DEFINE_SCALAR_TESTS(init) \
DEFINE_SCALAR_TEST(u8, init); \
DEFINE_SCALAR_TEST(u16, init); \
DEFINE_SCALAR_TEST(u32, init); \
DEFINE_SCALAR_TEST(u64, init); \
DEFINE_TEST(char_array_ ## init, unsigned char, STRING, init)
#define DEFINE_STRUCT_TEST(name, init) \
DEFINE_TEST(name ## _ ## init, \
struct test_ ## name, STRUCT, init)
#define DEFINE_STRUCT_TESTS(init) \
DEFINE_STRUCT_TEST(small_hole, init); \
DEFINE_STRUCT_TEST(big_hole, init); \
DEFINE_STRUCT_TEST(trailing_hole, init); \
DEFINE_STRUCT_TEST(packed, init)
/* These should be fully initialized all the time! */
DEFINE_SCALAR_TESTS(zero);
DEFINE_STRUCT_TESTS(zero);
/* Static initialization: padding may be left uninitialized. */
DEFINE_STRUCT_TESTS(static_partial);
DEFINE_STRUCT_TESTS(static_all);
/* Dynamic initialization: padding may be left uninitialized. */
DEFINE_STRUCT_TESTS(dynamic_partial);
DEFINE_STRUCT_TESTS(dynamic_all);
/* Runtime initialization: padding may be left uninitialized. */
DEFINE_STRUCT_TESTS(runtime_partial);
DEFINE_STRUCT_TESTS(runtime_all);
/* No initialization without compiler instrumentation. */
DEFINE_SCALAR_TESTS(none);
DEFINE_STRUCT_TESTS(none);
DEFINE_TEST(user, struct test_user, STRUCT, none);
/*
* Check two uses through a variable declaration outside either path,
* which was noticed as a special case in porting earlier stack init
* compiler logic.
*/
static int noinline __leaf_switch_none(int path, bool fill)
{
switch (path) {
uint64_t var;
case 1:
target_start = &var;
target_size = sizeof(var);
if (fill) {
fill_start = &var;
fill_size = sizeof(var);
memset(fill_start, forced_mask | 0x55, fill_size);
}
memcpy(check_buf, target_start, target_size);
break;
case 2:
target_start = &var;
target_size = sizeof(var);
if (fill) {
fill_start = &var;
fill_size = sizeof(var);
memset(fill_start, forced_mask | 0xaa, fill_size);
}
memcpy(check_buf, target_start, target_size);
break;
default:
var = 5;
return var & forced_mask;
}
return 0;
}
static noinline __init int leaf_switch_1_none(unsigned long sp, bool fill,
uint64_t *arg)
{
return __leaf_switch_none(1, fill);
}
static noinline __init int leaf_switch_2_none(unsigned long sp, bool fill,
uint64_t *arg)
{
return __leaf_switch_none(2, fill);
}
/*
* These are expected to fail for most configurations because neither
* GCC nor Clang have a way to perform initialization of variables in
* non-code areas (i.e. in a switch statement before the first "case").
* https://bugs.llvm.org/show_bug.cgi?id=44916
*/
DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR, 1);
DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, 1);
static int __init test_stackinit_init(void)
{
unsigned int failures = 0;
#define test_scalars(init) do { \
failures += test_u8_ ## init (); \
failures += test_u16_ ## init (); \
failures += test_u32_ ## init (); \
failures += test_u64_ ## init (); \
failures += test_char_array_ ## init (); \
} while (0)
#define test_structs(init) do { \
failures += test_small_hole_ ## init (); \
failures += test_big_hole_ ## init (); \
failures += test_trailing_hole_ ## init (); \
failures += test_packed_ ## init (); \
} while (0)
/* These are explicitly initialized and should always pass. */
test_scalars(zero);
test_structs(zero);
/* Padding here appears to be accidentally always initialized? */
test_structs(dynamic_partial);
/* Padding initialization depends on compiler behaviors. */
test_structs(static_partial);
test_structs(static_all);
test_structs(dynamic_all);
test_structs(runtime_partial);
test_structs(runtime_all);
/* STRUCTLEAK_BYREF_ALL should cover everything from here down. */
test_scalars(none);
failures += test_switch_1_none();
failures += test_switch_2_none();
/* STRUCTLEAK_BYREF should cover from here down. */
test_structs(none);
/* STRUCTLEAK will only cover this. */
failures += test_user();
if (failures == 0)
pr_info("all tests passed!\n");
else
pr_err("failures: %u\n", failures);
return failures ? -EINVAL : 0;
}
module_init(test_stackinit_init);
static void __exit test_stackinit_exit(void)
{ }
module_exit(test_stackinit_exit);
MODULE_LICENSE("GPL");