From b9878a86d60dc3d326e6877cfd30442de3d0c48a Mon Sep 17 00:00:00 2001 From: KenzieEdernez Date: Mon, 15 Dec 2025 03:15:30 +0700 Subject: [PATCH 1/2] Fixing and Improving Validation --- main.c | 8 ++++-- seccomp.c | 86 ++++++++++++++----------------------------------------- 2 files changed, 27 insertions(+), 67 deletions(-) diff --git a/main.c b/main.c index 98999c3..c48a88b 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ - - +/* For using free() */ +#include #include "seccomp.h" int main(int argc, char **argv) { @@ -13,7 +13,11 @@ int main(int argc, char **argv) { const char *profile_path = argv[1]; FILE *file = sc_must_read_and_validate_header_from_file(profile_path, &hdr); sc_must_read_filter_from_file(file, hdr.len_filter, &prog_allow); + /* Close file as we are done reading */ + fclose(file); sc_apply_seccomp_filter(&prog_allow); + /* Clear filter memory */ + free(prog_allow.filter); } diff --git a/seccomp.c b/seccomp.c index 27c5971..3dd28f9 100644 --- a/seccomp.c +++ b/seccomp.c @@ -1,74 +1,30 @@ -#include -#include -#include -#include -#include -#include -#include +#ifndef X_SECCOMP_H +#define X_SUPPORT_H -#include -#include -#include - -#include -#include -#include -#include "seccomp.h" +#include +#include -#define MAX_BPF_SIZE 32*1024 +#include -void die(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - vfprintf(stderr, msg, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(1); -} +/* Validations Constants */ +#define SC_HEADER_MAGIC_0 'S' +#define SC_HEADER_MAGIC_1 'C' +#define SC_VERSION 1 -FILE* sc_must_read_and_validate_header_from_file(const char *profile_path, struct sc_seccomp_file_header *hdr) -{ - FILE *file = fopen(profile_path, "rb"); - if (file == NULL) { - die("cannot open seccomp filter %s", profile_path); - } - size_t num_read = fread(hdr, 1, sizeof(struct sc_seccomp_file_header), file); - if (ferror(file) != 0) { - die("cannot read seccomp profile %s", profile_path); - } - if (num_read < sizeof(struct sc_seccomp_file_header)) { - die("short read on seccomp header: %zu", num_read); - } - return file; -} +struct sc_seccomp_file_header { + char header[2]; + uint8_t version; + uint8_t unrestricted; -void sc_must_read_filter_from_file(FILE *file, uint32_t len_bytes, struct sock_fprog *prog) -{ - prog->len = len_bytes / sizeof(struct sock_filter); - prog->filter = (struct sock_filter *)malloc(MAX_BPF_SIZE); - if (prog->filter == NULL) { - die("cannot allocate %u bytes of memory for seccomp filter ", len_bytes); - } - size_t num_read = fread(prog->filter, 1, len_bytes, file); - if (ferror(file)) { - die("cannot read filter"); - } - if (num_read != len_bytes) { - die("short read for filter %zu != %i", num_read, len_bytes); - } -} + uint32_t len_filter; + uint8_t reserved2[16]; +}; -int seccomp(unsigned int operation, unsigned int flags, void *args) { - errno = 0; - return syscall(__NR_seccomp, operation, flags, args); -} +void sc_must_read_filter_from_file(FILE *file, uint32_t len_bytes, struct sock_fprog *prog); +FILE* sc_must_read_and_validate_header_from_file(const char *profile_path, struct sc_seccomp_file_header *hdr); +void sc_apply_seccomp_filter(struct sock_fprog *prog); -void sc_apply_seccomp_filter(struct sock_fprog *prog) { - int err = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG, prog); - if (err != 0) { - die("cannot apply seccomp profile"); - } -} +void die(const char *fmt, ...); +#endif From 3d9f2f535419dcff599697bdf4166cc8a33aeefd Mon Sep 17 00:00:00 2001 From: KenzieEdernez Date: Mon, 15 Dec 2025 03:18:16 +0700 Subject: [PATCH 2/2] Fixing and Improving Validation --- seccomp.c | 114 ++++++++++++++++++++++++++++++++++++++++++++---------- seccomp.h | 5 +++ 2 files changed, 98 insertions(+), 21 deletions(-) diff --git a/seccomp.c b/seccomp.c index 3dd28f9..d1874b8 100644 --- a/seccomp.c +++ b/seccomp.c @@ -1,30 +1,102 @@ -#ifndef X_SECCOMP_H -#define X_SUPPORT_H - - -#include +#include +#include +#include #include +#include +#include +#include + +#include +#include +#include #include +#include +#include + +#include "seccomp.h" + +#define MAX_BPF_SIZE 32*1024 + +void die(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + +FILE* sc_must_read_and_validate_header_from_file(const char *profile_path, struct sc_seccomp_file_header *hdr) +{ + FILE *file = fopen(profile_path, "rb"); + if (file == NULL) { + die("cannot open seccomp filter %s", profile_path); + } + size_t num_read = fread(hdr, 1, sizeof(struct sc_seccomp_file_header), file); + if (ferror(file) != 0) { + die("cannot read seccomp profile %s", profile_path); + } + if (num_read < sizeof(struct sc_seccomp_file_header)) { + die("short read on seccomp header: %zu", num_read); + } + + /* Validation: Magic Bytes */ + if (hdr->header[0] != SC_HEADER_MAGIC_0 || hdr->header[1] != SC_HEADER_MAGIC_1) { + die("invalid seccomp file header magic"); + } + + /* Validation: Version */ + if (hdr->version != SC_VERSION) { + die("unsupported seccomp file version: %d", hdr->version); + } + + /* Validation: Filter Length (Size Limit) */ + if (hdr->len_filter > MAX_BPF_SIZE) { + die("seccomp filter too large: %u (max %d)", hdr->len_filter, MAX_BPF_SIZE); + } -/* Validations Constants */ -#define SC_HEADER_MAGIC_0 'S' -#define SC_HEADER_MAGIC_1 'C' -#define SC_VERSION 1 + /* Validation: Filter Length (Alignment) */ + if (hdr->len_filter % sizeof(struct sock_filter) != 0) { + die("invalid seccomp filter length: %u (must be multiple of %zu)", + hdr->len_filter, sizeof(struct sock_filter)); + } -struct sc_seccomp_file_header { - char header[2]; - uint8_t version; - uint8_t unrestricted; + return file; +} - uint32_t len_filter; - uint8_t reserved2[16]; -}; +void sc_must_read_filter_from_file(FILE *file, uint32_t len_bytes, struct sock_fprog *prog) +{ + /* Double check length before allocation */ + if (len_bytes > MAX_BPF_SIZE) { + die("filter length %u exceeds max %d", len_bytes, MAX_BPF_SIZE); + } -void sc_must_read_filter_from_file(FILE *file, uint32_t len_bytes, struct sock_fprog *prog); -FILE* sc_must_read_and_validate_header_from_file(const char *profile_path, struct sc_seccomp_file_header *hdr); -void sc_apply_seccomp_filter(struct sock_fprog *prog); + prog->len = len_bytes / sizeof(struct sock_filter); + + prog->filter = (struct sock_filter *)malloc(len_bytes); + if (prog->filter == NULL) { + die("cannot allocate %u bytes of memory for seccomp filter ", len_bytes); + } + + size_t num_read = fread(prog->filter, 1, len_bytes, file); + if (ferror(file)) { + die("cannot read filter"); + } + if (num_read != len_bytes) { + die("short read for filter %zu != %i", num_read, len_bytes); + } +} -void die(const char *fmt, ...); +int seccomp(unsigned int operation, unsigned int flags, void *args) { + errno = 0; + return syscall(__NR_seccomp, operation, flags, args); +} -#endif +void sc_apply_seccomp_filter(struct sock_fprog *prog) { + int err = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG, prog); + if (err != 0) { + die("cannot apply seccomp profile"); + } +} diff --git a/seccomp.h b/seccomp.h index d60ce6b..3dd28f9 100644 --- a/seccomp.h +++ b/seccomp.h @@ -7,6 +7,11 @@ #include +/* Validations Constants */ +#define SC_HEADER_MAGIC_0 'S' +#define SC_HEADER_MAGIC_1 'C' +#define SC_VERSION 1 + struct sc_seccomp_file_header { char header[2]; uint8_t version;