258 lines · c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,security.SetgidSetuidOrder -verify %s2 3typedef int uid_t;4typedef int gid_t;5 6int setuid(uid_t);7int setgid(gid_t);8int seteuid(uid_t);9int setegid(gid_t);10int setreuid(uid_t, uid_t);11int setregid(gid_t, gid_t);12int setresuid(uid_t, uid_t, uid_t);13int setresgid(gid_t, gid_t, gid_t);14 15uid_t getuid();16gid_t getgid();17 18 19 20void correct_order() {21 // A correct revocation sequence starts here.22 if (setgid(getgid()) == -1)23 return;24 if (setuid(getuid()) == -1)25 return;26 // No warning for the following setgid statement.27 // The previous setgid and setuid calls are a correct privilege revocation28 // sequence. The checker does not care about the following statements (except29 // if a wrong setuid-setgid sequence follows again).30 if (setgid(getgid()) == -1)31 return;32}33 34void incorrect_after_correct() {35 if (setgid(getgid()) == -1)36 return;37 if (setuid(getuid()) == -1)38 return;39 // Incorrect sequence starts here.40 if (setuid(getuid()) == -1)41 return;42 if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}43 return;44}45 46void incorrect_order() {47 if (setuid(getuid()) == -1)48 return;49 if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}50 return;51 if (setgid(getgid()) == -1)52 return;53}54 55void warn_at_second_time() {56 if (setuid(getuid()) == -1)57 return;58 if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}59 return;60 if (setuid(getuid()) == -1)61 return;62 if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}63 return;64}65 66uid_t f_uid();67gid_t f_gid();68 69void setuid_other() {70 if (setuid(f_uid()) == -1)71 return;72 if (setgid(getgid()) == -1)73 return;74}75 76void setgid_other() {77 if (setuid(getuid()) == -1)78 return;79 if (setgid(f_gid()) == -1)80 return;81 if (setgid(getgid()) == -1)82 return;83}84 85void setuid_other_between() {86 if (setuid(getuid()) == -1)87 return;88 if (setuid(f_uid()) == -1)89 return;90 if (setgid(getgid()) == -1)91 return;92}93 94void setgid_with_getuid() {95 if (setuid(getuid()) == -1)96 return;97 // add a clang-tidy check for this case?98 if (setgid(getuid()) == -1)99 return;100}101 102void setuid_with_getgid() {103 // add a clang-tidy check for this case?104 if (setuid(getgid()) == -1)105 return;106 if (setgid(getgid()) == -1)107 return;108}109 110int f_setuid() {111 return setuid(getuid());112}113 114int f_setgid() {115 return setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}116}117 118void function_calls() {119 if (f_setuid() == -1)120 return;121 if (f_setgid() == -1)122 return;123}124 125void seteuid_between() {126 if (setuid(getuid()) == -1)127 return;128 if (seteuid(getuid()) == -1)129 return;130 if (setgid(getgid()) == -1)131 return;132}133 134void setegid_between() {135 if (setuid(getuid()) == -1)136 return;137 if (setegid(getgid()) == -1)138 return;139 if (setgid(getgid()) == -1)140 return;141}142 143void setreuid_between() {144 if (setuid(getuid()) == -1)145 return;146 if (setreuid(getuid(), getuid()) == -1)147 return;148 if (setgid(getgid()) == -1)149 return;150}151 152void setregid_between() {153 if (setuid(getuid()) == -1)154 return;155 if (setregid(getgid(), getgid()) == -1)156 return;157 if (setgid(getgid()) == -1)158 return;159}160 161void setresuid_between() {162 if (setuid(getuid()) == -1)163 return;164 if (setresuid(getuid(), getuid(), getuid()) == -1)165 return;166 if (setgid(getgid()) == -1)167 return;168}169 170void setresgid_between() {171 if (setuid(getuid()) == -1)172 return;173 if (setresgid(getgid(), getgid(), getgid()) == -1)174 return;175 if (setgid(getgid()) == -1)176 return;177}178 179void getgid_getuid_between() {180 if (setuid(getuid()) == -1)181 return;182 (void)getgid();183 (void)getuid();184 if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}185 return;186}187 188void stored_getgid_getuid() {189 // possible future improvement: detect this case190 uid_t u = getuid();191 gid_t g = getgid();192 if (setuid(u) == -1)193 return;194 if (setgid(g) == -1) // no warning195 return;196}197 198void f_extern();199 200void other_unknown_function_between() {201 if (setuid(getuid()) == -1)202 return;203 f_extern();204 if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}205 return;206}207 208void setuid_error_case() {209 if (setuid(getuid()) == -1) {210 // No warning if we know that the first setuid call has failed.211 (void)setgid(getgid());212 return;213 }214 (void)setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}215}216 217void setuid_success_case() {218 if (setuid(getuid()) == 0) {219 if (setgid(getgid()) == 0) { // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}220 }221 }222}223 224void incorrect_order_compare_zero() {225 if (setuid(getuid()) != 0)226 return;227 (void)setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}228}229 230void setuid_error_case_compare_zero() {231 if (setuid(getuid()) != 0) {232 // No warning if we know that the first setuid call has failed.233 (void)setgid(getgid());234 return;235 }236}237 238void incorrect_order_compare_other() {239 if (setuid(getuid()) == -2) {240 // This is a case for improvement:241 // The checker does not recognize that this is an invalid error check,242 // but this is really another type of bug not related to this checker.243 (void)setgid(getgid()); // warning should appear here244 return;245 }246 if (setgid(getgid()) == -2) { // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}247 return;248 }249}250 251const int FAIL = -1;252 253void incorrect_order_compare_var() {254 if (setuid(getuid()) == FAIL)255 return;256 (void)setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}}257}258