diff --git a/launcher.c b/launcher.c index 4b71272..6109dcc 100644 --- a/launcher.c +++ b/launcher.c @@ -23,6 +23,7 @@ void print_help(char *self) { LOG_WARN(" --memory_limit memory limit in MB"); LOG_WARN(" --nproc_limit number of processes limit"); LOG_WARN(" --time_limit time limit in ms"); + LOG_WARN(" --fsize_limit write file size limit in MB"); LOG_WARN(" --sandbox_template sandbox template"); LOG_WARN(" --sandbox_action sandbox action"); LOG_WARN(" --uid user id"); @@ -40,6 +41,7 @@ void parse(int argc, char *argv[]) { [CFG_MEMORY_LIMIT] = {"memory_limit", required_argument, NULL, 0}, [CFG_NPROC_LIMIT] = {"nproc_limit", required_argument, NULL, 0}, [CFG_TIME_LIMIT] = {"time_limit", required_argument, NULL, 0}, + [CFG_FSIZE_LIMIT] = {"fsize_limit", required_argument, NULL, 0}, [CFG_SANDBOX_TEMPLATE] = {"sandbox_template", required_argument, NULL, 0}, [CFG_SANDBOX_ACTION] = {"sandbox_action", required_argument, NULL, 0}, [CFG_UID] = {"uid", optional_argument, NULL, 0}, @@ -57,9 +59,10 @@ void parse(int argc, char *argv[]) { while ((c = getopt_long_only(argc, argv, "", options, &idx)) != -1) { if (c != 0) break; - if (idx < CFG_IS_VALID) + if (idx < CFG_IS_VALID) { config[idx] = optarg; - else if (idx == CFG_IS_VALID) { + LOG_INFO("c = %d, x = %d, optarg = %s", c, idx, optarg); + } else if (idx == CFG_IS_VALID) { print_help(argv[0]); exit(0); } diff --git a/launcher.h b/launcher.h index 0dc3eb8..906f161 100644 --- a/launcher.h +++ b/launcher.h @@ -5,6 +5,7 @@ enum ConfigIndex { CFG_MEMORY_LIMIT = 0, CFG_NPROC_LIMIT, CFG_TIME_LIMIT, + CFG_FSIZE_LIMIT, CFG_SANDBOX_TEMPLATE, CFG_SANDBOX_ACTION, CFG_UID, diff --git a/library.c b/library.c index 3a3c891..2c00948 100644 --- a/library.c +++ b/library.c @@ -27,6 +27,7 @@ void setup_all(void) { config[CFG_MEMORY_LIMIT] = getenv(LIMIT_MEMORY); config[CFG_NPROC_LIMIT] = getenv(LIMIT_NPROC); config[CFG_TIME_LIMIT] = getenv(LIMIT_TIME); + config[CFG_FSIZE_LIMIT] = getenv(LIMIT_FSIZE); config[CFG_SANDBOX_TEMPLATE] = getenv(SANDBOX_TEMPLATE); config[CFG_SANDBOX_ACTION] = getenv(SANDBOX_ACTION); diff --git a/resource.c b/resource.c index 59635ab..c9629fa 100644 --- a/resource.c +++ b/resource.c @@ -21,12 +21,13 @@ void setup_rlimit(char *config[CFG_IS_VALID + 1]) { char *mem_limit_str = config[CFG_MEMORY_LIMIT]; // in mb char *nproc_limit_str = config[CFG_NPROC_LIMIT]; - char *time_limit_str = config[CFG_TIME_LIMIT]; // in ms + char *time_limit_str = config[CFG_TIME_LIMIT]; // in ms + char *fsize_limit_str = config[CFG_FSIZE_LIMIT]; // in mb - long mem_limit = 0, nproc_limit = 0, time_limit = 0; + long mem_limit = 0, nproc_limit = 0, time_limit = 0, fsize_limit = 0; if (mem_limit_str) { - // convert to bytes and double the memory limit + // convert to bytes mem_limit = strtol(mem_limit_str, NULL, 10) * 1024 * 1024; } @@ -39,7 +40,15 @@ void setup_rlimit(char *config[CFG_IS_VALID + 1]) { time_limit = limit ? (limit + 1000) / 1000 : 0; } + if (fsize_limit_str) { + // convert to bytes + fsize_limit = strtol(fsize_limit_str, NULL, 10) * 1024 * 1024; + } + SET_LIMIT(RLIMIT_AS, mem_limit, "memory", "bytes"); SET_LIMIT(RLIMIT_NPROC, nproc_limit, "nproc", "processes"); // per user, **not** subprocess SET_LIMIT(RLIMIT_CPU, time_limit, "time", "seconds"); // except blocked time + SET_LIMIT(RLIMIT_FSIZE, fsize_limit, "fsize", "bytes"); + + SET_LIMIT(RLIMIT_CORE, 0, "coredump", "bytes"); // disable core dump } diff --git a/resource.h b/resource.h index 25cf6a1..d2b4161 100644 --- a/resource.h +++ b/resource.h @@ -7,6 +7,7 @@ #define LIMIT_MEMORY "LIMIT_MEMORY" #define LIMIT_TIME "LIMIT_TIME" #define LIMIT_NPROC "LIMIT_NPROC" +#define LIMIT_FSIZE "LIMIT_FSIZE" void setup_rlimit(char *config[CFG_IS_VALID + 1]); diff --git a/test.c b/test.c index 148ca67..ece0712 100644 --- a/test.c +++ b/test.c @@ -64,6 +64,23 @@ void do_nproc() { } } +void do_fsize() { + FILE *fp = fopen("test.dat", "w"); + if (fp == NULL) { + LOG_ERR("FAIL: fopen failed"); + return; + } + + for (int i = 0; i < 1 << 30; i++) { + if (fputc('a', fp) == EOF) { + LOG_INFO("OK: fputc failed: i=%d", i); + break; + } + } + + fclose(fp); +} + #pragma GCC pop_options int main() { @@ -79,6 +96,7 @@ int main() { case 6: LOG_AND_EXECUTE(block1); break; case 7: LOG_AND_EXECUTE(block2); break; case 8: LOG_AND_EXECUTE(nproc); break; + case 9: LOG_AND_EXECUTE(fsize); break; default: { LOG_INFO("NO TEST SPECIFIED"); break;