brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 57ec5e9 Raw
186 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * ioperm.c - Test case for ioperm(2)4 * Copyright (c) 2015 Andrew Lutomirski5 */6 7#define _GNU_SOURCE8#include <err.h>9#include <stdio.h>10#include <stdint.h>11#include <signal.h>12#include <setjmp.h>13#include <stdlib.h>14#include <string.h>15#include <errno.h>16#include <unistd.h>17#include <sys/types.h>18#include <sys/wait.h>19#include <stdbool.h>20#include <sched.h>21#include <sys/io.h>22 23static int nerrs = 0;24 25static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),26		       int flags)27{28	struct sigaction sa;29	memset(&sa, 0, sizeof(sa));30	sa.sa_sigaction = handler;31	sa.sa_flags = SA_SIGINFO | flags;32	sigemptyset(&sa.sa_mask);33	if (sigaction(sig, &sa, 0))34		err(1, "sigaction");35 36}37 38static void clearhandler(int sig)39{40	struct sigaction sa;41	memset(&sa, 0, sizeof(sa));42	sa.sa_handler = SIG_DFL;43	sigemptyset(&sa.sa_mask);44	if (sigaction(sig, &sa, 0))45		err(1, "sigaction");46}47 48static jmp_buf jmpbuf;49 50static void sigsegv(int sig, siginfo_t *si, void *ctx_void)51{52	siglongjmp(jmpbuf, 1);53}54 55static bool try_outb(unsigned short port)56{57	sethandler(SIGSEGV, sigsegv, SA_RESETHAND);58	if (sigsetjmp(jmpbuf, 1) != 0) {59		return false;60	} else {61		asm volatile ("outb %%al, %w[port]"62			      : : [port] "Nd" (port), "a" (0));63		return true;64	}65	clearhandler(SIGSEGV);66}67 68static void expect_ok(unsigned short port)69{70	if (!try_outb(port)) {71		printf("[FAIL]\toutb to 0x%02hx failed\n", port);72		exit(1);73	}74 75	printf("[OK]\toutb to 0x%02hx worked\n", port);76}77 78static void expect_gp(unsigned short port)79{80	if (try_outb(port)) {81		printf("[FAIL]\toutb to 0x%02hx worked\n", port);82		exit(1);83	}84 85	printf("[OK]\toutb to 0x%02hx failed\n", port);86}87 88int main(void)89{90	cpu_set_t cpuset;91	CPU_ZERO(&cpuset);92	CPU_SET(0, &cpuset);93	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)94		err(1, "sched_setaffinity to CPU 0");95 96	expect_gp(0x80);97	expect_gp(0xed);98 99	/*100	 * Probe for ioperm support.  Note that clearing ioperm bits101	 * works even as nonroot.102	 */103	printf("[RUN]\tenable 0x80\n");104	if (ioperm(0x80, 1, 1) != 0) {105		printf("[OK]\tioperm(0x80, 1, 1) failed (%d) -- try running as root\n",106		       errno);107		return 0;108	}109	expect_ok(0x80);110	expect_gp(0xed);111 112	printf("[RUN]\tdisable 0x80\n");113	if (ioperm(0x80, 1, 0) != 0) {114		printf("[FAIL]\tioperm(0x80, 1, 0) failed (%d)", errno);115		return 1;116	}117	expect_gp(0x80);118	expect_gp(0xed);119 120	/* Make sure that fork() preserves ioperm. */121	if (ioperm(0x80, 1, 1) != 0) {122		printf("[FAIL]\tioperm(0x80, 1, 0) failed (%d)", errno);123		return 1;124	}125 126	pid_t child = fork();127	if (child == -1)128		err(1, "fork");129 130	if (child == 0) {131		printf("[RUN]\tchild: check that we inherited permissions\n");132		expect_ok(0x80);133		expect_gp(0xed);134		printf("[RUN]\tchild: Extend permissions to 0x81\n");135		if (ioperm(0x81, 1, 1) != 0) {136			printf("[FAIL]\tioperm(0x81, 1, 1) failed (%d)", errno);137			return 1;138		}139		printf("[RUN]\tchild: Drop permissions to 0x80\n");140		if (ioperm(0x80, 1, 0) != 0) {141			printf("[FAIL]\tioperm(0x80, 1, 0) failed (%d)", errno);142			return 1;143		}144		expect_gp(0x80);145		return 0;146	} else {147		int status;148		if (waitpid(child, &status, 0) != child ||149		    !WIFEXITED(status)) {150			printf("[FAIL]\tChild died\n");151			nerrs++;152		} else if (WEXITSTATUS(status) != 0) {153			printf("[FAIL]\tChild failed\n");154			nerrs++;155		} else {156			printf("[OK]\tChild succeeded\n");157		}158	}159 160	/* Verify that the child dropping 0x80 did not affect the parent */161	printf("\tVerify that unsharing the bitmap worked\n");162	expect_ok(0x80);163 164	/* Test the capability checks. */165	printf("\tDrop privileges\n");166	if (setresuid(1, 1, 1) != 0) {167		printf("[WARN]\tDropping privileges failed\n");168		return 0;169	}170 171	printf("[RUN]\tdisable 0x80\n");172	if (ioperm(0x80, 1, 0) != 0) {173		printf("[FAIL]\tioperm(0x80, 1, 0) failed (%d)", errno);174		return 1;175	}176	printf("[OK]\tit worked\n");177 178	printf("[RUN]\tenable 0x80 again\n");179	if (ioperm(0x80, 1, 1) == 0) {180		printf("[FAIL]\tit succeeded but should have failed.\n");181		return 1;182	}183	printf("[OK]\tit failed\n");184	return 0;185}186