123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- #include <seccomp.h>
- #include <errno.h>
- #include <string.h>
- enum {
- PLEDGE_STDIO = 1 << 0,
- PLEDGE_PROC = 1 << 1,
- PLEDGE_EXEC = 1 << 2,
- };
- typedef struct {
- char *name;
- int mask;
- } promise;
- promise ptable[] = {
- { .name = "stdio", .mask = PLEDGE_STDIO },
- { .name = "rpath", .mask = 0 },
- { .name = "wpath", .mask = 0 },
- { .name = "cpath", .mask = 0 },
- { .name = "dpath", .mask = 0 },
- { .name = "tmppath", .mask = 0 },
- { .name = "inet", .mask = 0 },
- { .name = "fattr", .mask = 0 },
- { .name = "flock", .mask = 0 },
- { .name = "unix", .mask = 0 },
- { .name = "dns", .mask = 0 },
- { .name = "getpw", .mask = 0 },
- { .name = "sendfd", .mask = 0 },
- { .name = "recvfd", .mask = 0 },
- { .name = "ioctl", .mask = 0 },
- { .name = "tty", .mask = 0 },
- { .name = "proc", .mask = PLEDGE_PROC },
- { .name = "exec", .mask = PLEDGE_EXEC },
- { .name = "prot_exec", .mask = 0 },
- { .name = "settime", .mask = 0 },
- { .name = "ps", .mask = 0 },
- { .name = "vminfo", .mask = 0 },
- { .name = "id", .mask = 0 },
- { .name = "pf", .mask = 0 },
- { .name = "audio", .mask = 0 },
- };
- int
- pledge(const char *promises, const char *paths[])
- {
- int i, n, f;
- int flags = 0;
- int rc = -1;
- scmp_filter_ctx ctx;
- ctx = seccomp_init(SCMP_ACT_TRAP);
- if (!ctx) {
- errno = EACCES;
- goto out;
- }
- while (*promises) {
- // skip spaces
- while (*promises && *promises == ' ') promises++;
- // look for a token
- f = 0;
- for (i = 0; i < sizeof(ptable)/sizeof(*ptable); i++) {
- n = strlen(ptable[i].name);
- if (!strncmp(promises, ptable[i].name, n)) {
- // this can be removed once every promise has been implemented
- if (!ptable[i].mask) {
- errno = ENOSYS;
- goto out;
- }
- flags |= ptable[i].mask;
- promises += n;
- f = 1;
- break;
- }
- }
- // what we saw was not any valid token
- if (!f) {
- errno = EINVAL;
- goto out;
- }
- // ensure the token is terminated by a space or end of string
- if (*promises && *promises != ' ') {
- errno = EINVAL;
- goto out;
- }
- }
- #define RULE(syscall) \
- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(syscall), 0); \
- if (rc < 0) goto out
- // everyone is allowed to exit
- RULE(exit_group);
- if (flags & PLEDGE_STDIO) {
- RULE(read);
- RULE(write);
- RULE(open);
- RULE(close);
- RULE(stat);
- RULE(fstat);
- RULE(lstat);
- RULE(poll);
- RULE(lseek);
- RULE(dup);
- RULE(dup2);
- }
- if (flags & PLEDGE_PROC) {
- RULE(fork);
- RULE(vfork);
- RULE(kill);
- RULE(getpriority);
- RULE(setpriority);
- RULE(setrlimit);
- RULE(setpgid);
- RULE(setsid);
- }
- if (flags & PLEDGE_EXEC) {
- RULE(execve);
- }
- rc = seccomp_load(ctx);
- if (rc < 0) goto out;
- rc = 0;
- out:
- seccomp_release(ctx);
- return rc;
- }
|