header->blocks = blk_count;
header->hdr_size = sizeof(*header);
- header->flags &= ENUM_NEGATE(SIEVE_BINARY_FLAG_RESOURCE_LIMIT);
+ header->flags = 0;
sieve_binary_file_zero_header_rusage(sbin);
if (!_save_aligned(sbin, stream, header, sizeof(*header), NULL)) {
discard any data from older versions. */
sbin->header.unused_update_time = 0;
sbin->header.unused_cpu_time_msecs = 0;
- sbin->header.flags &= ENUM_NEGATE(SIEVE_BINARY_FLAG_RESOURCE_LIMIT);
+ sbin->header.flags = 0;
/* Load block index */
enum sieve_error *error_code_r,
const char **client_error_r)
{
+ struct sieve_resource_usage rusage;
+
*client_error_r = NULL;
sieve_error_args_init(&error_code_r, NULL);
- if (HAS_ALL_BITS(sbin->header.flags,
- SIEVE_BINARY_FLAG_RESOURCE_LIMIT)) {
+ sieve_binary_get_resource_usage(sbin, &rusage);
+ if (sieve_resource_usage_is_excessive(sbin->svinst, &rusage)) {
e_debug(sbin->event,
"Binary execution is blocked: "
- "Cumulative resource usage limit exceeded "
- "(resource limit flag is set)");
+ "Cumulative resource usage limit exceeded");
*error_code_r = SIEVE_ERROR_RESOURCE_LIMIT;
*client_error_r = "cumulative resource usage limit exceeded";
return 0;
{
struct sieve_storage *storage;
struct sieve_resource_usage delta;
- struct sieve_resource_usage total;
- uint32_t flags;
sieve_error_args_init(&error_code_r, NULL);
storage = sbin->script->storage;
delta = sbin->rusage;
- sieve_binary_get_resource_usage(sbin, &total);
- flags = sbin->header.flags & SIEVE_BINARY_FLAG_RESOURCE_LIMIT;
- if (!HAS_ALL_BITS(flags, SIEVE_BINARY_FLAG_RESOURCE_LIMIT) &&
- !sieve_resource_usage_is_high(sbin->svinst, &total)) {
- /* Nothing meaningful to persist */
+ /* Persist only when this run consumed a meaningful amount of CPU.
+ Critically, refused-without-running attempts (delta == 0) must not
+ touch the file - otherwise the file's update_time would be refreshed
+ on every blocked attempt, preventing the resource_usage_timeout from
+ ever decaying the persisted CPU time and re-enabling the user. */
+ if (!sieve_resource_usage_is_high(sbin->svinst, &delta)) {
sieve_resource_usage_init(&sbin->rusage);
sbin->rusage_updated = FALSE;
return 0;
}
- if (sieve_rusage_storage_add(storage, &delta, flags) < 0) {
+ if (sieve_rusage_storage_add(storage, &delta) < 0) {
*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
return -1;
}
* Binary file
*/
-enum SIEVE_BINARY_FLAGS {
- SIEVE_BINARY_FLAG_RESOURCE_LIMIT = BIT(0),
-};
-
struct sieve_binary_header {
uint32_t magic;
uint16_t version_major;
{
struct sieve_storage *storage = sieve_binary_get_user_storage(sbin);
struct sieve_resource_usage rusage;
- struct sieve_binary_header *header = &sbin->header;
- uint32_t flags = 0;
if (storage == NULL)
return;
- if (sieve_rusage_storage_load(storage, &rusage, &flags) <= 0)
+ if (sieve_rusage_storage_load(storage, &rusage) <= 0)
return;
sbin->persisted_rusage.cpu_time_msecs = rusage.cpu_time_msecs;
sbin->persisted_rusage.update_time = ioloop_time;
- header->flags |= (flags & SIEVE_BINARY_FLAG_RESOURCE_LIMIT);
sieve_resource_usage_init(&sbin->rusage);
sbin->rusage_updated = FALSE;
}
bool sieve_binary_check_resource_usage(struct sieve_binary *sbin)
{
- struct sieve_binary_header *header = &sbin->header;
struct sieve_resource_usage rusage;
sieve_binary_get_resource_usage(sbin, &rusage);
-
- if (sieve_resource_usage_is_excessive(sbin->svinst, &rusage)) {
- header->flags |= SIEVE_BINARY_FLAG_RESOURCE_LIMIT;
- return FALSE;
- }
- return TRUE;
+ return !sieve_resource_usage_is_excessive(sbin->svinst, &rusage);
}
bool sieve_binary_record_resource_usage(
#define SIEVE_RUSAGE_LOCK_TIMEOUT 10
#define SIEVE_RUSAGE_LOCK_STALE_TIMEOUT 60
-/* Maximum size of the on-disk file. Single-line ASCII format with four
+/* Maximum size of the on-disk file. Single-line ASCII format with three
space-separated tokens; anything larger is treated as corrupt. */
#define SIEVE_RUSAGE_MAX_FILE_SIZE 128
struct sieve_rusage_record {
- uint32_t flags;
uint32_t cpu_time_msecs;
time_t update_time;
};
strcmp(tokens[0], SIEVE_RUSAGE_VERSION_TAG) != 0)
break;
if (tokens[1] == NULL || tokens[2] == NULL ||
- tokens[3] == NULL || tokens[4] != NULL)
+ tokens[3] != NULL)
break;
- if (str_to_uint32(tokens[1], &rec->flags) < 0)
+ if (str_to_uint32(tokens[1], &cpu_secs) < 0)
break;
- if (str_to_uint32(tokens[2], &cpu_secs) < 0)
- break;
- if (str_to_time(tokens[3], &rec->update_time) < 0)
+ if (str_to_time(tokens[2], &rec->update_time) < 0)
break;
if (cpu_secs > UINT32_MAX / 1000)
rec->cpu_time_msecs = UINT32_MAX;
}
int sieve_rusage_storage_load(struct sieve_storage *storage,
- struct sieve_resource_usage *rusage_r,
- uint32_t *flags_r)
+ struct sieve_resource_usage *rusage_r)
{
struct sieve_rusage_record rec;
unsigned int timeout;
sieve_resource_usage_init(rusage_r);
- *flags_r = 0;
if (storage->rusage_path == NULL)
return 0;
}
rusage_r->cpu_time_msecs = rec.cpu_time_msecs;
- *flags_r = rec.flags;
return 1;
}
int sieve_rusage_storage_add(struct sieve_storage *storage,
- const struct sieve_resource_usage *delta_rusage,
- uint32_t flags_to_set)
+ const struct sieve_resource_usage *delta_rusage)
{
struct sieve_rusage_record rec;
struct dotlock_settings dlset;
(ioloop_time - rec.update_time) > (time_t)timeout) {
/* decayed: discard previous values */
rec.cpu_time_msecs = 0;
- rec.flags = 0;
}
old_cpu = rec.cpu_time_msecs;
rec.cpu_time_msecs = UINT32_MAX;
else
rec.cpu_time_msecs = old_cpu + delta_rusage->cpu_time_msecs;
- rec.flags |= flags_to_set;
rec.update_time = ioloop_time;
/* Round CPU time up to whole seconds for persistence. */
cpu_secs = (rec.cpu_time_msecs + 999) / 1000;
out = t_str_new(64);
- str_printfa(out, "%s %u %u %lld\n", SIEVE_RUSAGE_VERSION_TAG,
- rec.flags, cpu_secs, (long long)rec.update_time);
+ str_printfa(out, "%s %u %lld\n", SIEVE_RUSAGE_VERSION_TAG,
+ cpu_secs, (long long)rec.update_time);
wret = write(fd, str_data(out), str_len(out));
if (wret != (ssize_t)str_len(out)) {
/* Load persisted resource usage from the per-user file. Returns 1 on success,
0 if the storage has no rusage file (no INBOX namespace path), -1 on error.
- Applies the resource_usage_timeout decay. flags_r receives sieve binary
- header flags (RESOURCE_LIMIT) that were persisted. */
+ Applies the resource_usage_timeout decay. */
int sieve_rusage_storage_load(struct sieve_storage *storage,
- struct sieve_resource_usage *rusage_r,
- uint32_t *flags_r);
+ struct sieve_resource_usage *rusage_r);
-/* Atomically add delta_rusage to and OR flags_to_set into the persisted
- per-user rusage file. Read-modify-write under fcntl WRLCK. Returns 1 on
- success, 0 if no rusage file is configured, -1 on error. */
+/* Atomically add delta_rusage to the persisted per-user rusage file.
+ Returns 1 on success, 0 if no rusage file is configured, -1 on error. */
int sieve_rusage_storage_add(struct sieve_storage *storage,
- const struct sieve_resource_usage *delta_rusage,
- uint32_t flags_to_set);
+ const struct sieve_resource_usage *delta_rusage);
#endif