1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,security.insecureAPI.vfork,unix.Vfork -verify %s 2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,security.insecureAPI.vfork,unix.Vfork -verify -x c++ %s 3 4 #include "Inputs/system-header-simulator.h" 5 6 void foo(); 7 8 // Ensure that child process is properly checked. 9 int f1(int x) { 10 pid_t pid = vfork(); // expected-warning{{Call to function 'vfork' is insecure}} 11 if (pid != 0) 12 return 0; 13 14 switch (x) { 15 case 0: 16 // Ensure that modifying pid is ok. 17 pid = 1; // no-warning 18 // Ensure that calling whitelisted routines is ok. 19 execl("", "", 0); // no-warning 20 _exit(1); // no-warning 21 break; 22 case 1: 23 // Ensure that writing variables is prohibited. 24 x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}} 25 break; 26 case 2: 27 // Ensure that calling functions is prohibited. 28 foo(); // expected-warning{{This function call is prohibited after a successful vfork}} 29 break; 30 default: 31 // Ensure that returning from function is prohibited. 32 return 0; // expected-warning{{Return is prohibited after a successful vfork; call _exit() instead}} 33 } 34 35 while(1); 36 } 37 38 // Same as previous but without explicit pid variable. 39 int f2(int x) { 40 pid_t pid = vfork(); // expected-warning{{Call to function 'vfork' is insecure}} 41 42 switch (x) { 43 case 0: 44 // Ensure that writing pid is ok. 45 pid = 1; // no-warning 46 // Ensure that calling whitelisted routines is ok. 47 execl("", "", 0); // no-warning 48 _exit(1); // no-warning 49 break; 50 case 1: 51 // Ensure that writing variables is prohibited. 52 x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}} 53 break; 54 case 2: 55 // Ensure that calling functions is prohibited. 56 foo(); // expected-warning{{This function call is prohibited after a successful vfork}} 57 break; 58 default: 59 // Ensure that returning from function is prohibited. 60 return 0; // expected-warning{{Return is prohibited after a successful vfork; call _exit() instead}} 61 } 62 63 while(1); 64 } 65 66 // Ensure that parent process isn't restricted. 67 int f3(int x) { 68 if (vfork() == 0) // expected-warning{{Call to function 'vfork' is insecure}} 69 _exit(1); 70 x = 0; // no-warning 71 foo(); // no-warning 72 return 0; 73 } // no-warning 74 75 // Unbound pids are special so test them separately. 76 void f4(int x) { 77 switch (x) { 78 case 0: 79 vfork(); // expected-warning{{Call to function 'vfork' is insecure}} 80 x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}} 81 break; 82 83 case 1: 84 { 85 char args[2]; 86 switch (vfork()) { // expected-warning{{Call to function 'vfork' is insecure}} 87 case 0: 88 args[0] = 0; // expected-warning{{This assignment is prohibited after a successful vfork}} 89 exit(1); 90 } 91 break; 92 } 93 94 case 2: 95 { 96 pid_t pid; 97 if ((pid = vfork()) == 0) // expected-warning{{Call to function 'vfork' is insecure}} 98 while(1); // no-warning 99 break; 100 } 101 } 102 while(1); 103 } //no-warning 104 105 106 void f5() { 107 // See "libxtables: move some code to avoid cautions in vfork man page" 108 // (http://lists.netfilter.org/pipermail/netfilter-buglog/2014-October/003280.html). 109 if (vfork() == 0) { // expected-warning{{Call to function 'vfork' is insecure}} 110 execl("prog", "arg1", 0); // no-warning 111 exit(1); // expected-warning{{This function call is prohibited after a successful vfork}} 112 } 113 } 114 115