1 /* 2 ** This program tests your system to see if you have the lovely 3 ** security-defeating semantics that an open with O_CREAT|O_EXCL 4 ** set will successfully open a file named by a symbolic link that 5 ** points to a non-existent file. Sadly, Posix is mute on what 6 ** should happen in this situation. 7 ** 8 ** Results to date: 9 ** AIX 3.2 OK 10 ** BSD family OK 11 ** BSD/OS 2.1 OK 12 ** FreeBSD 2.1 OK 13 ** DEC OSF/1 3.0 OK 14 ** HP-UX 9.04 FAIL 15 ** HP-UX 9.05 FAIL 16 ** HP-UX 9.07 OK 17 ** HP-UX 10.01 OK 18 ** HP-UX 10.10 OK 19 ** HP-UX 10.20 OK 20 ** Irix 5.3 OK 21 ** Irix 6.2 OK 22 ** Irix 6.3 OK 23 ** Irix 6.4 OK 24 ** Linux OK 25 ** NeXT 2.1 OK 26 ** Solaris 2.x OK 27 ** SunOS 4.x OK 28 ** Ultrix 4.3 OK 29 */ 30 31 #include <stdio.h> 32 #include <errno.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 37 char Attacker[128]; 38 char Attackee[128]; 39 40 main(argc, argv) 41 int argc; 42 char **argv; 43 { 44 struct stat st; 45 46 sprintf(Attacker, "/tmp/attacker.%d.%ld", getpid(), time(NULL)); 47 sprintf(Attackee, "/tmp/attackee.%d.%ld", getpid(), time(NULL)); 48 49 if (symlink(Attackee, Attacker) < 0) 50 { 51 printf("Could not create %s->%s symlink: %d\n", 52 Attacker, Attackee, errno); 53 bail(1); 54 } 55 (void) unlink(Attackee); 56 if (stat(Attackee, &st) >= 0) 57 { 58 printf("%s already exists -- remove and try again.\n", 59 Attackee); 60 bail(1); 61 } 62 if (open(Attacker, O_WRONLY|O_CREAT|O_EXCL, 0644) < 0) 63 { 64 int saveerr = errno; 65 66 if (stat(Attackee, &st) >= 0) 67 { 68 printf("Weird. Open failed but %s was created anyhow (errno = %d)\n", 69 Attackee, saveerr); 70 bail(1); 71 } 72 printf("Good show! Exclusive open works properly with symbolic links (errno = %d).\n", 73 saveerr); 74 bail(0); 75 } 76 if (stat(Attackee, &st) < 0) 77 { 78 printf("Weird. Open succeeded but %s was not created\n", 79 Attackee); 80 bail(2); 81 } 82 printf("Bad news: you can do an exclusive open through a symbolic link\n"); 83 printf("\tBe sure you #define BOGUS_O_EXCL in conf.h\n"); 84 bail(1); 85 } 86 87 bail(stat) 88 int stat; 89 { 90 (void) unlink(Attacker); 91 (void) unlink(Attackee); 92 exit(stat); 93 } 94