aboutsummaryrefslogtreecommitdiffstats
path: root/src/hs_helper.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2021-05-12 17:42:55 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2021-05-12 17:42:55 +0100
commit6a183f820fd4db594a7a9730aa084a8216827fd4 (patch)
tree826e62bc2978199251a0eb833d81290ced232449 /src/hs_helper.c
parent9647a701abfadd92a2975566cd19610c5810aa64 (diff)
downloadrspamd-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.c37
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;
+ }
}
}
}