This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/storm.git


The following commit(s) were added to refs/heads/master by this push:
     new 6dd5355c5 Validate the container id and invoke runc without a shell in 
reap-oci-container (#9008)
6dd5355c5 is described below

commit 6dd5355c5362927161c62a60f019b575f15a20ba
Author: reiabreu <[email protected]>
AuthorDate: Mon Aug 24 11:58:04 2026 +0100

    Validate the container id and invoke runc without a shell in 
reap-oci-container (#9008)
    
    * Validate the container id and invoke runc without a shell in 
reap-oci-container
    
    reap-oci-container now checks the container id with validate_container_id
    (hex digits and dashes, 36-42 chars) before it is used. 
validate_container_id
    is exported from oci_launch_cmd.c. cleanup_oci_container runs "runc delete" 
via
    fork/execv with an explicit argument vector instead of system(). Adds
    test_validate_container_id.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * Validate the worker id in profile-docker-container
    
    profile-docker-container now checks the worker id with validate_container_id
    before get_docker_container_pid builds the docker command line, and
    get_docker_container_pid returns pid -1 instead of dereferencing a NULL
    stream when popen fails.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * Pass -- before the container id to runc delete, and test the character 
check at a valid length
    
    validate_container_id accepts a leading dash, so end runc option parsing 
with
    -- before the id in the delete argument vector. The test string that stood 
in
    for a disallowed-character id was short enough to be rejected on length; 
replace
    it with a 40-character one so it exercises the character check.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 4.8 <[email protected]>
---
 storm-core/src/native/worker-launcher/impl/main.c  | 27 ++++++++++++---
 .../worker-launcher/impl/oci/oci_launch_cmd.c      |  2 +-
 .../worker-launcher/impl/oci/oci_launch_cmd.h      | 10 ++++++
 .../src/native/worker-launcher/impl/oci/oci_reap.c | 35 ++++++++++++++------
 .../native/worker-launcher/impl/worker-launcher.c  |  6 ++++
 .../worker-launcher/test/test-worker-launcher.c    | 38 ++++++++++++++++++++++
 6 files changed, 102 insertions(+), 16 deletions(-)

diff --git a/storm-core/src/native/worker-launcher/impl/main.c 
b/storm-core/src/native/worker-launcher/impl/main.c
index 28e841e8d..d99cec7d3 100644
--- a/storm-core/src/native/worker-launcher/impl/main.c
+++ b/storm-core/src/native/worker-launcher/impl/main.c
@@ -19,6 +19,7 @@
 #include "configuration.h"
 #include "worker-launcher.h"
 #include "oci/oci.h"
+#include "oci/oci_launch_cmd.h"
 #include "oci/oci_reap.h"
 
 #include <errno.h>
@@ -246,8 +247,16 @@ int main(int argc, char **argv) {
       exit_code = INVALID_ARGUMENT_NUMBER;
     } else {
       const char * worker_id = argv[optind++];
-      int pid = get_docker_container_pid(worker_id);
-      exit_code = profile_oci_container(pid, argv[optind]);
+      // Validate the worker id (a type 4 UUID, the same shape as a container
+      // id) before it is used to build the docker command line.
+      if (!validate_container_id(worker_id)) {
+        fprintf(ERRORFILE, "ERROR: Bad worker id in profile-docker-container: 
%s\n", worker_id);
+        fflush(ERRORFILE);
+        exit_code = INVALID_ARGUMENT_NUMBER;
+      } else {
+        int pid = get_docker_container_pid(worker_id);
+        exit_code = profile_oci_container(pid, argv[optind]);
+      }
     }
   } else if (strcasecmp("profiler", command) == 0) {
     if (argc != 5) {
@@ -312,9 +321,17 @@ int main(int argc, char **argv) {
     } else {
       char* container_id = argv[optind++];
       int num_reap_layers_keep = atoi(argv[optind]);
-      //becomes root.
-      setuid(0);
-      exit_code = cleanup_oci_container_by_id(container_id, 
num_reap_layers_keep);
+      // Validate the container id before it is used in a filesystem path or
+      // the runc command line.
+      if (!validate_container_id(container_id)) {
+        fprintf(ERRORFILE, "ERROR: Bad container id in reap-oci-container: 
%s\n", container_id);
+        fflush(ERRORFILE);
+        exit_code = INVALID_ARGUMENT_NUMBER;
+      } else {
+        //becomes root.
+        setuid(0);
+        exit_code = cleanup_oci_container_by_id(container_id, 
num_reap_layers_keep);
+      }
     }
   } else if (strcasecmp("profile-oci-container", command) == 0) {
     if (argc != 5) {
diff --git a/storm-core/src/native/worker-launcher/impl/oci/oci_launch_cmd.c 
b/storm-core/src/native/worker-launcher/impl/oci/oci_launch_cmd.c
index 7ebe07d7b..8cd69af2c 100644
--- a/storm-core/src/native/worker-launcher/impl/oci/oci_launch_cmd.c
+++ b/storm-core/src/native/worker-launcher/impl/oci/oci_launch_cmd.c
@@ -445,7 +445,7 @@ static bool all_uuid_digit(const char* input) {
   return true;
 }
 
-static bool validate_container_id(const char* input) {
+bool validate_container_id(const char* input) {
   // The container id will be the same as the worker id, with a prefix of 
"PORTNUM-"
   // Worker id is a type 4 UUID, e.g. 85afb30b-286e-4d32-ab7a-9d5aad89bb88
   // Container id for this worker on port 6702 would be: 
6702-85afb30b-286e-4d32-ab7a-9d5aad89bb88
diff --git a/storm-core/src/native/worker-launcher/impl/oci/oci_launch_cmd.h 
b/storm-core/src/native/worker-launcher/impl/oci/oci_launch_cmd.h
index 0a147cdcb..d63799598 100644
--- a/storm-core/src/native/worker-launcher/impl/oci/oci_launch_cmd.h
+++ b/storm-core/src/native/worker-launcher/impl/oci/oci_launch_cmd.h
@@ -18,6 +18,8 @@
 #ifndef OCI_OCI_LAUNCH_CMD_H
 #define OCI_OCI_LAUNCH_CMD_H
 
+#include <stdbool.h>
+
 #include "utils/cJSON.h"
 
 // NOTE: Update free_oci_launch_cmd when this is changed.
@@ -66,4 +68,12 @@ void free_oci_launch_cmd(oci_launch_cmd* olc);
  */
 oci_launch_cmd* parse_oci_launch_cmd(const char* command_filename);
 
+/**
+ * Validate a container id: a type 4 UUID with an optional "PORTNUM-"
+ * prefix, i.e. only hex digits and dashes, 36 to 42 characters.
+ *
+ * Returns true if the id is well-formed.
+ */
+bool validate_container_id(const char* input);
+
 #endif /* OCI_OCI_LAUNCH_CMD_H */
\ No newline at end of file
diff --git a/storm-core/src/native/worker-launcher/impl/oci/oci_reap.c 
b/storm-core/src/native/worker-launcher/impl/oci/oci_reap.c
index 62762a033..cd4e4f736 100644
--- a/storm-core/src/native/worker-launcher/impl/oci/oci_reap.c
+++ b/storm-core/src/native/worker-launcher/impl/oci/oci_reap.c
@@ -18,6 +18,7 @@
 #include <sys/types.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
+#include <sys/wait.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -751,20 +752,34 @@ int cleanup_oci_container(const char* container_id, const 
char* mount_path, cons
     }
   }
 
-  char* cmd = NULL;
-  if (asprintf(&cmd, "%s delete %s", runc_path, container_id) == -1) {
-    rc = 1;
-    goto cleanup;
-  }
-
-  fprintf(LOGFILE, "oci cleanup container command: %s\n", cmd);
-  if (system(cmd) != 0) {
-    fprintf(ERRORFILE, "WARN: oci cleanup container command %s failed\n", cmd);
+  fprintf(LOGFILE, "oci cleanup container command: %s delete %s\n", runc_path, 
container_id);
+  // Invoke runc with an explicit argument vector via fork/execv rather than
+  // through system().
+  pid_t child = fork();
+  if (child == -1) {
+    fprintf(ERRORFILE, "WARN: Failed to fork to delete oci container %s : 
%s\n",
+        container_id, strerror(errno));
     rc = 1;
+  } else if (child == 0) {
+    // "--" ends option parsing so a container id is never treated as a runc 
flag.
+    char* const delete_args[] = {
+        runc_path, "delete", "--", (char*) container_id, NULL
+    };
+    execv(runc_path, delete_args);
+    fprintf(ERRORFILE, "ERROR: Failed to exec %s delete %s : %s\n",
+        runc_path, container_id, strerror(errno));
+    _exit(1);
+  } else {
+    int status = 0;
+    if (waitpid(child, &status, 0) == -1
+        || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+      fprintf(ERRORFILE, "WARN: oci cleanup container command %s delete %s 
failed\n",
+          runc_path, container_id);
+      rc = 1;
+    }
   }
 
 cleanup:
   free(runc_path);
-  free(cmd);
   return rc;
 }
\ No newline at end of file
diff --git a/storm-core/src/native/worker-launcher/impl/worker-launcher.c 
b/storm-core/src/native/worker-launcher/impl/worker-launcher.c
index 3d1910105..53b8abef8 100644
--- a/storm-core/src/native/worker-launcher/impl/worker-launcher.c
+++ b/storm-core/src/native/worker-launcher/impl/worker-launcher.c
@@ -1276,6 +1276,12 @@ int get_docker_container_pid(const char *worker_id) {
   fflush(LOGFILE);
   FILE *inspect_docker = popen(docker_inspect_command, "r");
   int pid = -1;
+  if (inspect_docker == NULL) {
+    fprintf(ERRORFILE,
+            "ERROR: Could not run %s in get_docker_container_pid\n", 
docker_inspect_command);
+    fflush(ERRORFILE);
+    goto cleanup;
+  }
   int res = fscanf(inspect_docker, "%d", &pid);
   if (pclose(inspect_docker) != 0 || res <= 0) {
     fprintf(ERRORFILE,
diff --git a/storm-core/src/native/worker-launcher/test/test-worker-launcher.c 
b/storm-core/src/native/worker-launcher/test/test-worker-launcher.c
index 4226d527d..3aa659636 100644
--- a/storm-core/src/native/worker-launcher/test/test-worker-launcher.c
+++ b/storm-core/src/native/worker-launcher/test/test-worker-launcher.c
@@ -17,6 +17,7 @@
  */
 #include "configuration.h"
 #include "worker-launcher.h"
+#include "oci/oci_launch_cmd.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -150,6 +151,40 @@ void test_check_user() {
   }
 }
 
+void test_validate_container_id() {
+  // well-formed: bare worker UUID and port-prefixed container id
+  if (!validate_container_id("85afb30b-286e-4d32-ab7a-9d5aad89bb88")) {
+    printf("FAIL: rejected valid worker id\n");
+    exit(1);
+  }
+  if (!validate_container_id("6702-85afb30b-286e-4d32-ab7a-9d5aad89bb88")) {
+    printf("FAIL: rejected valid container id\n");
+    exit(1);
+  }
+  // ids with characters outside [0-9a-fA-F-], or of the wrong length, are 
rejected.
+  // this one is a valid length (40) so it exercises the character check, not 
the length check.
+  if (validate_container_id("6702-85afb30b-286e-4d32-ab7a-9d5aad89bZZ")) {
+    printf("FAIL: accepted id with disallowed characters\n");
+    exit(1);
+  }
+  if (validate_container_id("6702/85afb30b-286e-4d32-ab7a-9d5aad89bb88")) {
+    printf("FAIL: accepted id containing a slash\n");
+    exit(1);
+  }
+  if (validate_container_id("85afb30b-286e-4d32-ab7a-9d5aad89bb88-aaaaaaaa")) {
+    printf("FAIL: accepted id that is too long\n");
+    exit(1);
+  }
+  if (validate_container_id("")) {
+    printf("FAIL: accepted empty id\n");
+    exit(1);
+  }
+  if (validate_container_id("abc")) {
+    printf("FAIL: accepted too-short id\n");
+    exit(1);
+  }
+}
+
 void test_check_configuration_permissions() {
   printf("\nTesting check_configuration_permissions\n");
   if (check_configuration_permissions("/etc/passwd") != 0) {
@@ -310,6 +345,9 @@ int main(int argc, char **argv) {
   printf("\nTesting check_user()\n");
   test_check_user();
 
+  printf("\nTesting validate_container_id()\n");
+  test_validate_container_id();
+
   // the tests that change user need to be run in a subshell, so that
   // when they change user they don't give up our privs
   run_test_in_child("test_signal_container", test_signal_container);

Reply via email to