The Pedigree Project 0.1
module-contract-test/main.c
1/* Copyright (c) 2026, Pedigree Developers. */
2#define _GNU_SOURCE
3#include <errno.h>
4#include <fcntl.h>
5#include <signal.h>
6#include <stdio.h>
7#include <string.h>
8#include <unistd.h>
9
10#include <sys/wait.h>
11
12extern int delete_module(const char*, unsigned int);
13
14static int expect_error(const char* name, unsigned int flags, int expected) {
15 errno = 0;
16 int result = delete_module(name, flags);
17 if (result != -1 || errno != expected) {
18 fprintf(stderr, "delete_module flags=%x returned %d errno=%d expected=%d\n", flags, result,
19 errno, expected);
20 return 1;
21 }
22 return 0;
23}
24
25int main(void) {
26 setvbuf(stdout, NULL, _IONBF, 0);
27 alarm(30);
28 puts("MODULE-CONTRACT: BEGIN");
29 if (geteuid() != 0) {
30 fputs("MODULE-CONTRACT: FAIL requires root\n", stderr);
31 return 1;
32 }
33 char longName[64];
34 memset(longName, 'x', sizeof(longName));
35 longName[sizeof(longName) - 1] = 0;
36 if (expect_error(NULL, 0, EFAULT) || expect_error("", 0, ENOENT) ||
37 expect_error(longName, 0, ENOENT) || expect_error("missing-module", 0, ENOENT) ||
38 expect_error("module-unload-fixture", 1, EINVAL) ||
39 expect_error("module-unload-fixture", O_TRUNC, EOPNOTSUPP) ||
40 expect_error("posix", O_NONBLOCK, EBUSY) || expect_error("linker", O_NONBLOCK, EBUSY) ||
41 expect_error("vfs", O_NONBLOCK, EWOULDBLOCK)) {
42 puts("MODULE-CONTRACT: FAIL input-and-policy");
43 return 1;
44 }
45 puts("MODULE-CONTRACT: PASS input-and-policy");
46
47 pid_t child = fork();
48 if (!child) {
49 if (setuid(65534))
50 _exit(2);
51 _exit(expect_error("module-unload-fixture", O_NONBLOCK, EPERM));
52 }
53 int status = 0;
54 if (child < 0 || waitpid(child, &status, 0) != child || !WIFEXITED(status) ||
55 WEXITSTATUS(status)) {
56 puts("MODULE-CONTRACT: FAIL credentials");
57 return 1;
58 }
59 puts("MODULE-CONTRACT: PASS credentials");
60
61 errno = 0;
62 if (delete_module("module-unload-fixture", O_NONBLOCK)) {
63 fprintf(stderr, "MODULE-CONTRACT: FAIL unload errno=%d\n", errno);
64 return 1;
65 }
66 puts("MODULE-CONTRACT: PASS unload");
67 if (expect_error("module-unload-fixture", 0, ENOENT)) {
68 puts("MODULE-CONTRACT: FAIL repeated-unload");
69 return 1;
70 }
71 puts("MODULE-CONTRACT: PASS repeated-unload");
72 puts("MODULE-CONTRACT: END PASS");
73 return 0;
74}