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