diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-05-12 17:42:55 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-05-12 17:42:55 +0100 |
commit | 6a183f820fd4db594a7a9730aa084a8216827fd4 (patch) | |
tree | 826e62bc2978199251a0eb833d81290ced232449 /src/hs_helper.c | |
parent | 9647a701abfadd92a2975566cd19610c5810aa64 (diff) | |
download | rspamd-6a183f820fd4db594a7a9730aa084a8216827fd4.tar.gz rspamd-6a183f820fd4db594a7a9730aa084a8216827fd4.zip |
[Feature] Add race condition protection against hs_helper restarts
Diffstat (limited to 'src/hs_helper.c')
-rw-r--r-- | src/hs_helper.c | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/src/hs_helper.c b/src/hs_helper.c index f4f00cf05..cba2ca230 100644 --- a/src/hs_helper.c +++ b/src/hs_helper.c @@ -123,6 +123,7 @@ rspamd_hs_helper_cleanup_dir (struct hs_helper_ctx *ctx, gboolean forced) gint rc; gchar *pattern; gboolean ret = TRUE; + pid_t our_pid = getpid (); if (stat (ctx->hs_dir, &st) == -1) { msg_err ("cannot stat path %s, %s", @@ -160,10 +161,38 @@ rspamd_hs_helper_cleanup_dir (struct hs_helper_ctx *ctx, gboolean forced) rspamd_snprintf (pattern, len, "%s%c%s", ctx->hs_dir, G_DIR_SEPARATOR, "*.hs.new"); if ((rc = glob (pattern, 0, NULL, &globbuf)) == 0) { for (i = 0; i < globbuf.gl_pathc; i++) { - if (unlink (globbuf.gl_pathv[i]) == -1) { - msg_err ("cannot unlink %s: %s", globbuf.gl_pathv[i], - strerror (errno)); - ret = FALSE; + /* Check if we have a pid in the filename */ + const gchar *end_num = globbuf.gl_pathv[i] + + strlen (globbuf.gl_pathv[i]) - (sizeof (".hs.new") - 1); + const gchar *p = end_num - 1; + pid_t foreign_pid = -1; + + while (p > globbuf.gl_pathv[i]) { + if (g_ascii_isdigit (*p)) { + p --; + } + else { + p ++; + break; + } + } + + gulong ul; + if (p < end_num && rspamd_strtoul (p, end_num - p, &ul)) { + foreign_pid = ul; + } + + /* + * Remove only files that was left by us or some non-existing process + * There could be another race condition but it would just leave + * extra files which is relatively innocent? + */ + if (foreign_pid == -1 || foreign_pid == our_pid || kill (foreign_pid, 0) == -1) { + if (unlink(globbuf.gl_pathv[i]) == -1) { + msg_err ("cannot unlink %s: %s", globbuf.gl_pathv[i], + strerror(errno)); + ret = FALSE; + } } } } |