Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
fac59a22b0 | |||
e598e6a20b | |||
6568720c6d |
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "extern/Unity"]
|
||||
path = extern/Unity
|
||||
url = https://github.com/ThrowTheSwitch/Unity.git
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -1,4 +0,0 @@
|
||||
{
|
||||
"editor.defaultFormatter": "ms-vscode.cpptools",
|
||||
"editor.formatOnSave": true
|
||||
}
|
4
examples/cp/.gitignore
vendored
4
examples/cp/.gitignore
vendored
@ -1 +1,3 @@
|
||||
cp_priv_sep
|
||||
c
|
||||
c_cgroup
|
||||
ml
|
||||
|
@ -1,17 +1,13 @@
|
||||
C=clang
|
||||
|
||||
all: c cp_priv_sep c_cgroup ml
|
||||
all: c c_cgroup ml
|
||||
|
||||
clean:
|
||||
rm -f c cp_priv_sep c_cgroup ml
|
||||
rm -f c ml
|
||||
|
||||
c: cp.c
|
||||
${C} -o c cp.c
|
||||
|
||||
cp_priv_sep: cp_priv_sep.c ../../lib/clone3.c ../../include/clone3.h
|
||||
${C} -I../../include -o cp_priv_sep cp_priv_sep.c ../../lib/clone3.c
|
||||
sudo setcap CAP_SYS_ADMIN+eip ./cp_priv_sep
|
||||
|
||||
c_cgroup: cp_cgroup.c
|
||||
${C} -o c_cgroup cp_cgroup.c
|
||||
|
||||
|
@ -31,7 +31,37 @@ off_t get_file_size(int fd) {
|
||||
/*
|
||||
* Move self to a leaf node of the cgroup.
|
||||
*/
|
||||
int leaf_self() {}
|
||||
int leaf_self() {
|
||||
int cgroup_fd = open("/proc/self/cgroup", O_RDONLY);
|
||||
if (cgroup_fd == -1) {
|
||||
perror("open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lseek(cgroup_fd, 3, SEEK_SET) == -1) {
|
||||
perror("lseek");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char cgroup_root_dir[1024] = "/sys/fs/cgroup";
|
||||
|
||||
off_t len;
|
||||
if ((len = read(cgroup_fd, cgroup_root_dir + 14, 1010)) == -1) {
|
||||
perror("read");
|
||||
return -1;
|
||||
}
|
||||
cgroup_root_dir[len + 17] = 0x00;
|
||||
|
||||
fprintf(stderr, "%s\n", cgroup_root_dir);
|
||||
|
||||
int cgroup_dd = open(cgroup_root_dir, O_DIRECTORY);
|
||||
if (cgroup_dd == -1) {
|
||||
perror("open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the copy between the two file descriptors.
|
||||
@ -112,6 +142,8 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
// setup a cgroup for the child
|
||||
if (leaf_self() == -1)
|
||||
return -1;
|
||||
|
||||
// wait for the child to pause and restart it
|
||||
int status;
|
||||
|
0
examples/cp/cp_effects.ml
Normal file
0
examples/cp/cp_effects.ml
Normal file
@ -1,154 +0,0 @@
|
||||
// For privilege separation
|
||||
#include <clone3.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/wait.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// This program
|
||||
#include <stdio.h>
|
||||
|
||||
#define BUF_SIZE 4096
|
||||
|
||||
struct copy_args {
|
||||
char *src;
|
||||
char *dst;
|
||||
};
|
||||
|
||||
int process_args(int argc, char **argv, struct copy_args *);
|
||||
int do_copy(struct copy_args *args);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
pid_t child;
|
||||
|
||||
// Spawn args processor
|
||||
int args_pid_fd;
|
||||
|
||||
struct clone_args args_processor_cl_args = {
|
||||
.flags = CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWNS | CLONE_NEWPID |
|
||||
CLONE_NEWUSER | CLONE_NEWUTS | CLONE_PIDFD,
|
||||
.pidfd = (uint64_t)&args_pid_fd,
|
||||
.child_tid = (uint64_t)NULL,
|
||||
.parent_tid = (uint64_t)NULL,
|
||||
.exit_signal = SIGCHLD,
|
||||
.stack = (uint64_t)NULL,
|
||||
.stack_size = 0,
|
||||
.tls = (uint64_t)NULL,
|
||||
};
|
||||
|
||||
int args_pipe_fds[2];
|
||||
if (pipe(args_pipe_fds) < 0) {
|
||||
perror("pipe");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ((child = clone3(&args_processor_cl_args)) == 0) {
|
||||
char args[sizeof(struct copy_args)];
|
||||
|
||||
int code = process_args(argc, argv, &args);
|
||||
if (code != 0) {
|
||||
exit(code);
|
||||
}
|
||||
|
||||
write(args_pipe_fds[1], &args, sizeof(args));
|
||||
exit(0);
|
||||
} else if (child < 0) {
|
||||
perror("clone3");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Wait for args processor
|
||||
// Implicit assertion that sizeof(args) < the pipe buffer size (won't block)
|
||||
siginfo_t status;
|
||||
if (waitid(P_PIDFD, args_pid_fd, &status, WEXITED) == -1) {
|
||||
perror("waitid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status.si_status != 0) {
|
||||
return status.si_status;
|
||||
}
|
||||
|
||||
char args[sizeof(struct copy_args)];
|
||||
read(args_pipe_fds[0], &args, sizeof(args));
|
||||
|
||||
// Spawn copier (can be more separated)
|
||||
int copy_pid_fd;
|
||||
|
||||
struct clone_args do_copy_cl_args = {
|
||||
.flags = CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWUTS |
|
||||
CLONE_PIDFD,
|
||||
.pidfd = (uint64_t)©_pid_fd,
|
||||
.child_tid = (uint64_t)NULL,
|
||||
.parent_tid = (uint64_t)NULL,
|
||||
.exit_signal = SIGCHLD,
|
||||
.stack = (uint64_t)NULL,
|
||||
.stack_size = 0,
|
||||
.tls = (uint64_t)NULL,
|
||||
};
|
||||
|
||||
if ((child = clone3(&do_copy_cl_args)) == 0) {
|
||||
int code = do_copy(&args);
|
||||
exit(code);
|
||||
} else if (child < 0) {
|
||||
perror("clone3");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (waitid(P_PIDFD, copy_pid_fd, &status, WEXITED) == -1) {
|
||||
perror("waitid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return status.si_status;
|
||||
}
|
||||
|
||||
int process_args(int argc, char **argv, struct copy_args *args) {
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "usage: %s SRC DST\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
args->src = argv[1];
|
||||
args->dst = argv[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_copy(struct copy_args *args) {
|
||||
fprintf(stderr, "src: `%s`; dst: `%s`\n", args->src, args->dst);
|
||||
int src_fd, dst_fd;
|
||||
|
||||
if ((src_fd = open(args->src, O_RDONLY)) < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
if ((dst_fd = open(args->dst, O_WRONLY | O_CREAT | O_TRUNC)) < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
while (1) {
|
||||
int read_bytes = read(src_fd, buf, BUF_SIZE);
|
||||
if (read_bytes < 0) {
|
||||
perror("read");
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
if (!read_bytes) {
|
||||
fprintf(stderr, "copy complete\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (write(dst_fd, buf, read_bytes) < 0) {
|
||||
perror("write");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1
examples/echo/.gitignore
vendored
1
examples/echo/.gitignore
vendored
@ -1 +0,0 @@
|
||||
echo_priv_sep
|
@ -1,10 +0,0 @@
|
||||
C=clang -Wall
|
||||
|
||||
all: echo_priv_sep
|
||||
|
||||
clean:
|
||||
rm -f echo_priv_sep
|
||||
|
||||
echo_priv_sep: echo_priv_sep.c ../../lib/clone3.c ../../include/clone3.h
|
||||
${C} -I../../include -o echo_priv_sep echo_priv_sep.c ../../lib/clone3.c
|
||||
sudo setcap CAP_SYS_ADMIN+eip ./echo_priv_sep
|
0
examples/echo/echo.c
Normal file
0
examples/echo/echo.c
Normal file
0
examples/echo/echo.ml
Normal file
0
examples/echo/echo.ml
Normal file
0
examples/echo/echo_effects.ml
Normal file
0
examples/echo/echo_effects.ml
Normal file
0
examples/echo/echo_priv.c
Normal file
0
examples/echo/echo_priv.c
Normal file
@ -1,196 +0,0 @@
|
||||
// For privilege separation
|
||||
#include <clone3.h>
|
||||
|
||||
#include <linux/wait.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// This program
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
|
||||
int real_main(int, char **, int);
|
||||
int request_handler(int);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
pid_t child;
|
||||
|
||||
int num_pids = 2;
|
||||
int pid_fds[num_pids];
|
||||
|
||||
// Create IPC
|
||||
int pipe_fds[2];
|
||||
if (pipe(pipe_fds) < 0) {
|
||||
perror("pipe");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Spawn real_main
|
||||
// Use CLONE_FILES to have the opened fds passed up
|
||||
struct clone_args real_main_cl_args = {
|
||||
.flags = CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUSER |
|
||||
CLONE_NEWUTS | CLONE_PIDFD | CLONE_FILES,
|
||||
.pidfd = (uint64_t)&pid_fds[0],
|
||||
.child_tid = (uint64_t)NULL,
|
||||
.parent_tid = (uint64_t)NULL,
|
||||
.exit_signal = SIGCHLD,
|
||||
.stack = (uint64_t)NULL,
|
||||
.stack_size = 0,
|
||||
.tls = (uint64_t)NULL,
|
||||
};
|
||||
|
||||
if ((child = clone3(&real_main_cl_args)) == 0) {
|
||||
int code = real_main(argc, argv, pipe_fds[1]);
|
||||
exit(code);
|
||||
} else if (child < 0) {
|
||||
perror("clone3");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Spawn internal cloner (to maintain capabilities)
|
||||
// Use CLONE_FILES to pass the opened fds down
|
||||
struct clone_args process_generator_cl_args = {
|
||||
.flags = CLONE_FILES,
|
||||
.pidfd = (uint64_t)&pid_fds[1],
|
||||
.child_tid = (uint64_t)NULL,
|
||||
.parent_tid = (uint64_t)NULL,
|
||||
.exit_signal = SIGCHLD,
|
||||
.stack = (uint64_t)NULL,
|
||||
.stack_size = 0,
|
||||
.tls = (uint64_t)NULL,
|
||||
};
|
||||
|
||||
if ((child = clone3(&process_generator_cl_args)) == 0) {
|
||||
int read_pipe = pipe_fds[0];
|
||||
|
||||
int client_fd;
|
||||
while (1) {
|
||||
int bytes_read = read(read_pipe, &client_fd, sizeof(client_fd));
|
||||
if (bytes_read == 0) {
|
||||
break;
|
||||
} else if (bytes_read < 0) {
|
||||
perror("read");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "got client_fd: %d\n", client_fd);
|
||||
|
||||
// Do not use CLONE_FILES for default CoW behaviour
|
||||
struct clone_args request_cl_args = {
|
||||
.flags = CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUSER |
|
||||
CLONE_NEWUTS | CLONE_PIDFD,
|
||||
.pidfd = (uint64_t)&pid_fds[0],
|
||||
.child_tid = (uint64_t)NULL,
|
||||
.parent_tid = (uint64_t)NULL,
|
||||
.exit_signal = SIGCHLD,
|
||||
.stack = (uint64_t)NULL,
|
||||
.stack_size = 0,
|
||||
.tls = (uint64_t)NULL,
|
||||
};
|
||||
|
||||
if ((child = clone3(&request_cl_args)) == 0) {
|
||||
int code = request_handler(client_fd);
|
||||
exit(code);
|
||||
} else if (child < 0) {
|
||||
perror("clone3");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
} else if (child < 0) {
|
||||
perror("clone3");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Wait for child processes
|
||||
siginfo_t status;
|
||||
|
||||
for (int i = 0; i < num_pids; i++) {
|
||||
if (waitid(P_PIDFD, pid_fds[i], &status, WEXITED) == -1) {
|
||||
perror("waitid");
|
||||
return -1;
|
||||
}
|
||||
if (status.si_status != 0) {
|
||||
return status.si_status;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int real_main(int argc, char **argv, int write_pipe) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "expected 1 argument\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int port = atoi(argv[1]);
|
||||
|
||||
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (server_fd < 0) {
|
||||
perror("socket");
|
||||
}
|
||||
|
||||
int opt_val = 1;
|
||||
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof opt_val);
|
||||
|
||||
struct sockaddr_in server;
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
server.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
|
||||
perror("bind");
|
||||
}
|
||||
|
||||
if (listen(server_fd, 16) < 0) {
|
||||
perror("listen");
|
||||
}
|
||||
|
||||
while (1) {
|
||||
struct sockaddr_in client;
|
||||
socklen_t client_len = sizeof(client);
|
||||
|
||||
int client_fd = accept(server_fd, (struct sockaddr *)&client, &client_len);
|
||||
if (client_fd < 0) {
|
||||
perror("accept");
|
||||
}
|
||||
|
||||
write(write_pipe, &client_fd, sizeof(client_fd));
|
||||
fprintf(stderr, "sent client_fd: %d\n", client_fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int request_handler(int client_fd) {
|
||||
char buf[BUF_SIZE];
|
||||
while (1) {
|
||||
int read = recv(client_fd, buf, BUF_SIZE, 0);
|
||||
if (read < 0) {
|
||||
perror("recv");
|
||||
return read;
|
||||
}
|
||||
|
||||
if (!read) {
|
||||
fprintf(stderr, "connection terminated\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (send(client_fd, buf, read, 0) < 0) {
|
||||
perror("send");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1
examples/fib/.gitignore
vendored
1
examples/fib/.gitignore
vendored
@ -1 +0,0 @@
|
||||
fib_priv_sep
|
@ -1,10 +0,0 @@
|
||||
C=clang -Wall
|
||||
|
||||
all: fib_priv_sep
|
||||
|
||||
clean:
|
||||
rm -f fib_priv_sep
|
||||
|
||||
fib_priv_sep: fib_priv_sep.c ../../lib/clone3.c ../../include/clone3.h
|
||||
${C} -I../../include -o fib_priv_sep fib_priv_sep.c ../../lib/clone3.c
|
||||
sudo setcap CAP_SYS_ADMIN+eip ./fib_priv_sep
|
@ -1,76 +0,0 @@
|
||||
// For privilege separation
|
||||
#include <clone3.h>
|
||||
|
||||
#include <linux/wait.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
// This program
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
uint64_t fib(uint64_t i) {
|
||||
uint64_t a = 0;
|
||||
uint64_t b = 1;
|
||||
|
||||
for (; i > 0; i--) {
|
||||
uint64_t old_b = b;
|
||||
b = b + a;
|
||||
a = old_b;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
int real_main(int argc, char **argv);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int pid_fd;
|
||||
|
||||
struct clone_args cl_args = {
|
||||
.flags = CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWNS | CLONE_NEWPID |
|
||||
CLONE_NEWUSER | CLONE_NEWUTS | CLONE_PIDFD,
|
||||
.pidfd = (uint64_t)&pid_fd,
|
||||
.child_tid = (uint64_t)NULL,
|
||||
.parent_tid = (uint64_t)NULL,
|
||||
.exit_signal = SIGCHLD,
|
||||
.stack = (uint64_t)NULL,
|
||||
.stack_size = 0,
|
||||
.tls = (uint64_t)NULL,
|
||||
};
|
||||
|
||||
pid_t child = clone3(&cl_args);
|
||||
if (child < 0) {
|
||||
perror("clone3");
|
||||
exit(-1);
|
||||
} else if (child == 0) {
|
||||
int code = real_main(argc, argv);
|
||||
exit(code);
|
||||
} else {
|
||||
siginfo_t status;
|
||||
if (waitid(P_PIDFD, pid_fd, &status, WEXITED) == -1) {
|
||||
perror("waitid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
exit(status.si_status);
|
||||
}
|
||||
}
|
||||
|
||||
int real_main(int argc, char **argv) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "expected 1 argument\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t i = 0;
|
||||
if (sscanf(argv[1], "%lu", &i) != 1) {
|
||||
fprintf(stderr, "sscanf failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t fib_result = fib(i);
|
||||
printf("fib(%lu) = %lu\n", i, fib_result);
|
||||
return 0;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
if (unshare(CLONE_NEWNS))
|
||||
perror("unshare");
|
||||
if (mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL))
|
||||
perror("mount");
|
||||
if (umount("/"))
|
||||
perror("umount");
|
||||
}
|
1
extern/Unity
vendored
Submodule
1
extern/Unity
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 8ba01386008196a92ef4fdbdb0b00f2434c79563
|
@ -1,3 +0,0 @@
|
||||
#include <linux/sched.h>
|
||||
|
||||
long clone3(struct clone_args *cl_args);
|
@ -1,7 +0,0 @@
|
||||
#include <clone3.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
long clone3(struct clone_args *cl_args) {
|
||||
return syscall(SYS_clone3, cl_args, sizeof(struct clone_args));
|
||||
}
|
Reference in New Issue
Block a user