]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
security: Round 5.2 mkstemp/tmpfile/tmpnam secure (U01)
authorTulio A M Mendes <[email protected]>
Mon, 25 May 2026 19:13:02 +0000 (16:13 -0300)
committerTulio A M Mendes <[email protected]>
Wed, 3 Jun 2026 04:02:35 +0000 (01:02 -0300)
U01: Secure temporary file creation
- mkstemp: Use /dev/urandom for randomness, fallback to pid+counter
- mkstemp: Use alphanumeric charset (62 chars) instead of only digits
- mkstemp: Always use O_CREAT|O_EXCL with mode 0600
- tmpfile: Use mkstemp for secure creation, unlink immediately for anonymity
- tmpnam: Use mkstemp for secure name generation, don't leave file around

Tests: 119/119 PASS (smoke test, SMP=4)

user/ulibc/src/stdio.c
user/ulibc/src/stdlib.c

index 34109fb37248715ee3ae75023db1a3e16fb00d88..163d51b4562f674d328a645239ef7d91f322793a 100644 (file)
@@ -590,19 +590,28 @@ int pclose(FILE* fp) {
 }
 
 FILE* tmpfile(void) {
-    static int tmpcount = 0;
-    char name[32];
+    /* U01: Use mkstemp for secure temporary file creation */
+    char name[64];
     extern int getpid(void);
-    snprintf(name, sizeof(name), "/tmp/.tmpf_%d_%d", getpid(), tmpcount++);
-    return fopen(name, "w+");
+    snprintf(name, sizeof(name), "/tmp/.tmpf_XXXXXX");
+    int fd = mkstemp(name);
+    if (fd < 0) return NULL;
+    /* U01: Unlink immediately to make it anonymous (deleted on close) */
+    unlink(name);
+    return fdopen(fd, "w+");
 }
 
 char* tmpnam(char* s) {
-    static char buf[32];
-    static int count = 0;
-    snprintf(buf, sizeof(buf), "/tmp/tmp_%d", count++);
-    if (s) { strcpy(s, buf); return s; }
-    return buf;
+    /* U01: Use mkstemp for secure temporary file name generation */
+    static char buf[64];
+    char* target = s ? s : buf;
+    snprintf(target, 64, "/tmp/tmpnam_XXXXXX");
+    int fd = mkstemp(target);
+    if (fd >= 0) {
+        close(fd);
+        unlink(target); /* Don't leave the file around */
+    }
+    return target;
 }
 
 int fscanf(FILE* fp, const char* fmt, ...) {
index 19674eeebb4bf7c8e2299b5805ec78ec0ea2beec..f1cc1d510298740aafa252a53f5f29261b0f5cc9 100644 (file)
@@ -340,15 +340,27 @@ int mkstemp(char* tmpl) {
     /* Check template ends with XXXXXX */
     for (int i = 0; i < 6; i++)
         if (suffix[i] != 'X') return -1;
-    /* Generate unique name using pid + counter */
-    extern int getpid(void);
-    static int counter = 0;
-    int id = getpid() * 1000 + (counter++ % 1000);
-    for (int i = 5; i >= 0; i--) {
-        suffix[i] = (char)('0' + id % 10);
-        id /= 10;
+    /* U01: Try to use /dev/urandom for better randomness, fallback to pid+counter */
+    int rand_bytes[2] = {0, 0};
+    int rand_fd = open("/dev/urandom", 0);
+    if (rand_fd >= 0) {
+        read(rand_fd, rand_bytes, sizeof(rand_bytes));
+        close(rand_fd);
+    } else {
+        extern int getpid(void);
+        static int counter = 0;
+        rand_bytes[0] = getpid();
+        rand_bytes[1] = counter++;
     }
-    int fd = open(tmpl, 1 | 0x40 | 0x80 /* O_WRONLY|O_CREAT|O_EXCL */);
+    /* Use alphanumeric characters for XXXXXX */
+    const char* charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+    unsigned int seed = (unsigned int)(rand_bytes[0] ^ rand_bytes[1]);
+    for (int i = 0; i < 6; i++) {
+        suffix[i] = charset[seed % 62];
+        seed = seed * 1103515245 + 12345; /* LCG for variety */
+    }
+    /* U01: Always use O_CREAT|O_EXCL to prevent race conditions */
+    int fd = open(tmpl, 1 | 0x40 | 0x80 /* O_WRONLY|O_CREAT|O_EXCL */, 0600);
     return fd;
 }