diff options
Diffstat (limited to 'sway/main.c')
-rw-r--r-- | sway/main.c | 186 |
1 files changed, 82 insertions, 104 deletions
diff --git a/sway/main.c b/sway/main.c index 0611e80b..1c4939aa 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <getopt.h> | 1 | #include <getopt.h> |
3 | #include <pango/pangocairo.h> | 2 | #include <pango/pangocairo.h> |
4 | #include <signal.h> | 3 | #include <signal.h> |
@@ -6,6 +5,7 @@ | |||
6 | #include <stdio.h> | 5 | #include <stdio.h> |
7 | #include <stdlib.h> | 6 | #include <stdlib.h> |
8 | #include <string.h> | 7 | #include <string.h> |
8 | #include <sys/resource.h> | ||
9 | #include <sys/stat.h> | 9 | #include <sys/stat.h> |
10 | #include <sys/types.h> | 10 | #include <sys/types.h> |
11 | #include <sys/wait.h> | 11 | #include <sys/wait.h> |
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | static bool terminate_request = false; | 28 | static bool terminate_request = false; |
29 | static int exit_value = 0; | 29 | static int exit_value = 0; |
30 | static struct rlimit original_nofile_rlimit = {0}; | ||
30 | struct sway_server server = {0}; | 31 | struct sway_server server = {0}; |
31 | struct sway_debug debug = {0}; | 32 | struct sway_debug debug = {0}; |
32 | 33 | ||
@@ -47,44 +48,6 @@ void sig_handler(int signal) { | |||
47 | sway_terminate(EXIT_SUCCESS); | 48 | sway_terminate(EXIT_SUCCESS); |
48 | } | 49 | } |
49 | 50 | ||
50 | void detect_proprietary(int allow_unsupported_gpu) { | ||
51 | FILE *f = fopen("/proc/modules", "r"); | ||
52 | if (!f) { | ||
53 | return; | ||
54 | } | ||
55 | char *line = NULL; | ||
56 | size_t line_size = 0; | ||
57 | while (getline(&line, &line_size, f) != -1) { | ||
58 | if (strncmp(line, "nvidia ", 7) == 0) { | ||
59 | if (allow_unsupported_gpu) { | ||
60 | sway_log(SWAY_ERROR, | ||
61 | "!!! Proprietary Nvidia drivers are in use !!!"); | ||
62 | } else { | ||
63 | sway_log(SWAY_ERROR, | ||
64 | "Proprietary Nvidia drivers are NOT supported. " | ||
65 | "Use Nouveau. To launch sway anyway, launch with " | ||
66 | "--my-next-gpu-wont-be-nvidia and DO NOT report issues."); | ||
67 | exit(EXIT_FAILURE); | ||
68 | } | ||
69 | break; | ||
70 | } | ||
71 | if (strstr(line, "fglrx")) { | ||
72 | if (allow_unsupported_gpu) { | ||
73 | sway_log(SWAY_ERROR, | ||
74 | "!!! Proprietary AMD drivers are in use !!!"); | ||
75 | } else { | ||
76 | sway_log(SWAY_ERROR, "Proprietary AMD drivers do NOT support " | ||
77 | "Wayland. Use radeon. To try anyway, launch sway with " | ||
78 | "--unsupported-gpu and DO NOT report issues."); | ||
79 | exit(EXIT_FAILURE); | ||
80 | } | ||
81 | break; | ||
82 | } | ||
83 | } | ||
84 | free(line); | ||
85 | fclose(f); | ||
86 | } | ||
87 | |||
88 | void run_as_ipc_client(char *command, char *socket_path) { | 51 | void run_as_ipc_client(char *command, char *socket_path) { |
89 | int socketfd = ipc_open_socket(socket_path); | 52 | int socketfd = ipc_open_socket(socket_path); |
90 | uint32_t len = strlen(command); | 53 | uint32_t len = strlen(command); |
@@ -148,33 +111,49 @@ static void log_kernel(void) { | |||
148 | pclose(f); | 111 | pclose(f); |
149 | } | 112 | } |
150 | 113 | ||
151 | 114 | static bool detect_suid(void) { | |
152 | static bool drop_permissions(void) { | 115 | if (geteuid() != 0 && getegid() != 0) { |
153 | if (getuid() != geteuid() || getgid() != getegid()) { | 116 | return false; |
154 | // Set the gid and uid in the correct order. | ||
155 | if (setgid(getgid()) != 0) { | ||
156 | sway_log(SWAY_ERROR, "Unable to drop root group, refusing to start"); | ||
157 | return false; | ||
158 | } | ||
159 | if (setuid(getuid()) != 0) { | ||
160 | sway_log(SWAY_ERROR, "Unable to drop root user, refusing to start"); | ||
161 | return false; | ||
162 | } | ||
163 | } | 117 | } |
164 | if (setgid(0) != -1 || setuid(0) != -1) { | 118 | |
165 | sway_log(SWAY_ERROR, "Unable to drop root (we shouldn't be able to " | 119 | if (getuid() == geteuid() && getgid() == getegid()) { |
166 | "restore it after setuid), refusing to start"); | ||
167 | return false; | 120 | return false; |
168 | } | 121 | } |
122 | |||
123 | sway_log(SWAY_ERROR, "SUID operation is no longer supported, refusing to start. " | ||
124 | "This check will be removed in a future release."); | ||
169 | return true; | 125 | return true; |
170 | } | 126 | } |
171 | 127 | ||
128 | static void increase_nofile_limit(void) { | ||
129 | if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) { | ||
130 | sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: " | ||
131 | "getrlimit(NOFILE) failed"); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | struct rlimit new_rlimit = original_nofile_rlimit; | ||
136 | new_rlimit.rlim_cur = new_rlimit.rlim_max; | ||
137 | if (setrlimit(RLIMIT_NOFILE, &new_rlimit) != 0) { | ||
138 | sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: " | ||
139 | "setrlimit(NOFILE) failed"); | ||
140 | sway_log(SWAY_INFO, "Running with %d max open files", | ||
141 | (int)original_nofile_rlimit.rlim_cur); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | void restore_nofile_limit(void) { | ||
146 | if (original_nofile_rlimit.rlim_cur == 0) { | ||
147 | return; | ||
148 | } | ||
149 | if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) { | ||
150 | sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: " | ||
151 | "setrlimit(NOFILE) failed"); | ||
152 | } | ||
153 | } | ||
154 | |||
172 | void enable_debug_flag(const char *flag) { | 155 | void enable_debug_flag(const char *flag) { |
173 | if (strcmp(flag, "damage=highlight") == 0) { | 156 | if (strcmp(flag, "noatomic") == 0) { |
174 | debug.damage = DAMAGE_HIGHLIGHT; | ||
175 | } else if (strcmp(flag, "damage=rerender") == 0) { | ||
176 | debug.damage = DAMAGE_RERENDER; | ||
177 | } else if (strcmp(flag, "noatomic") == 0) { | ||
178 | debug.noatomic = true; | 157 | debug.noatomic = true; |
179 | } else if (strcmp(flag, "txn-wait") == 0) { | 158 | } else if (strcmp(flag, "txn-wait") == 0) { |
180 | debug.txn_wait = true; | 159 | debug.txn_wait = true; |
@@ -182,6 +161,8 @@ void enable_debug_flag(const char *flag) { | |||
182 | debug.txn_timings = true; | 161 | debug.txn_timings = true; |
183 | } else if (strncmp(flag, "txn-timeout=", 12) == 0) { | 162 | } else if (strncmp(flag, "txn-timeout=", 12) == 0) { |
184 | server.txn_timeout_ms = atoi(&flag[12]); | 163 | server.txn_timeout_ms = atoi(&flag[12]); |
164 | } else if (strcmp(flag, "legacy-wl-drm") == 0) { | ||
165 | debug.legacy_wl_drm = true; | ||
185 | } else { | 166 | } else { |
186 | sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag); | 167 | sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag); |
187 | } | 168 | } |
@@ -206,36 +187,35 @@ static void handle_wlr_log(enum wlr_log_importance importance, | |||
206 | _sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args); | 187 | _sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args); |
207 | } | 188 | } |
208 | 189 | ||
190 | static const struct option long_options[] = { | ||
191 | {"help", no_argument, NULL, 'h'}, | ||
192 | {"config", required_argument, NULL, 'c'}, | ||
193 | {"validate", no_argument, NULL, 'C'}, | ||
194 | {"debug", no_argument, NULL, 'd'}, | ||
195 | {"version", no_argument, NULL, 'v'}, | ||
196 | {"verbose", no_argument, NULL, 'V'}, | ||
197 | {"get-socketpath", no_argument, NULL, 'p'}, | ||
198 | {"unsupported-gpu", no_argument, NULL, 'u'}, | ||
199 | {0, 0, 0, 0} | ||
200 | }; | ||
201 | |||
202 | static const char usage[] = | ||
203 | "Usage: sway [options] [command]\n" | ||
204 | "\n" | ||
205 | " -h, --help Show help message and quit.\n" | ||
206 | " -c, --config <config> Specify a config file.\n" | ||
207 | " -C, --validate Check the validity of the config file, then exit.\n" | ||
208 | " -d, --debug Enables full logging, including debug information.\n" | ||
209 | " -v, --version Show the version number and quit.\n" | ||
210 | " -V, --verbose Enables more verbose logging.\n" | ||
211 | " --get-socketpath Gets the IPC socket path and prints it, then exits.\n" | ||
212 | "\n"; | ||
213 | |||
209 | int main(int argc, char **argv) { | 214 | int main(int argc, char **argv) { |
210 | static int verbose = 0, debug = 0, validate = 0, allow_unsupported_gpu = 0; | 215 | static bool verbose = false, debug = false, validate = false; |
211 | |||
212 | static const struct option long_options[] = { | ||
213 | {"help", no_argument, NULL, 'h'}, | ||
214 | {"config", required_argument, NULL, 'c'}, | ||
215 | {"validate", no_argument, NULL, 'C'}, | ||
216 | {"debug", no_argument, NULL, 'd'}, | ||
217 | {"version", no_argument, NULL, 'v'}, | ||
218 | {"verbose", no_argument, NULL, 'V'}, | ||
219 | {"get-socketpath", no_argument, NULL, 'p'}, | ||
220 | {"unsupported-gpu", no_argument, NULL, 'u'}, | ||
221 | {"my-next-gpu-wont-be-nvidia", no_argument, NULL, 'u'}, | ||
222 | {0, 0, 0, 0} | ||
223 | }; | ||
224 | 216 | ||
225 | char *config_path = NULL; | 217 | char *config_path = NULL; |
226 | 218 | ||
227 | const char* usage = | ||
228 | "Usage: sway [options] [command]\n" | ||
229 | "\n" | ||
230 | " -h, --help Show help message and quit.\n" | ||
231 | " -c, --config <config> Specify a config file.\n" | ||
232 | " -C, --validate Check the validity of the config file, then exit.\n" | ||
233 | " -d, --debug Enables full logging, including debug information.\n" | ||
234 | " -v, --version Show the version number and quit.\n" | ||
235 | " -V, --verbose Enables more verbose logging.\n" | ||
236 | " --get-socketpath Gets the IPC socket path and prints it, then exits.\n" | ||
237 | "\n"; | ||
238 | |||
239 | int c; | 219 | int c; |
240 | while (1) { | 220 | while (1) { |
241 | int option_index = 0; | 221 | int option_index = 0; |
@@ -253,25 +233,25 @@ int main(int argc, char **argv) { | |||
253 | config_path = strdup(optarg); | 233 | config_path = strdup(optarg); |
254 | break; | 234 | break; |
255 | case 'C': // validate | 235 | case 'C': // validate |
256 | validate = 1; | 236 | validate = true; |
257 | break; | 237 | break; |
258 | case 'd': // debug | 238 | case 'd': // debug |
259 | debug = 1; | 239 | debug = true; |
260 | break; | 240 | break; |
261 | case 'D': // extended debug options | 241 | case 'D': // extended debug options |
262 | enable_debug_flag(optarg); | 242 | enable_debug_flag(optarg); |
263 | break; | 243 | break; |
264 | case 'u': | 244 | case 'u': |
265 | allow_unsupported_gpu = 1; | 245 | allow_unsupported_gpu = true; |
266 | break; | 246 | break; |
267 | case 'v': // version | 247 | case 'v': // version |
268 | printf("sway version " SWAY_VERSION "\n"); | 248 | printf("sway version " SWAY_VERSION "\n"); |
269 | exit(EXIT_SUCCESS); | 249 | exit(EXIT_SUCCESS); |
270 | break; | 250 | break; |
271 | case 'V': // verbose | 251 | case 'V': // verbose |
272 | verbose = 1; | 252 | verbose = true; |
273 | break; | 253 | break; |
274 | case 'p': ; // --get-socketpath | 254 | case 'p': // --get-socketpath |
275 | if (getenv("SWAYSOCK")) { | 255 | if (getenv("SWAYSOCK")) { |
276 | printf("%s\n", getenv("SWAYSOCK")); | 256 | printf("%s\n", getenv("SWAYSOCK")); |
277 | exit(EXIT_SUCCESS); | 257 | exit(EXIT_SUCCESS); |
@@ -286,6 +266,11 @@ int main(int argc, char **argv) { | |||
286 | } | 266 | } |
287 | } | 267 | } |
288 | 268 | ||
269 | // SUID operation is deprecated, so block it for now. | ||
270 | if (detect_suid()) { | ||
271 | exit(EXIT_FAILURE); | ||
272 | } | ||
273 | |||
289 | // Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the | 274 | // Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the |
290 | // clear error message (when not running as an IPC client). | 275 | // clear error message (when not running as an IPC client). |
291 | if (!getenv("XDG_RUNTIME_DIR") && optind == argc) { | 276 | if (!getenv("XDG_RUNTIME_DIR") && optind == argc) { |
@@ -312,7 +297,6 @@ int main(int argc, char **argv) { | |||
312 | log_kernel(); | 297 | log_kernel(); |
313 | log_distro(); | 298 | log_distro(); |
314 | log_env(); | 299 | log_env(); |
315 | detect_proprietary(allow_unsupported_gpu); | ||
316 | 300 | ||
317 | if (optind < argc) { // Behave as IPC client | 301 | if (optind < argc) { // Behave as IPC client |
318 | if (optind != 1) { | 302 | if (optind != 1) { |
@@ -325,9 +309,6 @@ int main(int argc, char **argv) { | |||
325 | "`sway -d 2>sway.log`."); | 309 | "`sway -d 2>sway.log`."); |
326 | exit(EXIT_FAILURE); | 310 | exit(EXIT_FAILURE); |
327 | } | 311 | } |
328 | if (!drop_permissions()) { | ||
329 | exit(EXIT_FAILURE); | ||
330 | } | ||
331 | char *socket_path = getenv("SWAYSOCK"); | 312 | char *socket_path = getenv("SWAYSOCK"); |
332 | if (!socket_path) { | 313 | if (!socket_path) { |
333 | sway_log(SWAY_ERROR, "Unable to retrieve socket path"); | 314 | sway_log(SWAY_ERROR, "Unable to retrieve socket path"); |
@@ -339,14 +320,7 @@ int main(int argc, char **argv) { | |||
339 | return 0; | 320 | return 0; |
340 | } | 321 | } |
341 | 322 | ||
342 | if (!server_privileged_prepare(&server)) { | 323 | increase_nofile_limit(); |
343 | return 1; | ||
344 | } | ||
345 | |||
346 | if (!drop_permissions()) { | ||
347 | server_fini(&server); | ||
348 | exit(EXIT_FAILURE); | ||
349 | } | ||
350 | 324 | ||
351 | // handle SIGTERM signals | 325 | // handle SIGTERM signals |
352 | signal(SIGTERM, sig_handler); | 326 | signal(SIGTERM, sig_handler); |
@@ -357,12 +331,14 @@ int main(int argc, char **argv) { | |||
357 | 331 | ||
358 | sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION); | 332 | sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION); |
359 | 333 | ||
360 | root = root_create(); | ||
361 | |||
362 | if (!server_init(&server)) { | 334 | if (!server_init(&server)) { |
363 | return 1; | 335 | return 1; |
364 | } | 336 | } |
365 | 337 | ||
338 | if (server.linux_dmabuf_v1) { | ||
339 | wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1); | ||
340 | } | ||
341 | |||
366 | if (validate) { | 342 | if (validate) { |
367 | bool valid = load_main_config(config_path, false, true); | 343 | bool valid = load_main_config(config_path, false, true); |
368 | free(config_path); | 344 | free(config_path); |
@@ -377,6 +353,8 @@ int main(int argc, char **argv) { | |||
377 | goto shutdown; | 353 | goto shutdown; |
378 | } | 354 | } |
379 | 355 | ||
356 | set_rr_scheduling(); | ||
357 | |||
380 | if (!server_start(&server)) { | 358 | if (!server_start(&server)) { |
381 | sway_terminate(EXIT_FAILURE); | 359 | sway_terminate(EXIT_FAILURE); |
382 | goto shutdown; | 360 | goto shutdown; |