brintos

brintos / linux-shallow public Read only

0
0
Text · 3.0 KiB · d9f8ba8 Raw
138 lines · c
1// SPDX-License-Identifier: GPL-2.02#define _GNU_SOURCE3#include <sys/mman.h>4#include <stdint.h>5#include <asm-generic/unistd.h>6#include <string.h>7#include <sys/time.h>8#include <sys/resource.h>9#include <stdbool.h>10#include "../kselftest.h"11#include <syscall.h>12#include <errno.h>13#include <stdio.h>14#include <stdlib.h>15#include <fcntl.h>16#include <sys/ioctl.h>17#include <sys/vfs.h>18#include <sys/stat.h>19#include "mseal_helpers.h"20 21/*22 * define sys_xyx to call syscall directly.23 */24static int sys_mseal(void *start, size_t len)25{26	int sret;27 28	errno = 0;29	sret = syscall(__NR_mseal, start, len, 0);30	return sret;31}32 33static inline int sys_mprotect(void *ptr, size_t size, unsigned long prot)34{35	int sret;36 37	errno = 0;38	sret = syscall(__NR_mprotect, ptr, size, prot);39	return sret;40}41 42static bool seal_support(void)43{44	int ret;45	void *ptr;46	unsigned long page_size = getpagesize();47 48	ptr = mmap(NULL, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);49	if (ptr == (void *) -1)50		return false;51 52	ret = sys_mseal(ptr, page_size);53	if (ret < 0)54		return false;55 56	return true;57}58 59const char somestr[4096] = {"READONLY"};60 61static void test_seal_elf(void)62{63	int ret;64	FILE *maps;65	char line[512];66	uintptr_t  addr_start, addr_end;67	char prot[5];68	char filename[256];69	unsigned long page_size = getpagesize();70	unsigned long long ptr = (unsigned long long) somestr;71	char *somestr2 = (char *)somestr;72 73	/*74	 * Modify the protection of readonly somestr75	 */76	if (((unsigned long long)ptr % page_size) != 0)77		ptr = (unsigned long long)ptr & ~(page_size - 1);78 79	ksft_print_msg("somestr = %s\n", somestr);80	ksft_print_msg("change protection to rw\n");81	ret = sys_mprotect((void *)ptr, page_size, PROT_READ|PROT_WRITE);82	FAIL_TEST_IF_FALSE(!ret);83	*somestr2 = 'A';84	ksft_print_msg("somestr is modified to: %s\n", somestr);85	ret = sys_mprotect((void *)ptr, page_size, PROT_READ);86	FAIL_TEST_IF_FALSE(!ret);87 88	maps = fopen("/proc/self/maps", "r");89	FAIL_TEST_IF_FALSE(maps);90 91	/*92	 * apply sealing to elf binary93	 */94	while (fgets(line, sizeof(line), maps)) {95		if (sscanf(line, "%lx-%lx %4s %*x %*x:%*x %*u %255[^\n]",96			&addr_start, &addr_end, prot, filename) == 4) {97			if (strlen(filename)) {98				/*99				 * seal the mapping if read only.100				 */101				if (strstr(prot, "r-")) {102					ret = sys_mseal((void *)addr_start, addr_end - addr_start);103					FAIL_TEST_IF_FALSE(!ret);104					ksft_print_msg("sealed: %lx-%lx %s %s\n",105						addr_start, addr_end, prot, filename);106					if ((uintptr_t) somestr >= addr_start &&107						(uintptr_t) somestr <= addr_end)108						ksft_print_msg("mapping for somestr found\n");109				}110			}111		}112	}113	fclose(maps);114 115	ret = sys_mprotect((void *)ptr, page_size, PROT_READ | PROT_WRITE);116	FAIL_TEST_IF_FALSE(ret < 0);117	ksft_print_msg("somestr is sealed, mprotect is rejected\n");118 119	REPORT_TEST_PASS();120}121 122int main(int argc, char **argv)123{124	bool test_seal = seal_support();125 126	ksft_print_header();127	ksft_print_msg("pid=%d\n", getpid());128 129	if (!test_seal)130		ksft_exit_skip("sealing not supported, check CONFIG_64BIT\n");131 132	ksft_set_plan(1);133 134	test_seal_elf();135 136	ksft_finished();137}138