Files
snapd/src/seccomp.c
2015-04-21 19:44:52 -05:00

112 lines
2.7 KiB
C

#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <seccomp.h>
#include "utils.h"
char *filter_profile_dir = "/var/lib/snappy/seccomp/profiles/";
// strip whitespace from the end of the given string (inplace)
size_t trim_right(char *s, size_t slen) {
while(slen > 0 && isspace(s[slen - 1])) {
s[--slen] = 0;
}
return slen;
}
int seccomp_load_filters(const char *filter_profile)
{
debug("seccomp_load_filters %s", filter_profile);
int rc = 0;
int syscall_nr = -1;
scmp_filter_ctx ctx = NULL;
FILE *f = NULL;
size_t lineno = 0;
ctx = seccomp_init(SCMP_ACT_KILL);
if (ctx == NULL)
return ENOMEM;
if (getenv("SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR") != NULL)
filter_profile_dir = getenv("SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR");
char profile_path[128];
if (snprintf(profile_path, sizeof(profile_path), "%s/%s", filter_profile_dir, filter_profile) < 0) {
goto out;
}
f = fopen(profile_path, "r");
if (f == NULL) {
fprintf(stderr, "Can not open %s (%s)\n", profile_path, strerror(errno));
return -1;
}
// 80 characters + '\n' + '\0'
char buf[82];
while (fgets(buf, sizeof(buf), f) != NULL)
{
size_t len;
lineno++;
// comment, ignore
if(buf[0] == '#')
continue;
// ensure the entire line was read
len = strlen(buf);
if (len == 0)
continue;
else if (buf[len - 1] != '\n' && len > (sizeof(buf) - 2)) {
fprintf(stderr, "seccomp filter line %zu was too long (%zu characters max)\n", lineno, sizeof(buf) - 2);
rc = -1;
goto out;
}
// kill final newline
len = trim_right(buf, len);
if (len == 0)
continue;
// check for special "@unrestricted" command
if (strncmp(buf, "@unrestricted", sizeof(buf)) == 0)
goto out;
// syscall not available on this arch/kernel
// as this is a syscall whitelist its ok and the error can be ignored
syscall_nr = seccomp_syscall_resolve_name(buf);
if (syscall_nr == __NR_SCMP_ERROR)
continue;
// a normal line with a syscall
rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, syscall_nr, 0);
if (rc != 0) {
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall_nr, 0);
if (rc != 0) {
fprintf(stderr, "seccomp_rule_add failed with %i for '%s'\n", rc, buf);
goto out;
}
}
}
// load it into the kernel
rc = seccomp_load(ctx);
if (rc != 0) {
fprintf(stderr, "seccomp_load failed with %i\n", rc);
goto out;
}
out:
if (f != NULL) {
fclose(f);
}
seccomp_release(ctx);
return rc;
}