diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-05-11 12:48:30 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-11 12:48:30 -0400 |
commit | 6df0f9a7e4d41cdc56206d178e57eb141a0e3d8f (patch) | |
tree | ee9a1ffafa93162484829ca42f6f61a997ca0f90 | |
parent | Mention Patreon in README.md (diff) | |
parent | Replace spaces with tabs in resolve_path (diff) | |
download | sway-6df0f9a7e4d41cdc56206d178e57eb141a0e3d8f.tar.gz sway-6df0f9a7e4d41cdc56206d178e57eb141a0e3d8f.tar.zst sway-6df0f9a7e4d41cdc56206d178e57eb141a0e3d8f.zip |
Merge pull request #1218 from Hummer12007/suicaps
Terminate when both suid bit and filecaps are set
-rw-r--r-- | common/util.c | 66 | ||||
-rw-r--r-- | sway/main.c | 40 |
2 files changed, 65 insertions, 41 deletions
diff --git a/common/util.c b/common/util.c index a9e6a9c2..34bb5ec1 100644 --- a/common/util.c +++ b/common/util.c | |||
@@ -124,38 +124,38 @@ uint32_t parse_color(const char *color) { | |||
124 | } | 124 | } |
125 | 125 | ||
126 | char* resolve_path(const char* path) { | 126 | char* resolve_path(const char* path) { |
127 | struct stat sb; | 127 | struct stat sb; |
128 | ssize_t r; | 128 | ssize_t r; |
129 | int i; | 129 | int i; |
130 | char *current = NULL; | 130 | char *current = NULL; |
131 | char *resolved = NULL; | 131 | char *resolved = NULL; |
132 | 132 | ||
133 | if(!(current = strdup(path))) { | 133 | if(!(current = strdup(path))) { |
134 | return NULL; | 134 | return NULL; |
135 | } | 135 | } |
136 | for (i = 0; i < 16; ++i) { | 136 | for (i = 0; i < 16; ++i) { |
137 | if (lstat(current, &sb) == -1) { | 137 | if (lstat(current, &sb) == -1) { |
138 | goto failed; | 138 | goto failed; |
139 | } | 139 | } |
140 | if((sb.st_mode & S_IFMT) != S_IFLNK) { | 140 | if((sb.st_mode & S_IFMT) != S_IFLNK) { |
141 | return current; | 141 | return current; |
142 | } | 142 | } |
143 | if (!(resolved = malloc(sb.st_size + 1))) { | 143 | if (!(resolved = malloc(sb.st_size + 1))) { |
144 | goto failed; | 144 | goto failed; |
145 | } | 145 | } |
146 | r = readlink(current, resolved, sb.st_size); | 146 | r = readlink(current, resolved, sb.st_size); |
147 | if (r == -1 || r > sb.st_size) { | 147 | if (r == -1 || r > sb.st_size) { |
148 | goto failed; | 148 | goto failed; |
149 | } | 149 | } |
150 | resolved[r] = '\0'; | 150 | resolved[r] = '\0'; |
151 | free(current); | 151 | free(current); |
152 | current = strdup(resolved); | 152 | current = strdup(resolved); |
153 | free(resolved); | 153 | free(resolved); |
154 | resolved = NULL; | 154 | resolved = NULL; |
155 | } | 155 | } |
156 | 156 | ||
157 | failed: | 157 | failed: |
158 | free(resolved); | 158 | free(resolved); |
159 | free(current); | 159 | free(current); |
160 | return NULL; | 160 | return NULL; |
161 | } \ No newline at end of file | 161 | } |
diff --git a/sway/main.c b/sway/main.c index b9549b12..819788b1 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "stringop.h" | 27 | #include "stringop.h" |
28 | #include "sway.h" | 28 | #include "sway.h" |
29 | #include "log.h" | 29 | #include "log.h" |
30 | #include "util.h" | ||
30 | 31 | ||
31 | static bool terminate_request = false; | 32 | static bool terminate_request = false; |
32 | static int exit_value = 0; | 33 | static int exit_value = 0; |
@@ -209,6 +210,27 @@ static void security_sanity_check() { | |||
209 | #endif | 210 | #endif |
210 | } | 211 | } |
211 | 212 | ||
213 | static void executable_sanity_check() { | ||
214 | #ifdef __linux__ | ||
215 | struct stat sb; | ||
216 | char *exe = realpath("/proc/self/exe", NULL); | ||
217 | stat(exe, &sb); | ||
218 | // We assume that cap_get_file returning NULL implies ENODATA | ||
219 | if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) { | ||
220 | sway_log(L_ERROR, | ||
221 | "sway executable has both the s(g)uid bit AND file caps set."); | ||
222 | sway_log(L_ERROR, | ||
223 | "This is strongly discouraged (and completely broken)."); | ||
224 | sway_log(L_ERROR, | ||
225 | "Please clear one of them (either the suid bit, or the file caps)."); | ||
226 | sway_log(L_ERROR, | ||
227 | "If unsure, strip the file caps."); | ||
228 | exit(EXIT_FAILURE); | ||
229 | } | ||
230 | free(exe); | ||
231 | #endif | ||
232 | } | ||
233 | |||
212 | int main(int argc, char **argv) { | 234 | int main(int argc, char **argv) { |
213 | static int verbose = 0, debug = 0, validate = 0; | 235 | static int verbose = 0, debug = 0, validate = 0; |
214 | 236 | ||
@@ -288,6 +310,15 @@ int main(int argc, char **argv) { | |||
288 | } | 310 | } |
289 | } | 311 | } |
290 | 312 | ||
313 | // we need to setup logging before wlc_init in case it fails. | ||
314 | if (debug) { | ||
315 | init_log(L_DEBUG); | ||
316 | } else if (verbose || validate) { | ||
317 | init_log(L_INFO); | ||
318 | } else { | ||
319 | init_log(L_ERROR); | ||
320 | } | ||
321 | |||
291 | if (optind < argc) { // Behave as IPC client | 322 | if (optind < argc) { // Behave as IPC client |
292 | if(optind != 1) { | 323 | if(optind != 1) { |
293 | sway_log(L_ERROR, "Don't use options with the IPC client"); | 324 | sway_log(L_ERROR, "Don't use options with the IPC client"); |
@@ -317,6 +348,7 @@ int main(int argc, char **argv) { | |||
317 | return 0; | 348 | return 0; |
318 | } | 349 | } |
319 | 350 | ||
351 | executable_sanity_check(); | ||
320 | #ifdef __linux__ | 352 | #ifdef __linux__ |
321 | bool suid = false; | 353 | bool suid = false; |
322 | if (getuid() != geteuid() || getgid() != getegid()) { | 354 | if (getuid() != geteuid() || getgid() != getegid()) { |
@@ -329,14 +361,6 @@ int main(int argc, char **argv) { | |||
329 | } | 361 | } |
330 | #endif | 362 | #endif |
331 | 363 | ||
332 | // we need to setup logging before wlc_init in case it fails. | ||
333 | if (debug) { | ||
334 | init_log(L_DEBUG); | ||
335 | } else if (verbose || validate) { | ||
336 | init_log(L_INFO); | ||
337 | } else { | ||
338 | init_log(L_ERROR); | ||
339 | } | ||
340 | wlc_log_set_handler(wlc_log_handler); | 364 | wlc_log_set_handler(wlc_log_handler); |
341 | log_kernel(); | 365 | log_kernel(); |
342 | log_distro(); | 366 | log_distro(); |