From ea1313d80d5ee1623b00c8cdf6e7ff8a7e14c2ae Mon Sep 17 00:00:00 2001 From: Mykyta Holubakha Date: Thu, 12 Jan 2017 04:25:03 +0200 Subject: [PATCH 1/2] Keep CAP_SYS_PTRACE with suid binary --- sway/main.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sway/main.c b/sway/main.c index e8a02e7a..6c74aab2 100644 --- a/sway/main.c +++ b/sway/main.c @@ -10,6 +10,9 @@ #include #include #include +#ifdef __linux__ +#include +#endif #include "sway/extensions.h" #include "sway/layout.h" #include "sway/config.h" @@ -289,6 +292,18 @@ int main(int argc, char **argv) { return 0; } +#ifdef __linux__ + bool suid = false; + if (getuid() != geteuid() || getgid() != getegid()) { + // Retain capabilities after setuid() + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { + sway_log(L_ERROR, "Cannot keep caps after setuid()"); + exit(EXIT_FAILURE); + } + suid = true; + } +#endif + // we need to setup logging before wlc_init in case it fails. if (debug) { init_log(L_DEBUG); @@ -311,6 +326,19 @@ int main(int argc, char **argv) { } register_extensions(); +#ifdef __linux__ + if (suid) { + // Drop every cap except CAP_SYS_PTRACE + cap_t caps = cap_init(); + cap_value_t keep = CAP_SYS_PTRACE; + if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || + cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || + cap_set_proc(caps)) { + sway_log(L_ERROR, "Failed to drop extra capabilities"); + exit(EXIT_FAILURE); + } + } +#endif // handle SIGTERM signals signal(SIGTERM, sig_handler); From d9ba61d7e91c5aceef1a6a736dc65f0594b9be2a Mon Sep 17 00:00:00 2001 From: Mykyta Holubakha Date: Thu, 12 Jan 2017 04:35:09 +0200 Subject: [PATCH 2/2] Log capability dropping --- sway/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/main.c b/sway/main.c index 6c74aab2..7bf71b53 100644 --- a/sway/main.c +++ b/sway/main.c @@ -331,6 +331,7 @@ int main(int argc, char **argv) { // Drop every cap except CAP_SYS_PTRACE cap_t caps = cap_init(); cap_value_t keep = CAP_SYS_PTRACE; + sway_log(L_INFO, "Dropping extra capabilities"); if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || cap_set_proc(caps)) {