commit 61e578392ff6b798d3ac93bd416ad55b80b5171d from: Alisdair MacLeod via: Alisdair MacLeod <131350026+admacleod@users.noreply.github.com> date: Tue Mar 24 18:48:13 2026 UTC Document unveil and pledge rationale in main() Expand comments to explain why the database parent directory is unveiled rather than the file itself, why unveil(NULL, NULL) locks the path list, and why fattr is included in the pledge promises. Co-Authored-By: Claude Opus 4.6 (1M context) commit - 2d4e7ca4912b508bcb0e76113e7a99be5f28f245 commit + 61e578392ff6b798d3ac93bd416ad55b80b5171d blob - 4a725df6c99a0c819bf35575c3fe064ce8b71971 blob + d512b12b1e6a25654703e290d008afddc7703a03 --- deskd.c +++ deskd.c @@ -76,9 +76,13 @@ main(int argc, char *argv[]) if (strcmp(dbpath, ":memory:") != 0) { /* - * Unveil the directory containing the database, not just - * the file itself. SQLite creates auxiliary files (-journal, - * -wal, -shm) alongside the database that must be accessible. + * Unveil the parent directory of the database file rather + * than the file itself. unveil(2) grants access to a single + * path; SQLite creates auxiliary files alongside the database + * (-journal, -wal, -shm) which are separate paths that would + * be blocked if only the database file were unveiled. When + * the path has no directory component, unveil the current + * working directory instead. */ char *slash = strrchr(dbpath, '/'); if (slash != NULL) { @@ -98,11 +102,17 @@ main(int argc, char *argv[]) } free(dbpath); + /* Lock the unveil list; no further paths can be added. */ if (unveil(NULL, NULL) != 0) { fprintf(stderr, "unveil lock failed\n"); return 1; } + /* + * Restrict the process to the syscalls needed for CGI I/O and + * SQLite file operations. fattr is required because SQLite + * manipulates file attributes on its journal and WAL files. + */ if (pledge("stdio rpath wpath cpath flock fattr", NULL) != 0) { fprintf(stderr, "pledge failed\n"); return 1;