From 63fe1864c51f6e93495292e4abd180bb76c1c050 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan.bosch@open-xchange.com> Date: Mon, 7 Dec 2020 23:41:41 +0100 Subject: [PATCH] plugins: imap-sieve: Implement cumulative resource limits on script execution. --- src/plugins/imapsieve/imap-sieve.c | 33 +++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/plugins/imapsieve/imap-sieve.c b/src/plugins/imapsieve/imap-sieve.c index 3ed19ea8f..63383bfaf 100644 --- a/src/plugins/imapsieve/imap-sieve.c +++ b/src/plugins/imapsieve/imap-sieve.c @@ -282,6 +282,8 @@ struct imap_sieve_run_script { /* Binary corrupt after recompile; don't recompile again */ bool binary_corrupt:1; + /* Resource usage exceeded */ + bool rusage_exceeded:1; }; struct imap_sieve_run { @@ -563,6 +565,13 @@ imap_sieve_run_open_script(struct imap_sieve_run *isrun, "Failed to %s script `%s'", compile_name, sieve_script_location(script)); break; + /* Cumulative resource limit exceeded */ + case SIEVE_ERROR_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(cumulative resource limit exceeded)", + sieve_script_location(script), compile_name); + break; /* Something else */ default: e_error(sieve_get_event(svinst), @@ -668,10 +677,12 @@ imap_sieve_run_scripts(struct imap_sieve_run *isrun, struct sieve_instance *svinst = isieve->svinst; struct imap_sieve_run_script *scripts = isrun->scripts; unsigned int count = isrun->scripts_count; + struct sieve_resource_usage *rusage = + &scriptenv->exec_status->resource_usage; struct sieve_multiscript *mscript; struct sieve_error_handler *ehandler; struct sieve_script *last_script = NULL; - bool user_script = FALSE, more = TRUE; + bool user_script = FALSE, more = TRUE, rusage_exceeded = FALSE; enum sieve_compile_flags cpflags; enum sieve_execute_flags exflags; enum sieve_error compile_error = SIEVE_ERROR_NONE; @@ -696,6 +707,12 @@ imap_sieve_run_scripts(struct imap_sieve_run *isrun, user_script = (script == isrun->user_script); last_script = script; + if (scripts[i].rusage_exceeded) { + rusage_exceeded = TRUE; + break; + } + + sieve_resource_usage_init(rusage); if (user_script) { cpflags |= SIEVE_COMPILE_FLAG_NOGLOBAL; exflags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; @@ -762,6 +779,12 @@ imap_sieve_run_scripts(struct imap_sieve_run *isrun, else if (more) (void)sieve_save(sbin, FALSE, NULL); } + + if (user_script && !sieve_record_resource_usage(sbin, rusage)) { + rusage_exceeded = ((i + 1) < count && more); + scripts[i].rusage_exceeded = TRUE; + break; + } } /* Finish execution */ @@ -771,6 +794,12 @@ imap_sieve_run_scripts(struct imap_sieve_run *isrun, isrun->user_ehandler : isieve->master_ehandler); if (compile_error == SIEVE_ERROR_TEMP_FAILURE) { ret = sieve_multiscript_tempfail(&mscript, ehandler, exflags); + } else if (rusage_exceeded) { + i_assert(last_script != NULL); + (void)sieve_multiscript_tempfail(&mscript, ehandler, exflags); + sieve_error(ehandler, sieve_script_name(last_script), + "cumulative resource usage limit exceeded"); + ret = SIEVE_EXEC_RESOURCE_LIMIT; } else { ret = sieve_multiscript_finish(&mscript, ehandler, exflags, NULL); @@ -784,6 +813,8 @@ imap_sieve_run_scripts(struct imap_sieve_run *isrun, return 1; } + if (last_script == NULL && ret == SIEVE_EXEC_OK) + return 0; return imap_sieve_handle_exec_status(isrun, last_script, ret, scriptenv->exec_status, fatal_r); } -- GitLab