brintos

brintos / linux-shallow public Read only

0
0
Text · 6.3 KiB · 200bedc Raw
304 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#ifdef __aarch64__4#include <asm/hwcap.h>5#endif6 7#include <linux/mman.h>8#include <linux/prctl.h>9 10#include <stdio.h>11#include <stdlib.h>12#include <sys/auxv.h>13#include <sys/prctl.h>14#include <sys/wait.h>15#include <unistd.h>16 17#include "../kselftest_harness.h"18 19#ifndef __aarch64__20# define PROT_BTI	021#endif22 23TEST(prctl_flags)24{25	EXPECT_LT(prctl(PR_SET_MDWE, PR_MDWE_NO_INHERIT, 0L, 0L, 7L), 0);26	EXPECT_EQ(errno, EINVAL);27 28	EXPECT_LT(prctl(PR_SET_MDWE, 7L, 0L, 0L, 0L), 0);29	EXPECT_EQ(errno, EINVAL);30	EXPECT_LT(prctl(PR_SET_MDWE, 0L, 7L, 0L, 0L), 0);31	EXPECT_EQ(errno, EINVAL);32	EXPECT_LT(prctl(PR_SET_MDWE, 0L, 0L, 7L, 0L), 0);33	EXPECT_EQ(errno, EINVAL);34	EXPECT_LT(prctl(PR_SET_MDWE, 0L, 0L, 0L, 7L), 0);35	EXPECT_EQ(errno, EINVAL);36 37	EXPECT_LT(prctl(PR_GET_MDWE, 7L, 0L, 0L, 0L), 0);38	EXPECT_EQ(errno, EINVAL);39	EXPECT_LT(prctl(PR_GET_MDWE, 0L, 7L, 0L, 0L), 0);40	EXPECT_EQ(errno, EINVAL);41	EXPECT_LT(prctl(PR_GET_MDWE, 0L, 0L, 7L, 0L), 0);42	EXPECT_EQ(errno, EINVAL);43	EXPECT_LT(prctl(PR_GET_MDWE, 0L, 0L, 0L, 7L), 0);44	EXPECT_EQ(errno, EINVAL);45}46 47FIXTURE(consecutive_prctl_flags) {};48FIXTURE_SETUP(consecutive_prctl_flags) {}49FIXTURE_TEARDOWN(consecutive_prctl_flags) {}50 51FIXTURE_VARIANT(consecutive_prctl_flags)52{53	unsigned long first_flags;54	unsigned long second_flags;55	bool should_work;56};57 58FIXTURE_VARIANT_ADD(consecutive_prctl_flags, can_keep_no_flags)59{60	.first_flags = 0,61	.second_flags = 0,62	.should_work = true,63};64 65FIXTURE_VARIANT_ADD(consecutive_prctl_flags, can_keep_exec_gain)66{67	.first_flags = PR_MDWE_REFUSE_EXEC_GAIN,68	.second_flags = PR_MDWE_REFUSE_EXEC_GAIN,69	.should_work = true,70};71 72FIXTURE_VARIANT_ADD(consecutive_prctl_flags, can_keep_both_flags)73{74	.first_flags = PR_MDWE_REFUSE_EXEC_GAIN | PR_MDWE_NO_INHERIT,75	.second_flags = PR_MDWE_REFUSE_EXEC_GAIN | PR_MDWE_NO_INHERIT,76	.should_work = true,77};78 79FIXTURE_VARIANT_ADD(consecutive_prctl_flags, cant_disable_mdwe)80{81	.first_flags = PR_MDWE_REFUSE_EXEC_GAIN,82	.second_flags = 0,83	.should_work = false,84};85 86FIXTURE_VARIANT_ADD(consecutive_prctl_flags, cant_disable_mdwe_no_inherit)87{88	.first_flags = PR_MDWE_REFUSE_EXEC_GAIN | PR_MDWE_NO_INHERIT,89	.second_flags = 0,90	.should_work = false,91};92 93FIXTURE_VARIANT_ADD(consecutive_prctl_flags, cant_disable_no_inherit)94{95	.first_flags = PR_MDWE_REFUSE_EXEC_GAIN | PR_MDWE_NO_INHERIT,96	.second_flags = PR_MDWE_REFUSE_EXEC_GAIN,97	.should_work = false,98};99 100FIXTURE_VARIANT_ADD(consecutive_prctl_flags, cant_enable_no_inherit)101{102	.first_flags = PR_MDWE_REFUSE_EXEC_GAIN,103	.second_flags = PR_MDWE_REFUSE_EXEC_GAIN | PR_MDWE_NO_INHERIT,104	.should_work = false,105};106 107TEST_F(consecutive_prctl_flags, two_prctls)108{109	int ret;110 111	EXPECT_EQ(prctl(PR_SET_MDWE, variant->first_flags, 0L, 0L, 0L), 0);112 113	ret = prctl(PR_SET_MDWE, variant->second_flags, 0L, 0L, 0L);114	if (variant->should_work) {115		EXPECT_EQ(ret, 0);116 117		ret = prctl(PR_GET_MDWE, 0L, 0L, 0L, 0L);118		ASSERT_EQ(ret, variant->second_flags);119	} else {120		EXPECT_NE(ret, 0);121		ASSERT_EQ(errno, EPERM);122	}123}124 125FIXTURE(mdwe)126{127	void *p;128	int flags;129	size_t size;130	pid_t pid;131};132 133FIXTURE_VARIANT(mdwe)134{135	bool enabled;136	bool forked;137	bool inherit;138};139 140FIXTURE_VARIANT_ADD(mdwe, stock)141{142	.enabled = false,143	.forked = false,144	.inherit = false,145};146 147FIXTURE_VARIANT_ADD(mdwe, enabled)148{149	.enabled = true,150	.forked = false,151	.inherit = true,152};153 154FIXTURE_VARIANT_ADD(mdwe, inherited)155{156	.enabled = true,157	.forked = true,158	.inherit = true,159};160 161FIXTURE_VARIANT_ADD(mdwe, not_inherited)162{163	.enabled = true,164	.forked = true,165	.inherit = false,166};167 168static bool executable_map_should_fail(const FIXTURE_VARIANT(mdwe) *variant)169{170	return variant->enabled && (!variant->forked || variant->inherit);171}172 173FIXTURE_SETUP(mdwe)174{175	unsigned long mdwe_flags;176	int ret, status;177 178	self->p = NULL;179	self->flags = MAP_SHARED | MAP_ANONYMOUS;180	self->size = getpagesize();181 182	if (!variant->enabled)183		return;184 185	mdwe_flags = PR_MDWE_REFUSE_EXEC_GAIN;186	if (!variant->inherit)187		mdwe_flags |= PR_MDWE_NO_INHERIT;188 189	ret = prctl(PR_SET_MDWE, mdwe_flags, 0L, 0L, 0L);190	ASSERT_EQ(ret, 0) {191		TH_LOG("PR_SET_MDWE failed or unsupported");192	}193 194	ret = prctl(PR_GET_MDWE, 0L, 0L, 0L, 0L);195	ASSERT_EQ(ret, mdwe_flags);196 197	if (variant->forked) {198		self->pid = fork();199		ASSERT_GE(self->pid, 0) {200			TH_LOG("fork failed\n");201		}202 203		if (self->pid > 0) {204			ret = waitpid(self->pid, &status, 0);205			ASSERT_TRUE(WIFEXITED(status));206			exit(WEXITSTATUS(status));207		}208	}209}210 211FIXTURE_TEARDOWN(mdwe)212{213	if (self->p && self->p != MAP_FAILED)214		munmap(self->p, self->size);215}216 217TEST_F(mdwe, mmap_READ_EXEC)218{219	self->p = mmap(NULL, self->size, PROT_READ | PROT_EXEC, self->flags, 0, 0);220	EXPECT_NE(self->p, MAP_FAILED);221}222 223TEST_F(mdwe, mmap_WRITE_EXEC)224{225	self->p = mmap(NULL, self->size, PROT_WRITE | PROT_EXEC, self->flags, 0, 0);226	if (executable_map_should_fail(variant)) {227		EXPECT_EQ(self->p, MAP_FAILED);228	} else {229		EXPECT_NE(self->p, MAP_FAILED);230	}231}232 233TEST_F(mdwe, mprotect_stay_EXEC)234{235	int ret;236 237	self->p = mmap(NULL, self->size, PROT_READ | PROT_EXEC, self->flags, 0, 0);238	ASSERT_NE(self->p, MAP_FAILED);239 240	ret = mprotect(self->p, self->size, PROT_READ | PROT_EXEC);241	EXPECT_EQ(ret, 0);242}243 244TEST_F(mdwe, mprotect_add_EXEC)245{246	int ret;247 248	self->p = mmap(NULL, self->size, PROT_READ, self->flags, 0, 0);249	ASSERT_NE(self->p, MAP_FAILED);250 251	ret = mprotect(self->p, self->size, PROT_READ | PROT_EXEC);252	if (executable_map_should_fail(variant)) {253		EXPECT_LT(ret, 0);254	} else {255		EXPECT_EQ(ret, 0);256	}257}258 259TEST_F(mdwe, mprotect_WRITE_EXEC)260{261	int ret;262 263	self->p = mmap(NULL, self->size, PROT_WRITE, self->flags, 0, 0);264	ASSERT_NE(self->p, MAP_FAILED);265 266	ret = mprotect(self->p, self->size, PROT_WRITE | PROT_EXEC);267	if (executable_map_should_fail(variant)) {268		EXPECT_LT(ret, 0);269	} else {270		EXPECT_EQ(ret, 0);271	}272}273 274TEST_F(mdwe, mmap_FIXED)275{276	void *p;277 278	self->p = mmap(NULL, self->size, PROT_READ, self->flags, 0, 0);279	ASSERT_NE(self->p, MAP_FAILED);280 281	/* MAP_FIXED unmaps the existing page before mapping which is allowed */282	p = mmap(self->p, self->size, PROT_READ | PROT_EXEC,283		 self->flags | MAP_FIXED, 0, 0);284	EXPECT_EQ(p, self->p);285}286 287TEST_F(mdwe, arm64_BTI)288{289	int ret;290 291#ifdef __aarch64__292	if (!(getauxval(AT_HWCAP2) & HWCAP2_BTI))293#endif294		SKIP(return, "HWCAP2_BTI not supported");295 296	self->p = mmap(NULL, self->size, PROT_EXEC, self->flags, 0, 0);297	ASSERT_NE(self->p, MAP_FAILED);298 299	ret = mprotect(self->p, self->size, PROT_EXEC | PROT_BTI);300	EXPECT_EQ(ret, 0);301}302 303TEST_HARNESS_MAIN304