main
44ceea7 ยท 1 month ago 7 commits
 1#define _POSIX_C_SOURCE 200809L
 2#include "password-buffer.h"
 3#include "log.h"
 4#include "swaylock.h"
 5#include <stdlib.h>
 6#include <errno.h>
 7#include <unistd.h>
 8#include <limits.h>
 9#include <sys/mman.h>
10
11static bool mlock_supported = true;
12static long int page_size = 0;
13
14static long int get_page_size() {
15	if (!page_size) {
16		page_size = sysconf(_SC_PAGESIZE);
17	}
18	return page_size;
19}
20
21// password_buffer_lock expects addr to be page alligned
22static bool password_buffer_lock(char *addr, size_t size) {
23	int retries = 5;
24	while (mlock(addr, size) != 0 && retries > 0) {
25		switch (errno) {
26		case EAGAIN:
27			retries--;
28			if (retries == 0) {
29				swaylock_log(LOG_ERROR, "mlock() supported but failed too often.");
30				return false;
31			}
32			break;
33		case EPERM:
34			swaylock_log_errno(LOG_ERROR, "Unable to mlock() password memory: Unsupported!");
35			mlock_supported = false;
36			return true;
37		default:
38			swaylock_log_errno(LOG_ERROR, "Unable to mlock() password memory.");
39			return false;
40		}
41		return false;
42	}
43
44	return true;
45}
46
47// password_buffer_unlock expects addr to be page alligned
48static bool password_buffer_unlock(char *addr, size_t size) {
49	if (mlock_supported) {
50		if (munlock(addr, size) != 0) {
51			swaylock_log_errno(LOG_ERROR, "Unable to munlock() password memory.");
52			return false;
53		}
54	}
55
56	return true;
57}
58
59char *password_buffer_create(size_t size) {
60	void *buffer;
61	int result = posix_memalign(&buffer, get_page_size(), size);
62	if (result) {
63		//posix_memalign doesn't set errno according to the man page
64		errno = result;
65		swaylock_log_errno(LOG_ERROR, "failed to alloc password buffer");
66		return NULL;
67	}
68
69	if (!password_buffer_lock(buffer, size)) {
70		free(buffer);
71		return NULL;
72	}
73
74	return buffer;
75}
76
77void password_buffer_destroy(char *buffer, size_t size) {
78	clear_buffer(buffer, size);
79	password_buffer_unlock(buffer, size);
80	free(buffer);
81}