diff options
author | emersion <contact@emersion.fr> | 2018-10-06 18:47:34 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-06 18:47:34 +0200 |
commit | 176832fe30576ccfbb7dee3d9e600e56abf21da1 (patch) | |
tree | a4ccf0cb0afafc0c8db6cbded85a3b156945b12b | |
parent | Update CONTRIBUTING.md (diff) | |
parent | Fix swaylock w/shadow on glibc, improve security (diff) | |
download | sway-176832fe30576ccfbb7dee3d9e600e56abf21da1.tar.gz sway-176832fe30576ccfbb7dee3d9e600e56abf21da1.tar.zst sway-176832fe30576ccfbb7dee3d9e600e56abf21da1.zip |
Merge pull request #2776 from swaywm/swaylock-setuid
Fix swaylock w/shadow on glibc, improve security
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | swaylock/meson.build | 3 | ||||
-rw-r--r-- | swaylock/shadow.c | 27 |
3 files changed, 31 insertions, 0 deletions
diff --git a/meson.build b/meson.build index 1e7ce281..42386fbc 100644 --- a/meson.build +++ b/meson.build | |||
@@ -44,6 +44,7 @@ gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false) | |||
44 | pixman = dependency('pixman-1') | 44 | pixman = dependency('pixman-1') |
45 | libinput = dependency('libinput', version: '>=1.6.0') | 45 | libinput = dependency('libinput', version: '>=1.6.0') |
46 | libpam = cc.find_library('pam', required: false) | 46 | libpam = cc.find_library('pam', required: false) |
47 | crypt = cc.find_library('crypt', required: false) | ||
47 | systemd = dependency('libsystemd', required: false) | 48 | systemd = dependency('libsystemd', required: false) |
48 | elogind = dependency('libelogind', required: false) | 49 | elogind = dependency('libelogind', required: false) |
49 | math = cc.find_library('m') | 50 | math = cc.find_library('m') |
diff --git a/swaylock/meson.build b/swaylock/meson.build index 6605340b..f3321a78 100644 --- a/swaylock/meson.build +++ b/swaylock/meson.build | |||
@@ -26,6 +26,9 @@ else | |||
26 | warning('The swaylock binary must be setuid when compiled without libpam') | 26 | warning('The swaylock binary must be setuid when compiled without libpam') |
27 | warning('You must do this manually post-install: chmod a+s /path/to/swaylock') | 27 | warning('You must do this manually post-install: chmod a+s /path/to/swaylock') |
28 | sources += ['shadow.c'] | 28 | sources += ['shadow.c'] |
29 | if crypt.found() | ||
30 | dependencies += [crypt] | ||
31 | endif | ||
29 | endif | 32 | endif |
30 | 33 | ||
31 | executable('swaylock', | 34 | executable('swaylock', |
diff --git a/swaylock/shadow.c b/swaylock/shadow.c index 1f10514c..f928eaa3 100644 --- a/swaylock/shadow.c +++ b/swaylock/shadow.c | |||
@@ -6,9 +6,21 @@ | |||
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <wlr/util/log.h> | 7 | #include <wlr/util/log.h> |
8 | #include "swaylock/swaylock.h" | 8 | #include "swaylock/swaylock.h" |
9 | #ifdef __GLIBC__ | ||
10 | // GNU, you damn slimy bastard | ||
11 | #include <crypt.h> | ||
12 | #endif | ||
9 | 13 | ||
10 | static int comm[2][2]; | 14 | static int comm[2][2]; |
11 | 15 | ||
16 | static void clear_buffer(void *buf, size_t bytes) { | ||
17 | volatile char *buffer = buf; | ||
18 | volatile char zero = '\0'; | ||
19 | for (size_t i = 0; i < bytes; ++i) { | ||
20 | buffer[i] = zero; | ||
21 | } | ||
22 | } | ||
23 | |||
12 | void run_child(void) { | 24 | void run_child(void) { |
13 | /* This code runs as root */ | 25 | /* This code runs as root */ |
14 | struct passwd *pwent = getpwuid(getuid()); | 26 | struct passwd *pwent = getpwuid(getuid()); |
@@ -25,6 +37,17 @@ void run_child(void) { | |||
25 | } | 37 | } |
26 | encpw = swent->sp_pwdp; | 38 | encpw = swent->sp_pwdp; |
27 | } | 39 | } |
40 | |||
41 | /* We don't need any additional logging here because the parent process will | ||
42 | * also fail here and will handle logging for us. */ | ||
43 | if (setgid(getgid()) != 0) { | ||
44 | exit(EXIT_FAILURE); | ||
45 | } | ||
46 | if (setuid(getuid()) != 0) { | ||
47 | exit(EXIT_FAILURE); | ||
48 | } | ||
49 | |||
50 | /* This code does not run as root */ | ||
28 | wlr_log(WLR_DEBUG, "prepared to authorize user %s", pwent->pw_name); | 51 | wlr_log(WLR_DEBUG, "prepared to authorize user %s", pwent->pw_name); |
29 | 52 | ||
30 | size_t size; | 53 | size_t size; |
@@ -60,10 +83,14 @@ void run_child(void) { | |||
60 | result = strcmp(c, encpw) == 0; | 83 | result = strcmp(c, encpw) == 0; |
61 | if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) { | 84 | if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) { |
62 | wlr_log_errno(WLR_ERROR, "failed to write pw check result"); | 85 | wlr_log_errno(WLR_ERROR, "failed to write pw check result"); |
86 | clear_buffer(buf, size); | ||
63 | exit(EXIT_FAILURE); | 87 | exit(EXIT_FAILURE); |
64 | } | 88 | } |
89 | clear_buffer(buf, size); | ||
65 | free(buf); | 90 | free(buf); |
66 | } | 91 | } |
92 | |||
93 | clear_buffer(encpw, strlen(encpw)); | ||
67 | exit(EXIT_SUCCESS); | 94 | exit(EXIT_SUCCESS); |
68 | } | 95 | } |
69 | 96 | ||