diff --git a/src/builder/b-deletion.c b/src/builder/b-deletion.c
index 9b3595a..1d130e4 100644
--- a/src/builder/b-deletion.c
+++ b/src/builder/b-deletion.c
@@ -134,27 +134,32 @@ child_lejp_cb(struct lejp_ctx *ctx, char reason)
lws_snprintf(full_path, sizeof(full_path), "%s/jobs/%s", conn->home_dir, ctx->buf);
- if (!stat(full_path, &st)) {
- memset(&di, 0, sizeof(di));
- di.dirpath = full_path;
- di.cb = sai_rm_rf_cb;
- di.do_toplevel_cb = 1;
+ /*
+ * Don't stat the path first: the sanitizing above is the
+ * actual security gate, a stat-then-act is a TOCTOU race
+ * (CID 505638), and lws_dir_via_info() returns 1 whether or
+ * not the dir could be opened anyway. So just attempt the
+ * removal directly and report a missing job dir from the
+ * rmdir() errno instead.
+ */
+ memset(&di, 0, sizeof(di));
+ di.dirpath = full_path;
+ di.cb = sai_rm_rf_cb;
+ di.do_toplevel_cb = 1;
- lwsl_notice("%s: performing rm -rf %s\n", __func__, full_path);
+ lwsl_notice("%s: performing rm -rf %s\n", __func__, full_path);
- lws_dir_via_info(&di);
-
- /* lws_dir_via_info returns 1 on success. Errors are logged by sai_rm_rf_cb. */
+ /* Errors are logged by sai_rm_rf_cb. */
+ lws_dir_via_info(&di);
#if defined(WIN32)
- SetFileAttributesA(full_path, FILE_ATTRIBUTE_NORMAL);
+ SetFileAttributesA(full_path, FILE_ATTRIBUTE_NORMAL);
#endif
- rmdir(full_path);
+ if (rmdir(full_path) && errno == ENOENT)
+ lwsl_notice("%s: job dir %s not found (errno %d)\n",
+ __func__, full_path, errno);
- if (!stat(full_path, &st))
- lwsl_notice("%s: top level dir %s still exists\n", __func__, full_path);
- } else {
- lwsl_notice("%s: job dir %s not found (errno %d)\n", __func__, full_path, errno);
- }
+ if (!stat(full_path, &st))
+ lwsl_notice("%s: top level dir %s still exists\n", __func__, full_path);
}
return 0;
}
diff --git a/src/web/w-ws-browser.c b/src/web/w-ws-browser.c
index 385f436..ec842ca 100644
--- a/src/web/w-ws-browser.c
+++ b/src/web/w-ws-browser.c
@@ -1858,7 +1858,7 @@ saiw_browser_broadcast_queue_pcon_energy(struct vhd *vhd, struct pss *pss, sai_p
if (pss && !pss->wants_builder_info)
return 0;
- if (!vhd || !energy)
+ if (!vhd || !energy || !pss)
return 0;
memset(&d, 0, sizeof(d));
@@ -2156,7 +2156,7 @@ saiw_browser_broadcast_queue_power_history(struct vhd *vhd, struct pss *pss)
if (pss && !pss->wants_builder_info)
return 0;
- if (!vhd)
+ if (!vhd || !pss)
return 0;
memset(&d, 0, sizeof(d));