Initial version
This commit is contained in:
parent
3f5f72f940
commit
2c397da373
3 changed files with 127 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
pidjail
|
5
Makefile
Normal file
5
Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
all: pidjail
|
||||
|
||||
pidjail: main.c
|
||||
gcc -o $@ $^
|
||||
chmod u+s $@
|
121
main.c
Normal file
121
main.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
// we need this so sched.h exports unshare and CLONE_*
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
char** argdup(int argc, const char** argv)
|
||||
{
|
||||
char** newargs = malloc(sizeof(char*) * (argc+1));
|
||||
for(size_t i = 0; i < argc; i++)
|
||||
{
|
||||
newargs[i] = strdup(argv[i]);
|
||||
}
|
||||
newargs[argc] = NULL;
|
||||
return newargs;
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
if(argc == 1) {
|
||||
printf("Usage: pidjail PROGRAM ARGUMENTS...\n"
|
||||
"Run command within its own pid namespace. Integrated init process.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// next fork shall be in a new pid namespace
|
||||
if (unshare(CLONE_NEWPID) != 0)
|
||||
{
|
||||
int err = errno;
|
||||
printf("Failed to unshare pid namespace (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
int err = errno;
|
||||
printf("Failed to fork (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
// parent waits for child then exits
|
||||
int status;
|
||||
if(waitpid(pid, &status, 0) == -1)
|
||||
{
|
||||
int err = errno;
|
||||
printf("Failed to wait (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Child should be in new pid namespace and
|
||||
// functions as the the init process
|
||||
// it needs to fork again then wait for any child.
|
||||
// if the forked child exits then exit.
|
||||
|
||||
pid = fork();
|
||||
if (pid != 0)
|
||||
{
|
||||
// Init process wait for anything and exit if first child exits.
|
||||
pid_t first_child = pid;
|
||||
pid_t exited_child;
|
||||
int child_status;
|
||||
int err;
|
||||
do {
|
||||
exited_child = wait(&child_status);
|
||||
err = errno;
|
||||
} while(exited_child != first_child && exited_child != -1);
|
||||
|
||||
if (exited_child == -1)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
int exit_code = WEXITSTATUS(child_status);
|
||||
return exit_code;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// First child of init process. do exec here
|
||||
// use cli arguments for subprocess. skip 0 as it's our programs name.
|
||||
|
||||
// Drop root privileges
|
||||
if (seteuid(getuid()) == -1)
|
||||
{
|
||||
int err = errno;
|
||||
printf("Failed to drop root privileges with seteuid (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (setegid(getgid()) == -1)
|
||||
{
|
||||
int err = errno;
|
||||
printf("Failed to drop root privileges with setegid (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
char** newargs = argdup(argc-1, &argv[1]);
|
||||
|
||||
if (execv(newargs[0], newargs) == -1)
|
||||
{
|
||||
printf("Failed to exec (%d)\n", errno);
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue