ms-runner/starter/ns_exec.c
2024-09-23 22:52:43 +05:00

79 lines
3.9 KiB
C

#include<sys/prctl.h>
#include<sys/mount.h>
#include<sys/stat.h>
static void procfs_prepare()
{
if (mkdir("/proc", 0555) && errno != EEXIST) die("Failed to mkdir /proc: %m\n");
if (mount("proc", "/proc", "proc", 0, "")) die("Failed to mount proc: %m\n");
}
#define hostname "runner"
#define put_old "oldfs"
void mnt_prepare(char* rootfs, char* shared_mountpoint) {
char* shared_folder = NULL;
asprintf(&shared_folder, "../%s", shared_mountpoint);
if (mount(rootfs, rootfs, "ext4", MS_BIND,"")) die("failed to mount %s: %m", rootfs);
if (chdir(rootfs)) die("falied to cd:%m");
//if (mount("/sys","sys","sysfs",0,"")) die("failed to mount sysfs: %m");
//if (mount("/dev","dev","udev",0,"")) die("failed to mount: %m");
if (mkdir("shared", 0777) && errno != EEXIST) die("Failed to mkdir %s: %m\n", shared_mountpoint);
if (mount(shared_folder, "shared", "ext4", MS_BIND, "")) die("failed to mount shared folder: %m");
if (mkdir(put_old, 0000) && errno != EEXIST) die("Failed to mkdir %s: %m\n", put_old);
if (syscall(SYS_pivot_root, ".", put_old)) die("Failed to pivot_root from %s to %s: %m\n", rootfs, put_old);
if (chdir("/")) die("Failed to chdir to new root: %m\n");
procfs_prepare();
if (umount2(put_old, MNT_DETACH)) die("Failed to umount put_old %s: %m\n", put_old);
if (rmdir(put_old)) die("Failed to rmdir: %m");
free(shared_folder);
}
void ro_fs(char* shared_mountpoint) {
char* shared_folder = malloc(strlen(shared_mountpoint)+4);
strcpy(shared_folder, "../");
strcat(shared_folder, shared_mountpoint);
if (mount("/", "/", "ext4", MS_REMOUNT | MS_RDONLY| MS_BIND, "")) die("failed to mount: %m");
if (mount(shared_mountpoint, "shared", "ext4", MS_REMOUNT | MS_BIND, "")) die("failed to mount: %m");
free(shared_folder);
}
#undef put_old
void await_setup(int pipe) { // wait for signal from parent
char buf[2];
if (read(pipe, buf, 2) != 2) die("Failed to read from pipe: %m\n");
}
static int nsrun(void* arg) {
//die when parent dies
if (prctl(PR_SET_PDEATHSIG, SIGKILL)) die("cannot PR_SET_PDEATHSIG for child process: %m\n");
struct params *params = (struct params*) arg;
await_setup(params->fd[0]);
char cwd[PATH_MAX];
if(getcwd(cwd, sizeof(cwd))==NULL) die("getcwd error: %m");
if(chdir(params->shared_folder)) die("failed to chdir to shared folder: %m")
int out_fd = open("out", O_WRONLY | O_CREAT, 0666);
if(out_fd == -1) die("unable to open output file:%m")
else dup2(out_fd, STDOUT_FILENO);
int in_fd = open("in", O_RDONLY | O_CREAT, 0666);
if(in_fd == -1) die("unable to open input file:%m")
else dup2(in_fd, STDIN_FILENO);
int err_fd = open("err", O_WRONLY | O_CREAT, 0666);
if(err_fd == -1) die("unable to open error file:%m")
else dup2(err_fd, STDERR_FILENO);
if(chdir(cwd)) die("failed to chdir: %m");
mnt_prepare("minrootfs", params->shared_folder);
sethostname(hostname, sizeof(hostname));
ro_fs(params->shared_folder);
if(setgid(1000)) die("failed to setgid:%m");
if(setuid(1000)) die("failed to setuid:%m");
char** argv = params->argv;
char* cmd = argv[0];
char* env[]={
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"PWD=/",
NULL,
};
if (execve(cmd, argv, env) == -1) die("failed to exec,%m");
return 1;// removes warning
}