Fix pledge to process lists with zero index syscalls (#402)

This commit is contained in:
Paul Kulchenko 2022-05-06 20:55:28 -07:00 committed by GitHub
parent 15c59e716f
commit b30f5c0c4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -33,7 +33,6 @@
static const uint16_t kPledgeLinuxDefault[] = { static const uint16_t kPledgeLinuxDefault[] = {
__NR_linux_exit, // __NR_linux_exit, //
__NR_linux_exit_group, // __NR_linux_exit_group, //
0, //
}; };
static const uint16_t kPledgeLinuxStdio[] = { static const uint16_t kPledgeLinuxStdio[] = {
@ -96,7 +95,6 @@ static const uint16_t kPledgeLinuxStdio[] = {
__NR_linux_wait4, // __NR_linux_wait4, //
__NR_linux_write, // __NR_linux_write, //
__NR_linux_writev, // __NR_linux_writev, //
0, //
}; };
static const uint16_t kPledgeLinuxRpath[] = { static const uint16_t kPledgeLinuxRpath[] = {
@ -114,7 +112,6 @@ static const uint16_t kPledgeLinuxRpath[] = {
__NR_linux_fchown, // __NR_linux_fchown, //
__NR_linux_fchownat, // __NR_linux_fchownat, //
__NR_linux_fstat, // __NR_linux_fstat, //
0, //
}; };
static const uint16_t kPledgeLinuxWpath[] = { static const uint16_t kPledgeLinuxWpath[] = {
@ -131,7 +128,6 @@ static const uint16_t kPledgeLinuxWpath[] = {
__NR_linux_fchown, // __NR_linux_fchown, //
__NR_linux_fchownat, // __NR_linux_fchownat, //
__NR_linux_fstat, // __NR_linux_fstat, //
0, //
}; };
static const uint16_t kPledgeLinuxCpath[] = { static const uint16_t kPledgeLinuxCpath[] = {
@ -146,12 +142,10 @@ static const uint16_t kPledgeLinuxCpath[] = {
__NR_linux_mkdir, // __NR_linux_mkdir, //
__NR_linux_mkdirat, // __NR_linux_mkdirat, //
__NR_linux_rmdir, // __NR_linux_rmdir, //
0, //
}; };
static const uint16_t kPledgeLinuxDpath[] = { static const uint16_t kPledgeLinuxDpath[] = {
__NR_linux_mknod, // __NR_linux_mknod, //
0, //
}; };
static const uint16_t kPledgeLinuxTmppath[] = { static const uint16_t kPledgeLinuxTmppath[] = {
@ -160,7 +154,6 @@ static const uint16_t kPledgeLinuxTmppath[] = {
__NR_linux_chown, // __NR_linux_chown, //
__NR_linux_unlink, // __NR_linux_unlink, //
__NR_linux_fstat, // __NR_linux_fstat, //
0, //
}; };
static const uint16_t kPledgeLinuxInet[] = { static const uint16_t kPledgeLinuxInet[] = {
@ -174,7 +167,6 @@ static const uint16_t kPledgeLinuxInet[] = {
__NR_linux_getsockname, // __NR_linux_getsockname, //
__NR_linux_setsockopt, // __NR_linux_setsockopt, //
__NR_linux_getsockopt, // __NR_linux_getsockopt, //
0, //
}; };
static const uint16_t kPledgeLinuxFattr[] = { static const uint16_t kPledgeLinuxFattr[] = {
@ -188,7 +180,6 @@ static const uint16_t kPledgeLinuxFattr[] = {
__NR_linux_lchown, // __NR_linux_lchown, //
__NR_linux_fchown, // __NR_linux_fchown, //
__NR_linux_utimes, // __NR_linux_utimes, //
0, //
}; };
static const uint16_t kPledgeLinuxUnix[] = { static const uint16_t kPledgeLinuxUnix[] = {
@ -202,7 +193,6 @@ static const uint16_t kPledgeLinuxUnix[] = {
__NR_linux_getsockname, // __NR_linux_getsockname, //
__NR_linux_setsockopt, // __NR_linux_setsockopt, //
__NR_linux_getsockopt, // __NR_linux_getsockopt, //
0, //
}; };
static const uint16_t kPledgeLinuxDns[] = { static const uint16_t kPledgeLinuxDns[] = {
@ -210,7 +200,6 @@ static const uint16_t kPledgeLinuxDns[] = {
__NR_linux_recvfrom, // __NR_linux_recvfrom, //
__NR_linux_socket, // __NR_linux_socket, //
__NR_linux_connect, // __NR_linux_connect, //
0, //
}; };
static const uint16_t kPledgeLinuxProc[] = { static const uint16_t kPledgeLinuxProc[] = {
@ -222,12 +211,10 @@ static const uint16_t kPledgeLinuxProc[] = {
__NR_linux_setrlimit, // __NR_linux_setrlimit, //
__NR_linux_setpgid, // __NR_linux_setpgid, //
__NR_linux_setsid, // __NR_linux_setsid, //
0, //
}; };
static const uint16_t kPledgeLinuxExec[] = { static const uint16_t kPledgeLinuxExec[] = {
__NR_linux_execve, // __NR_linux_execve, //
0, //
}; };
static const uint16_t kPledgeLinuxId[] = { static const uint16_t kPledgeLinuxId[] = {
@ -241,27 +228,29 @@ static const uint16_t kPledgeLinuxId[] = {
__NR_linux_setrlimit, // __NR_linux_setrlimit, //
__NR_linux_getpriority, // __NR_linux_getpriority, //
__NR_linux_setpriority, // __NR_linux_setpriority, //
0, //
}; };
#define PLEDGELEN(pledge) pledge, ARRAYLEN(pledge)
static const struct Pledges { static const struct Pledges {
const char *name; const char *name;
const uint16_t *syscalls; const uint16_t *syscalls;
const size_t len;
} kPledgeLinux[] = { } kPledgeLinux[] = {
{"default", kPledgeLinuxDefault}, // {"default", PLEDGELEN(kPledgeLinuxDefault)}, //
{"stdio", kPledgeLinuxStdio}, // {"stdio", PLEDGELEN(kPledgeLinuxStdio)}, //
{"rpath", kPledgeLinuxRpath}, // {"rpath", PLEDGELEN(kPledgeLinuxRpath)}, //
{"wpath", kPledgeLinuxWpath}, // {"wpath", PLEDGELEN(kPledgeLinuxWpath)}, //
{"cpath", kPledgeLinuxCpath}, // {"cpath", PLEDGELEN(kPledgeLinuxCpath)}, //
{"dpath", kPledgeLinuxDpath}, // {"dpath", PLEDGELEN(kPledgeLinuxDpath)}, //
{"tmppath", kPledgeLinuxTmppath}, // {"tmppath", PLEDGELEN(kPledgeLinuxTmppath)}, //
{"inet", kPledgeLinuxInet}, // {"inet", PLEDGELEN(kPledgeLinuxInet)}, //
{"fattr", kPledgeLinuxFattr}, // {"fattr", PLEDGELEN(kPledgeLinuxFattr)}, //
{"unix", kPledgeLinuxUnix}, // {"unix", PLEDGELEN(kPledgeLinuxUnix)}, //
{"dns", kPledgeLinuxDns}, // {"dns", PLEDGELEN(kPledgeLinuxDns)}, //
{"proc", kPledgeLinuxProc}, // {"proc", PLEDGELEN(kPledgeLinuxProc)}, //
{"exec", kPledgeLinuxExec}, // {"exec", PLEDGELEN(kPledgeLinuxExec)}, //
{"id", kPledgeLinuxId}, // {"id", PLEDGELEN(kPledgeLinuxId)}, //
{0}, // {0}, //
}; };
@ -290,9 +279,9 @@ static bool AppendFilter(struct Filter *f, struct sock_filter *p, size_t n) {
return true; return true;
} }
static bool AppendPledge(struct Filter *f, const uint16_t *p) { static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len) {
int i; int i;
for (i = 0; p[i]; ++i) { for (i = 0; i < len; ++i) {
struct sock_filter fragment[] = {_SECCOMP_ALLOW_SYSCALL(p[i])}; struct sock_filter fragment[] = {_SECCOMP_ALLOW_SYSCALL(p[i])};
if (!AppendFilter(f, fragment, ARRAYLEN(fragment))) { if (!AppendFilter(f, fragment, ARRAYLEN(fragment))) {
return false; return false;
@ -301,10 +290,11 @@ static bool AppendPledge(struct Filter *f, const uint16_t *p) {
return true; return true;
} }
static const uint16_t *FindPledge(const struct Pledges *p, const char *name) { static const uint16_t *FindPledge(const struct Pledges *p, const char *name, size_t *len) {
int i; int i;
for (i = 0; p[i].name; ++i) { for (i = 0; p[i].name; ++i) {
if (!strcasecmp(name, p[i].name)) { if (!strcasecmp(name, p[i].name)) {
*len = p[i].len;
return p[i].syscalls; return p[i].syscalls;
} }
} }
@ -314,20 +304,21 @@ static const uint16_t *FindPledge(const struct Pledges *p, const char *name) {
static int sys_pledge_linux(const char *promises, const char *execpromises) { static int sys_pledge_linux(const char *promises, const char *execpromises) {
bool ok; bool ok;
int rc = -1; int rc = -1;
size_t plen;
struct Filter f = {0}; struct Filter f = {0};
const uint16_t *pledge; const uint16_t *pledge;
char *s, *tok, *state, *start; char *s, *tok, *state, *start;
if (execpromises) return einval(); if (execpromises) return einval();
if ((start = s = strdup(promises)) && if ((start = s = strdup(promises)) &&
AppendFilter(&f, kFilterStart, ARRAYLEN(kFilterStart)) && AppendFilter(&f, kFilterStart, ARRAYLEN(kFilterStart)) &&
AppendPledge(&f, kPledgeLinuxDefault)) { AppendPledge(&f, kPledgeLinuxDefault, ARRAYLEN(kPledgeLinuxDefault))) {
for (ok = true; (tok = strtok_r(start, " \t\r\n", &state)); start = 0) { for (ok = true; (tok = strtok_r(start, " \t\r\n", &state)); start = 0) {
if (!(pledge = FindPledge(kPledgeLinux, tok))) { if (!(pledge = FindPledge(kPledgeLinux, tok, &plen))) {
ok = false; ok = false;
rc = einval(); rc = einval();
break; break;
} }
if (!AppendPledge(&f, pledge)) { if (!AppendPledge(&f, pledge, plen)) {
ok = false; ok = false;
break; break;
} }