pit
refactor
aa3c45b800fd0cff3cddede1eca800f6e5438ea1
IIIlllIIIllI <seb.michalk@gmail.com>
2026-01-17 11:36:44 +0000
Makefile | 2 - config.mk | 2 - pit.c | 160 ++++++++++++++++++++++++++------------------------------------ 3 files changed, 67 insertions(+), 97 deletions(-) diff --git a/Makefile b/Makefile index ce7e028..03002cb 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,3 @@ -# pit - encrypted container utility - include config.mk SRC = pit.c diff --git a/config.mk b/config.mk index e86b8a5..ecc3737 100644 --- a/config.mk +++ b/config.mk @@ -1,8 +1,6 @@ -# pit version VERSION = 0.1 -# paths PREFIX = /usr/local # includes and libs diff --git a/pit.c b/pit.c index 85b966c..b3421de 100644 --- a/pit.c +++ b/pit.c @@ -1,7 +1,7 @@ -/* pit +/* pit * See LICENSE file for copyright and license details. */ #define _POSIX_C_SOURCE 200809L -#define _DEFAULT_SOURCE +#define _DEFAULT_SOURCE #include <ctype.h> #include <dirent.h> #include <errno.h> @@ -24,9 +24,8 @@ #include <termios.h> #include <unistd.h> -/* sizes */ #define PIT_BLOCK_SIZE 4096 -#define KEY_SIZE 32 /* 256 bit */ +#define KEY_SIZE 32 #define SALT_SIZE 32 #define ITER_COUNT 500000 @@ -41,7 +40,6 @@ #define KEYFILE_PAYLOAD_SIZE (KEY_SIZE + WRAP_MAC_SIZE) #define KEYFILE_SIZE (SALT_SIZE + WRAP_NONCE_SIZE + KEYFILE_PAYLOAD_SIZE) -/* cipher conf */ #define CIPHER "aes" #define CIPHER_MODE "xts-plain64" #define HASH "sha256" @@ -86,7 +84,6 @@ static int cleanup_stale_device(const char *name); static int setup_device_mapper(const char *path, const char *key); static int teardown_device_mapper(const char *path); static int check_filesystem(const char *device); -static int debug_fs_info(const char *device); static int create_filesystem(const char *device); static int ensure_mount_dir(void); static int create_mount_point(const char *path); @@ -98,13 +95,10 @@ static int list_pits(void); static int find_mounted_pits(char ***paths, int *count); static int panic_close(void); -/* globals */ static const char *program_name; static int term_modified = 0; static struct termios saved_term; static long pagesize; - -/* function implementations */ static void die(const char *fmt, ...) { @@ -120,7 +114,7 @@ static int init_sec_mem(void) { struct rlimit rlim; - size_t required_mem = 8 * 1024 * 1024; /* 8mb minimum */ + size_t required_mem = 8 * 1024 * 1024; if (getrlimit(RLIMIT_MEMLOCK, &rlim) == 0) { if (rlim.rlim_cur < required_mem) { @@ -153,7 +147,7 @@ xrealloc(void *p, size_t len) static void * secure_alloc(size_t size) { - void *ptr; + void *ptr; if (pagesize <= 0) { pagesize = sysconf(_SC_PAGESIZE); @@ -188,7 +182,7 @@ secure_free(void *ptr, size_t size) } } -static void +static void usage(void) { die("usage: pit [-v] [-h] command [arguments]\n" @@ -234,14 +228,13 @@ read_password(char *password, size_t size, const char *prompt) return -1; new = saved_term; - new.c_lflag &= ~ECHO; /* disable echo */ + new.c_lflag &= ~ECHO; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new) != 0) return -1; - term_modified = 1; + term_modified = 1; - /* Show prompt and get password */ fprintf(stderr, "%s", prompt); fflush(stderr); @@ -347,6 +340,8 @@ generate_key(const char *keyfile) int fd = -1; int ret = -1; size_t i; + size_t total; + ssize_t written; int derived = -1; randombytes_buf(master, KEY_SIZE); @@ -401,9 +396,9 @@ generate_key(const char *keyfile) goto cleanup; } - size_t total = 0; + total = 0; while (total < KEYFILE_SIZE) { - ssize_t written = write(fd, filebuf + total, KEYFILE_SIZE - total); + written = write(fd, filebuf + total, KEYFILE_SIZE - total); if (written < 0) { if (errno == EINTR) continue; @@ -439,6 +434,7 @@ create_pit(const char *path, size_t size) int fd; char *buf = secure_alloc(PIT_BLOCK_SIZE); size_t remain; + ssize_t nwrite; if (!buf) { die("pit: out of memory\n"); @@ -453,17 +449,16 @@ create_pit(const char *path, size_t size) randombytes_buf(buf, PIT_BLOCK_SIZE); - remain = size * 1024 * 1024; + remain = size * 1024 * 1024; while (remain > 0) { - ssize_t nwrite = write(fd, buf, PIT_BLOCK_SIZE); + nwrite = write(fd, buf, PIT_BLOCK_SIZE); if (nwrite < 0) { close(fd); secure_free(buf, PIT_BLOCK_SIZE); die("pit: write error: %s\n", strerror(errno)); } remain -= nwrite; - - /* refresh random data every 50 blocks */ + if (remain % (50 * PIT_BLOCK_SIZE) == 0) randombytes_buf(buf, PIT_BLOCK_SIZE); } @@ -556,7 +551,7 @@ get_mapper_path(const char *path) { static char mapper[PATH_MAX]; const char *name = strrchr(path, '/'); - + name = name ? name + 1 : path; snprintf(mapper, sizeof(mapper), "/dev/mapper/%s%s", MAPPER_PREFIX, name); return mapper; @@ -568,11 +563,11 @@ cleanup_stale_device(const char *name) char path[PATH_MAX]; struct stat st; const char *mapper_name; - + mapper_name = strrchr(get_mapper_path(name), '/'); if (!mapper_name) return -1; - mapper_name++; + mapper_name++; snprintf(path, sizeof(path), "/dev/mapper/%s", mapper_name); if (stat(path, &st) == 0) { @@ -580,7 +575,7 @@ cleanup_stale_device(const char *name) int r; printf("pit: cleaning up stale device %s\n", mapper_name); - + r = crypt_init_by_name(&cd, mapper_name); if (r < 0) { fprintf(stderr, "pit: failed to init device %s\n", mapper_name); @@ -589,7 +584,7 @@ cleanup_stale_device(const char *name) r = crypt_deactivate(cd, mapper_name); crypt_free(cd); - + if (r < 0) { fprintf(stderr, "pit: failed to deactivate stale device %s\n", mapper_name); return -1; @@ -611,7 +606,7 @@ setup_device_mapper(const char *path, const char *key) return -1; mapper_name = strrchr(mapper_path, '/') + 1; - if (cleanup_stale_device(path) < 0){ + if (cleanup_stale_device(path) < 0) { fprintf(stderr, "pit: failed to clean up stale device\n"); return -1; } @@ -624,8 +619,8 @@ setup_device_mapper(const char *path, const char *key) r = crypt_load(cd, CRYPT_LUKS1, NULL); if (r == 0) { - - r = crypt_activate_by_passphrase(cd, mapper_name, + + r = crypt_activate_by_passphrase(cd, mapper_name, CRYPT_ANY_SLOT, key, KEY_SIZE, 0); if (r < 0) { @@ -650,7 +645,7 @@ setup_device_mapper(const char *path, const char *key) } r = crypt_keyslot_add_by_volume_key(cd, 0, NULL, 0, - key, KEY_SIZE); + key, KEY_SIZE); if (r < 0) { fprintf(stderr, "pit: failed to add keyslot\n"); crypt_free(cd); @@ -703,7 +698,7 @@ static int check_filesystem(const char *device) { int fd; - unsigned char buf[2048]; /* ext4 superblock starts at offset 1024 */ + unsigned char buf[2048]; ssize_t bytes_read; fd = open(device, O_RDONLY); @@ -724,26 +719,6 @@ check_filesystem(const char *device) return (buf[0x38] == 0x53 && buf[0x39] == 0xEF); } -static int -debug_fs_info(const char *device) -{ - pid_t pid; - int status; - - pid = fork(); - if (pid < 0) { - return -1; - } - - if (pid == 0) { - execl("/sbin/tune2fs", "tune2fs", "-l", device, NULL); - _exit(1); - } - - waitpid(pid, &status, 0); - return WIFEXITED(status) ? WEXITSTATUS(status) : -1; -} - static int open_pit(const char *path, const char *keyfile) { @@ -773,7 +748,6 @@ open_pit(const char *path, const char *keyfile) if (!mapper_path) die("pit: failed to get mapper path\n"); - /* only create filesystem if one doesn't exist */ printf("pit: checking fs on %s\n", mapper_path); if (!check_filesystem(mapper_path)) { printf("pit: no filesystem detected, creating new one\n"); @@ -783,10 +757,8 @@ open_pit(const char *path, const char *keyfile) } } else { printf("pit: existing filesystem found\n"); - /* debug_fs_info(mapper_path); */ } - /* Create mount point */ if (create_mount_point(path) < 0) { teardown_device_mapper(path); die("pit: failed to create mount point\n"); @@ -813,17 +785,17 @@ list_pits(void) int count = 0; int ret = 0; int i = 0; - + if (find_mounted_pits(&mounted_paths, &count) < 0) { fprintf(stderr, "pit: failed to find mounted pits\n"); return -1; } - + if (count == 0) { printf("pit: no pits currently mounted\n"); } else { printf("pit: %d pit%s currently mounted:\n", count, count == 1 ? "" : "s"); - + for (i = 0; i < count; i++) { if (mounted_paths[i]) { char device_path[PATH_MAX] = {0}; @@ -834,7 +806,7 @@ list_pits(void) char mnt_path[PATH_MAX] = {0}; char dev_path[PATH_MAX] = {0}; sscanf(line, "%s %s", dev_path, mnt_path); - + if (strcmp(mnt_path, mounted_paths[i]) == 0) { strncpy(device_path, dev_path, PATH_MAX - 1); break; @@ -842,7 +814,7 @@ list_pits(void) } fclose(mtab); } - + if (device_path[0]) { const char *mapper_prefix = "/dev/mapper/pit-"; if (strncmp(device_path, mapper_prefix, strlen(mapper_prefix)) == 0) { @@ -853,12 +825,12 @@ list_pits(void) } else { printf(" %s\n", mounted_paths[i]); } - + free(mounted_paths[i]); } } } - + free(mounted_paths); return ret; } @@ -913,7 +885,6 @@ create_filesystem(const char *device) } if (pid == 0) { - execl("/sbin/mkfs.ext4", "mkfs.ext4", "-q", "-F", device, NULL); fprintf(stderr, "pit: exec mkfs.ext4 failed: %s\n", strerror(errno)); _exit(1); @@ -971,7 +942,6 @@ close_pit(const char *path) if (!S_ISREG(st.st_mode)) die("pit: %s is not a regular file\n", path); - /* Unmount filesystem */ name = strrchr(path, '/'); name = name ? name + 1 : path; snprintf(mount_dir, sizeof(mount_dir), "%s%s", MOUNTPOINT_PREFIX, name); @@ -979,7 +949,6 @@ close_pit(const char *path) if (unmount_filesystem(mount_dir) < 0) die("pit: failed to unmount filesystem\n"); - /* Teardown device mapper */ r = teardown_device_mapper(path); if (r < 0) die("pit: failed to teardown device mapper\n"); @@ -995,7 +964,7 @@ find_mounted_pits(char ***paths, int *count) char line[PATH_MAX]; char **list = NULL; int n = 0; - + mtab = fopen("/proc/mounts", "r"); if (!mtab) { fprintf(stderr, "pit: cannot open /proc/mounts\n"); @@ -1003,16 +972,20 @@ find_mounted_pits(char ***paths, int *count) } while (fgets(line, sizeof(line), mtab)) { + char *space; + char *mountpoint; + int i; + if (strstr(line, MOUNTPOINT_PREFIX)) { - char *space = strchr(line, ' '); + space = strchr(line, ' '); if (!space) continue; - + list = xrealloc(list, (n + 1) * sizeof(char *)); *space = '\0'; space++; - char *mountpoint = space; + mountpoint = space; space = strchr(mountpoint, ' '); if (!space) continue; @@ -1021,7 +994,7 @@ find_mounted_pits(char ***paths, int *count) list[n] = strdup(mountpoint); if (!list[n]) { fclose(mtab); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) free(list[i]); free(list); die("pit: strdup failed: %s\n", strerror(errno)); @@ -1036,7 +1009,6 @@ find_mounted_pits(char ***paths, int *count) return 0; } -/* panic_close forcefully, without any save attempt, closes the mounts by pit */ static int panic_close(void) { @@ -1045,34 +1017,39 @@ panic_close(void) int ret = 0; char **mounted = NULL; int count = 0; + int i; if (geteuid() != 0) { return run_privileged("%s panic", program_name); } - /* first find our mounted pits */ if (find_mounted_pits(&mounted, &count) == 0 && count > 0) { printf("pit: force closing %d containers...\n", count); - - for (int i = 0; i < count; i++) { - if (!mounted[i]) continue; - /* check /proc for processes using this mount */ - DIR *proc_dir = opendir("/proc"); + for (i = 0; i < count; i++) { + DIR *proc_dir; + struct dirent *pid_dir; + char path[PATH_MAX]; + char link[PATH_MAX]; + ssize_t len; + pid_t pid; + + if (!mounted[i]) + continue; + + proc_dir = opendir("/proc"); if (proc_dir) { - struct dirent *pid_dir; while ((pid_dir = readdir(proc_dir)) != NULL) { - if (!isdigit(pid_dir->d_name[0])) + if (!isdigit(pid_dir->d_name[0])) continue; - char path[PATH_MAX], link[PATH_MAX]; snprintf(path, sizeof(path), "/proc/%s/cwd", pid_dir->d_name); - - ssize_t len = readlink(path, link, sizeof(link) - 1); + + len = readlink(path, link, sizeof(link) - 1); if (len > 0) { link[len] = '\0'; if (strstr(link, mounted[i])) { - pid_t pid = atoi(pid_dir->d_name); + pid = atoi(pid_dir->d_name); printf("pit: killing process %d using %s\n", pid, mounted[i]); kill(pid, SIGKILL); } @@ -1082,11 +1059,10 @@ panic_close(void) usleep(100000); } - /* Force unmount */ printf("pit: force unmounting %s\n", mounted[i]); if (umount2(mounted[i], MNT_FORCE | MNT_DETACH) < 0) { - fprintf(stderr, "pit: cannot unmount %s: %s\n", - mounted[i], strerror(errno)); + fprintf(stderr, "pit: cannot unmount %s: %s\n", + mounted[i], strerror(errno)); } rmdir(mounted[i]); free(mounted[i]); @@ -1094,7 +1070,6 @@ panic_close(void) free(mounted); } - /* force close all pit mappers */ dir = opendir("/dev/mapper"); if (!dir) { fprintf(stderr, "pit: cannot open /dev/mapper: %s\n", strerror(errno)); @@ -1103,8 +1078,9 @@ panic_close(void) while ((dp = readdir(dir)) != NULL) { if (strncmp(dp->d_name, MAPPER_PREFIX, strlen(MAPPER_PREFIX)) == 0) { - printf("pit: force closing device %s\n", dp->d_name); struct crypt_device *cd; + + printf("pit: force closing device %s\n", dp->d_name); if (crypt_init_by_name(&cd, dp->d_name) == 0) { crypt_deactivate_by_name(cd, dp->d_name, CRYPT_DEACTIVATE_FORCE); crypt_free(cd); @@ -1137,29 +1113,27 @@ main(int argc, char *argv[]) die("pit: cannot initialize sodium\n"); if (!strcmp(argv[1], "key")) { - if (argc != 3) + if (argc != 3) usage(); if (generate_key(argv[2]) < 0) die("pit: cannot generate key\n"); return 0; } - if (!strcmp(argv[1], "dig") || + if (!strcmp(argv[1], "dig") || !strcmp(argv[1], "open") || !strcmp(argv[1], "close") || !strcmp(argv[1], "panic")) { - if (geteuid() != 0) { - char cmd[4096] = {0}; int i; - + strcat(cmd, program_name); for (i = 1; i < argc; i++) { strcat(cmd, " "); strcat(cmd, argv[i]); } - + return run_privileged("%s", cmd); } }