diff options
Diffstat (limited to 'sway/main.c')
-rw-r--r-- | sway/main.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/sway/main.c b/sway/main.c index a040cec9..73c4b5f2 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -4,13 +4,16 @@ | |||
4 | #include <wlc/wlc.h> | 4 | #include <wlc/wlc.h> |
5 | #include <sys/wait.h> | 5 | #include <sys/wait.h> |
6 | #include <sys/types.h> | 6 | #include <sys/types.h> |
7 | #include <sys/stat.h> | ||
7 | #include <sys/un.h> | 8 | #include <sys/un.h> |
8 | #include <signal.h> | 9 | #include <signal.h> |
9 | #include <unistd.h> | 10 | #include <unistd.h> |
10 | #include <getopt.h> | 11 | #include <getopt.h> |
12 | #include <sys/capability.h> | ||
11 | #include "sway/extensions.h" | 13 | #include "sway/extensions.h" |
12 | #include "sway/layout.h" | 14 | #include "sway/layout.h" |
13 | #include "sway/config.h" | 15 | #include "sway/config.h" |
16 | #include "sway/security.h" | ||
14 | #include "sway/handlers.h" | 17 | #include "sway/handlers.h" |
15 | #include "sway/input.h" | 18 | #include "sway/input.h" |
16 | #include "sway/ipc-server.h" | 19 | #include "sway/ipc-server.h" |
@@ -142,6 +145,63 @@ static void log_kernel() { | |||
142 | fclose(f); | 145 | fclose(f); |
143 | } | 146 | } |
144 | 147 | ||
148 | static void security_sanity_check() { | ||
149 | // TODO: Notify users visually if this has issues | ||
150 | struct stat s; | ||
151 | if (stat("/proc", &s)) { | ||
152 | sway_log(L_ERROR, | ||
153 | "!! DANGER !! /proc is not available - sway CANNOT enforce security rules!"); | ||
154 | } | ||
155 | cap_flag_value_t v; | ||
156 | cap_t cap = cap_get_proc(); | ||
157 | if (!cap || cap_get_flag(cap, CAP_SYS_PTRACE, CAP_PERMITTED, &v) != 0 || v != CAP_SET) { | ||
158 | sway_log(L_ERROR, | ||
159 | "!! DANGER !! Sway does not have CAP_SYS_PTRACE and cannot enforce security rules for processes running as other users."); | ||
160 | } | ||
161 | if (cap) { | ||
162 | cap_free(cap); | ||
163 | } | ||
164 | if (!stat(SYSCONFDIR "/sway", &s)) { | ||
165 | if (s.st_uid != 0 || s.st_gid != 0 | ||
166 | || (s.st_mode & S_IWGRP) || (s.st_mode & S_IWOTH)) { | ||
167 | sway_log(L_ERROR, | ||
168 | "!! DANGER !! " SYSCONFDIR "/sway is not secure! It should be owned by root and set to 0755 at the minimum"); | ||
169 | } | ||
170 | } | ||
171 | struct { | ||
172 | char *command; | ||
173 | enum command_context context; | ||
174 | bool checked; | ||
175 | } expected[] = { | ||
176 | { "reload", CONTEXT_BINDING, false }, | ||
177 | { "restart", CONTEXT_BINDING, false }, | ||
178 | { "permit", CONTEXT_CONFIG, false }, | ||
179 | { "reject", CONTEXT_CONFIG, false }, | ||
180 | { "ipc", CONTEXT_CONFIG, false }, | ||
181 | }; | ||
182 | int expected_len = 5; | ||
183 | for (int i = 0; i < config->command_policies->length; ++i) { | ||
184 | struct command_policy *policy = config->command_policies->items[i]; | ||
185 | for (int j = 0; j < expected_len; ++j) { | ||
186 | if (strcmp(expected[j].command, policy->command) == 0) { | ||
187 | expected[j].checked = true; | ||
188 | if (expected[j].context != policy->context) { | ||
189 | sway_log(L_ERROR, | ||
190 | "!! DANGER !! Command security policy for %s should be set to %s", | ||
191 | expected[j].command, command_policy_str(expected[j].context)); | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | } | ||
196 | for (int j = 0; j < expected_len; ++j) { | ||
197 | if (!expected[j].checked) { | ||
198 | sway_log(L_ERROR, | ||
199 | "!! DANGER !! Command security policy for %s should be set to %s", | ||
200 | expected[j].command, command_policy_str(expected[j].context)); | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | |||
145 | int main(int argc, char **argv) { | 205 | int main(int argc, char **argv) { |
146 | static int verbose = 0, debug = 0, validate = 0; | 206 | static int verbose = 0, debug = 0, validate = 0; |
147 | 207 | ||
@@ -170,6 +230,10 @@ int main(int argc, char **argv) { | |||
170 | " --get-socketpath Gets the IPC socket path and prints it, then exits.\n" | 230 | " --get-socketpath Gets the IPC socket path and prints it, then exits.\n" |
171 | "\n"; | 231 | "\n"; |
172 | 232 | ||
233 | // Security: | ||
234 | unsetenv("LD_PRELOAD"); | ||
235 | setenv("LD_LIBRARY_PATH", _LD_LIBRARY_PATH, 1); | ||
236 | |||
173 | int c; | 237 | int c; |
174 | while (1) { | 238 | while (1) { |
175 | int option_index = 0; | 239 | int option_index = 0; |
@@ -298,6 +362,8 @@ int main(int argc, char **argv) { | |||
298 | free(config_path); | 362 | free(config_path); |
299 | } | 363 | } |
300 | 364 | ||
365 | security_sanity_check(); | ||
366 | |||
301 | if (!terminate_request) { | 367 | if (!terminate_request) { |
302 | wlc_run(); | 368 | wlc_run(); |
303 | } | 369 | } |