1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,security.insecureAPI.vfork,unix.Vfork -verify %s
2 // RUN: %clang_analyze_cc1 -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.
f1(int x,int y)9 int f1(int x, int y) {
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     switch (y) {
20     case 0:
21       execl("", "", 0); // no-warning
22       break;
23     case 1:
24       execle("", "", 0); // no-warning
25       break;
26     case 2:
27       execlp("", "", 0); // no-warning
28       break;
29     case 3:
30       execv("", NULL); // no-warning
31       break;
32     case 4:
33       execve("", NULL, NULL); // no-warning
34       break;
35     case 5:
36       execvp("", NULL); // no-warning
37       break;
38     case 6:
39       execvpe("", NULL, NULL); // no-warning
40       break;
41     }
42     _exit(1); // no-warning
43     break;
44   case 1:
45     // Ensure that writing variables is prohibited.
46     x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}}
47     break;
48   case 2:
49     // Ensure that calling functions is prohibited.
50     foo(); // expected-warning{{This function call is prohibited after a successful vfork}}
51     break;
52   default:
53     // Ensure that returning from function is prohibited.
54     return 0; // expected-warning{{Return is prohibited after a successful vfork; call _exit() instead}}
55   }
56 
57   while(1);
58 }
59 
60 // Same as previous but without explicit pid variable.
f2(int x)61 int f2(int x) {
62   pid_t pid = vfork(); // expected-warning{{Call to function 'vfork' is insecure}}
63 
64   switch (x) {
65   case 0:
66     // Ensure that writing pid is ok.
67     pid = 1; // no-warning
68     // Ensure that calling whitelisted routines is ok.
69     execl("", "", 0); // no-warning
70     _exit(1); // no-warning
71     break;
72   case 1:
73     // Ensure that writing variables is prohibited.
74     x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}}
75     break;
76   case 2:
77     // Ensure that calling functions is prohibited.
78     foo(); // expected-warning{{This function call is prohibited after a successful vfork}}
79     break;
80   default:
81     // Ensure that returning from function is prohibited.
82     return 0; // expected-warning{{Return is prohibited after a successful vfork; call _exit() instead}}
83   }
84 
85   while(1);
86 }
87 
88 // Ensure that parent process isn't restricted.
f3(int x)89 int f3(int x) {
90   if (vfork() == 0) // expected-warning{{Call to function 'vfork' is insecure}}
91     _exit(1);
92   x = 0; // no-warning
93   foo(); // no-warning
94   return 0;
95 } // no-warning
96 
97 // Unbound pids are special so test them separately.
f4(int x)98 void f4(int x) {
99   switch (x) {
100   case 0:
101     vfork(); // expected-warning{{Call to function 'vfork' is insecure}}
102     x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}}
103     break;
104 
105   case 1:
106     {
107       char args[2];
108       switch (vfork()) { // expected-warning{{Call to function 'vfork' is insecure}}
109       case 0:
110         args[0] = 0; // expected-warning{{This assignment is prohibited after a successful vfork}}
111         exit(1);
112       }
113       break;
114     }
115 
116   case 2:
117     {
118       pid_t pid;
119       if ((pid = vfork()) == 0) // expected-warning{{Call to function 'vfork' is insecure}}
120         while(1); // no-warning
121       break;
122     }
123   }
124   while(1);
125 } //no-warning
126 
127 
f5()128 void f5() {
129   // See "libxtables: move some code to avoid cautions in vfork man page"
130   // (http://lists.netfilter.org/pipermail/netfilter-buglog/2014-October/003280.html).
131   if (vfork() == 0) { // expected-warning{{Call to function 'vfork' is insecure}}
132     execl("prog", "arg1", 0); // no-warning
133     exit(1);  // expected-warning{{This function call is prohibited after a successful vfork}}
134   }
135 }
136 
137