mirror of
https://github.com/swaywm/sway.git
synced 2024-11-17 13:42:36 +00:00
Merge pull request #2776 from swaywm/swaylock-setuid
Fix swaylock w/shadow on glibc, improve security
This commit is contained in:
commit
176832fe30
|
@ -44,6 +44,7 @@ gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false)
|
||||||
pixman = dependency('pixman-1')
|
pixman = dependency('pixman-1')
|
||||||
libinput = dependency('libinput', version: '>=1.6.0')
|
libinput = dependency('libinput', version: '>=1.6.0')
|
||||||
libpam = cc.find_library('pam', required: false)
|
libpam = cc.find_library('pam', required: false)
|
||||||
|
crypt = cc.find_library('crypt', required: false)
|
||||||
systemd = dependency('libsystemd', required: false)
|
systemd = dependency('libsystemd', required: false)
|
||||||
elogind = dependency('libelogind', required: false)
|
elogind = dependency('libelogind', required: false)
|
||||||
math = cc.find_library('m')
|
math = cc.find_library('m')
|
||||||
|
|
|
@ -26,6 +26,9 @@ else
|
||||||
warning('The swaylock binary must be setuid when compiled without libpam')
|
warning('The swaylock binary must be setuid when compiled without libpam')
|
||||||
warning('You must do this manually post-install: chmod a+s /path/to/swaylock')
|
warning('You must do this manually post-install: chmod a+s /path/to/swaylock')
|
||||||
sources += ['shadow.c']
|
sources += ['shadow.c']
|
||||||
|
if crypt.found()
|
||||||
|
dependencies += [crypt]
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
executable('swaylock',
|
executable('swaylock',
|
||||||
|
|
|
@ -6,9 +6,21 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "swaylock/swaylock.h"
|
#include "swaylock/swaylock.h"
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
// GNU, you damn slimy bastard
|
||||||
|
#include <crypt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static int comm[2][2];
|
static int comm[2][2];
|
||||||
|
|
||||||
|
static void clear_buffer(void *buf, size_t bytes) {
|
||||||
|
volatile char *buffer = buf;
|
||||||
|
volatile char zero = '\0';
|
||||||
|
for (size_t i = 0; i < bytes; ++i) {
|
||||||
|
buffer[i] = zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void run_child(void) {
|
void run_child(void) {
|
||||||
/* This code runs as root */
|
/* This code runs as root */
|
||||||
struct passwd *pwent = getpwuid(getuid());
|
struct passwd *pwent = getpwuid(getuid());
|
||||||
|
@ -25,6 +37,17 @@ void run_child(void) {
|
||||||
}
|
}
|
||||||
encpw = swent->sp_pwdp;
|
encpw = swent->sp_pwdp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We don't need any additional logging here because the parent process will
|
||||||
|
* also fail here and will handle logging for us. */
|
||||||
|
if (setgid(getgid()) != 0) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (setuid(getuid()) != 0) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This code does not run as root */
|
||||||
wlr_log(WLR_DEBUG, "prepared to authorize user %s", pwent->pw_name);
|
wlr_log(WLR_DEBUG, "prepared to authorize user %s", pwent->pw_name);
|
||||||
|
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -60,10 +83,14 @@ void run_child(void) {
|
||||||
result = strcmp(c, encpw) == 0;
|
result = strcmp(c, encpw) == 0;
|
||||||
if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) {
|
if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) {
|
||||||
wlr_log_errno(WLR_ERROR, "failed to write pw check result");
|
wlr_log_errno(WLR_ERROR, "failed to write pw check result");
|
||||||
|
clear_buffer(buf, size);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
clear_buffer(buf, size);
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_buffer(encpw, strlen(encpw));
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue