brintos

brintos / linux-shallow public Read only

0
0
Text · 2.0 KiB · 96a976c Raw
93 lines · c
1// SPDX-License-Identifier: GPL-2.02#define _GNU_SOURCE3#include <sched.h>4#include <unistd.h>5#include <stdio.h>6#include <stdlib.h>7#include <signal.h>8#include <errno.h>9#include <sys/types.h>10#include <sys/stat.h>11#include <fcntl.h>12#include <sys/ioctl.h>13#include <sys/prctl.h>14#include <sys/wait.h>15 16#define NSIO    0xb717#define NS_GET_USERNS   _IO(NSIO, 0x1)18 19#define pr_err(fmt, ...) \20		({ \21			fprintf(stderr, "%s:%d:" fmt ": %m\n", \22				__func__, __LINE__, ##__VA_ARGS__); \23			1; \24		})25 26int main(int argc, char *argvp[])27{28	int pfd[2], ns, uns, init_uns;29	struct stat st1, st2;30	char path[128];31	pid_t pid;32	char c;33 34	if (pipe(pfd))35		return 1;36 37	pid = fork();38	if (pid < 0)39		return pr_err("fork");40	if (pid == 0) {41		prctl(PR_SET_PDEATHSIG, SIGKILL);42		if (unshare(CLONE_NEWUTS | CLONE_NEWUSER))43			return pr_err("unshare");44		close(pfd[0]);45		close(pfd[1]);46		while (1)47			sleep(1);48		return 0;49	}50	close(pfd[1]);51	if (read(pfd[0], &c, 1) != 0)52		return pr_err("Unable to read from pipe");53	close(pfd[0]);54 55	snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid);56	ns = open(path, O_RDONLY);57	if (ns < 0)58		return pr_err("Unable to open %s", path);59 60	uns = ioctl(ns, NS_GET_USERNS);61	if (uns < 0)62		return pr_err("Unable to get an owning user namespace");63 64	if (fstat(uns, &st1))65		return pr_err("fstat");66 67	snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);68	if (stat(path, &st2))69		return pr_err("stat");70 71	if (st1.st_ino != st2.st_ino)72		return pr_err("NS_GET_USERNS returned a wrong namespace");73 74	init_uns = ioctl(uns, NS_GET_USERNS);75	if (uns < 0)76		return pr_err("Unable to get an owning user namespace");77 78	if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)79		return pr_err("Don't get EPERM");80 81	if (unshare(CLONE_NEWUSER))82		return pr_err("unshare");83 84	if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM)85		return pr_err("Don't get EPERM");86	if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)87		return pr_err("Don't get EPERM");88 89	kill(pid, SIGKILL);90	wait(NULL);91	return 0;92}93