Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
Commit bdeb891
  • Loading branch information
jirutka committed Nov 29, 2023
2 parents adde37a + bdeb891 commit 1307d7b
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 22 deletions.
4 changes: 2 additions & 2 deletions comm.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "comm.h"
#include "log.h"
#include "swaylock.h"
#include "password-buffer.h"

static int comm[2][2] = {{-1, -1}, {-1, -1}};

Expand All @@ -19,9 +20,8 @@ ssize_t read_comm_request(char **buf_ptr) {
return -1;
}
swaylock_log(LOG_DEBUG, "received pw check request");
char *buf = malloc(size);
char *buf = password_buffer_create(size);
if (!buf) {
swaylock_log_errno(LOG_ERROR, "failed to malloc pw buffer");
return -1;
}
size_t offs = 0;
Expand Down
9 changes: 9 additions & 0 deletions include/password-buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef _SWAY_PASSWORD_BUFFER_H
#define _SWAY_PASSWORD_BUFFER_H

#include <stddef.h>

char *password_buffer_create(size_t size);
void password_buffer_destroy(char *buffer, size_t size);

#endif
3 changes: 2 additions & 1 deletion include/swaylock.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ struct swaylock_args {

struct swaylock_password {
size_t len;
char buffer[1024];
size_t buffer_len;
char *buffer;
};

struct swaylock_state {
Expand Down
10 changes: 5 additions & 5 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "comm.h"
#include "log.h"
#include "loop.h"
#include "password-buffer.h"
#include "pool-buffer.h"
#include "seat.h"
#include "swaylock.h"
Expand Down Expand Up @@ -1811,13 +1812,12 @@ int main(int argc, char **argv) {
state.auth_state = AUTH_STATE_GRACE;
}

#ifdef __linux__
// Most non-linux platforms require root to mlock()
if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) {
swaylock_log(LOG_ERROR, "Unable to mlock() password memory.");
state.password.len = 0;
state.password.buffer_len = 1024;
state.password.buffer = password_buffer_create(state.password.buffer_len);
if (!state.password.buffer) {
return EXIT_FAILURE;
}
#endif

wl_list_init(&state.surfaces);
state.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ sources = [
'loop.c',
'main.c',
'password.c',
'password-buffer.c',
'pool-buffer.c',
'render.c',
'seat.c',
Expand Down
9 changes: 4 additions & 5 deletions pam.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <unistd.h>
#include "comm.h"
#include "log.h"
#include "password-buffer.h"
#include "swaylock.h"

static char *pw_buf = NULL;
Expand Down Expand Up @@ -96,20 +97,18 @@ void run_pw_backend_child(void) {
}

int pam_status = pam_authenticate(auth_handle, 0);
password_buffer_destroy(pw_buf, size);
pw_buf = NULL;

bool success = pam_status == PAM_SUCCESS;
if (!success) {
swaylock_log(LOG_ERROR, "pam_authenticate failed: %s",
get_pam_auth_error(pam_status));
}

if (!write_comm_reply(success)) {
clear_buffer(pw_buf, size);
exit(EXIT_FAILURE);
}

clear_buffer(pw_buf, size);
free(pw_buf);
pw_buf = NULL;
}

pam_setcred(auth_handle, PAM_REFRESH_CRED);
Expand Down
81 changes: 81 additions & 0 deletions password-buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#define _POSIX_C_SOURCE 200809L
#include "password-buffer.h"
#include "log.h"
#include "swaylock.h"
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <sys/mman.h>

static bool mlock_supported = true;
static long int page_size = 0;

static long int get_page_size() {
if (!page_size) {
page_size = sysconf(_SC_PAGESIZE);
}
return page_size;
}

// password_buffer_lock expects addr to be page alligned
static bool password_buffer_lock(char *addr, size_t size) {
int retries = 5;
while (mlock(addr, size) != 0 && retries > 0) {
switch (errno) {
case EAGAIN:
retries--;
if (retries == 0) {
swaylock_log(LOG_ERROR, "mlock() supported but failed too often.");
return false;
}
break;
case EPERM:
swaylock_log_errno(LOG_ERROR, "Unable to mlock() password memory: Unsupported!");
mlock_supported = false;
return true;
default:
swaylock_log_errno(LOG_ERROR, "Unable to mlock() password memory.");
return false;
}
return false;
}

return true;
}

// password_buffer_unlock expects addr to be page alligned
static bool password_buffer_unlock(char *addr, size_t size) {
if (mlock_supported) {
if (munlock(addr, size) != 0) {
swaylock_log_errno(LOG_ERROR, "Unable to munlock() password memory.");
return false;
}
}

return true;
}

char *password_buffer_create(size_t size) {
void *buffer;
int result = posix_memalign(&buffer, get_page_size(), size);
if (result) {
//posix_memalign doesn't set errno according to the man page
errno = result;
swaylock_log_errno(LOG_ERROR, "failed to alloc password buffer");
return NULL;
}

if (!password_buffer_lock(buffer, size)) {
free(buffer);
return NULL;
}

return buffer;
}

void password_buffer_destroy(char *buffer, size_t size) {
clear_buffer(buffer, size);
password_buffer_unlock(buffer, size);
free(buffer);
}
4 changes: 2 additions & 2 deletions password.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void clear_buffer(char *buf, size_t size) {
}

void clear_password_buffer(struct swaylock_password *pw) {
clear_buffer(pw->buffer, sizeof(pw->buffer));
clear_buffer(pw->buffer, pw->buffer_len);
pw->len = 0;
}

Expand All @@ -37,7 +37,7 @@ static bool backspace(struct swaylock_password *pw) {

static void append_ch(struct swaylock_password *pw, uint32_t codepoint) {
size_t utf8_size = utf8_chsize(codepoint);
if (pw->len + utf8_size + 1 >= sizeof(pw->buffer)) {
if (pw->len + utf8_size + 1 >= pw->buffer_len) {
// TODO: Display error
return;
}
Expand Down
11 changes: 4 additions & 7 deletions shadow.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#endif
#include "comm.h"
#include "log.h"
#include "password-buffer.h"
#include "swaylock.h"

void initialize_pw_backend(int argc, char **argv) {
Expand Down Expand Up @@ -81,23 +82,19 @@ void run_pw_backend_child(void) {
}

char *c = crypt(buf, encpw);
password_buffer_destroy(buf, size);
buf = NULL;

if (c == NULL) {
swaylock_log_errno(LOG_ERROR, "crypt failed");
clear_buffer(buf, size);
exit(EXIT_FAILURE);
}
bool success = strcmp(c, encpw) == 0;

if (!write_comm_reply(success)) {
clear_buffer(buf, size);
exit(EXIT_FAILURE);
}

// We don't want to keep it in memory longer than necessary,
// so clear *before* sleeping.
clear_buffer(buf, size);
free(buf);

sleep(2);
}

Expand Down

0 comments on commit 1307d7b

Please sign in to comment.