/*
 * Behavioral spot-check of the native sysent[] table edge cases:
 *   1. syscall numbers >= SYS_MAXSYSCALL (556) and just below it  -> SIGSYS path, no OOB
 *   2. lkmnosys slot 210 -> SIGSYS, slot 219 -> SIGSYS
 *   3. obsolete slot 11 -> SIGSYS
 *   4. mmap (7-arg syscall: exercises the narg>regcnt=6 stack-arg copyin)
 *   5. mmap via indirect syscall(197,...) (exercises sys_xsyscall regcnt=5 path + copyin of 2 stack args)
 *   6. lseek 64-bit result (rsize=8) returns full 64-bit offset
 *   7. getrandom (rsize=8) sanity
 * Build: cc -o sysent_edge sysent_edge.c
 */
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

static int sigsys_count;
static void onsig(int s __unused) { sigsys_count++; _exit(77); }

static long sc(long n, long a, long b, long c, long d, long e, long f, long g)
{
	return syscall(n, a, b, c, d, e, f, g);
}

int main(void)
{
	signal(SIGSYS, onsig);
	int fail = 0;

	/* 1. out-of-range syscall numbers must not crash the kernel */
	printf("[1] OOR syscalls: ");
	fflush(stdout);
	pid_t p = fork();
	if (p == 0) { sc(556,0,0,0,0,0,0,0); _exit(1); }
	int st; waitpid(p, &st, 0);
	printf("556->%s ", WIFSIGNALED(st) ? "SIGSYS" : "exit");
	p = fork();
	if (p == 0) { sc(0x7fffffff,0,0,0,0,0,0,0); _exit(1); }
	waitpid(p, &st, 0);
	printf("INT_MAX->%s ", WIFSIGNALED(st) ? "SIGSYS" : "exit");
	p = fork();
	if (p == 0) { sc(555,0,0,0,0,0,0,0); } /* futimesat: EINVAL via args, NOT SIGSYS-by-table */
	waitpid(p, &st, 0);
	printf("555->%s\n", WIFSIGNALED(st) ? "SIGSYS" : "no-signal");

	/* 2./3. lkm + obsolete slots -> SIGSYS */
	p = fork();
	if (p == 0) { sc(210,0,0,0,0,0,0,0); _exit(1); }
	waitpid(p, &st, 0);
	printf("[2] lkmnosys 210 -> %s\n", WIFSIGNALED(st) ? "SIGSYS" : "no-signal");
	p = fork();
	if (p == 0) { sc(11,0,0,0,0,0,0,0); _exit(1); }
	waitpid(p, &st, 0);
	printf("[3] obsolete 11  -> %s\n", WIFSIGNALED(st) ? "SIGSYS" : "no-signal");

	/* 4. direct 7-arg mmap */
	void *m = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
	printf("[4] direct mmap = %p\n", m);
	if (m == MAP_FAILED) fail++;

	/* 5. indirect mmap via syscall(197,...): code in rdi, 6 args in rsi.., last from stack */
	long im = sc(SYS_syscall, 197, 0, 4096, PROT_READ|PROT_WRITE,
		     MAP_ANON|MAP_PRIVATE, -1, 0);
	printf("[5] indirect mmap = 0x%lx\n", (unsigned long)im);
	if (im == -1) fail++;

	/* 5b. indirect __syscall(198,...) variant */
	long im2 = sc(SYS___syscall, 197, 0, 4096, PROT_READ|PROT_WRITE,
		      MAP_ANON|MAP_PRIVATE, -1, 0);
	printf("[5b] indirect __syscall mmap = 0x%lx\n", (unsigned long)im2);
	if (im2 == -1) fail++;

	/* 6. lseek 64-bit result across the 2^32 boundary */
	int fd = open("/tmp/sysent_edge.tmp", O_RDWR|O_CREAT, 0600);
	if (fd >= 0) {
		off_t r = lseek(fd, 0x100000000LL, SEEK_SET);
		printf("[6] lseek(4GiB) = %lld (errno path %d)\n", (long long)r, errno);
		if (r < 0) fail++;
		close(fd); unlink("/tmp/sysent_edge.tmp");
	}

	/* 7. getrandom rsize=8 */
	unsigned char rb[8];
	long gr = syscall(SYS_getrandom, rb, 8, 0);
	printf("[7] getrandom = %ld\n", gr);
	if (gr != 8) fail++;

	printf(fail ? "RESULT: FAIL(%d)\n" : "RESULT: PASS\n", fail);
	return fail ? 1 : 0;
}
