From: Omar Polo Subject: sandboxing the libexec helpers on freebsd To: gameoftrees@openbsd.org Cc: Thomas Adam Date: Sun, 19 Jun 2022 15:14:31 +0200 Admittedly, I don't use freebsd very frequently, but while I was updating my local build of got on a freebsd box i remembered about this diff. I started to working on it in parallel or shortly after the landlock patch, but then got into other things and forgot. I've quickly resumed it, updated to the latest commit in -portable and polished it a bit. Some test fails, probably for the lack of gln (?), but they largely pass. A brief runtime testing also shows that everything works: got commit, update, fetch, histedit, rebase, even tog, so I'm pretty confident. It's also quite simple. cap_enter(2) put the current process into "capability mode", which is a sandbox to make it short. It's somewhat similar to pledge("stdio recvfd") in which prohibits the current process to allocate new file descriptors via most means (like open(2), socket(2), ...) but still allows to using other ways (like accept(2) or openat(2) on already-opened file descriptors -- it doesn't concern us). This comes in handy since the libexec helpers are designed to work on the received resources, not to "take initiatives" by themselves. Heavy testing by freebsd users is welcome! :) Thanks, Omar Polo ----------------------------------------------- commit d885d71d613cc4cea92009597e06484530206fe8 from: Omar Polo date: Sun Jun 19 13:06:37 2022 UTC use capsicum on FreeBSD Thanks to the design of Got, the libexec helpers don't need any resource (in fact they run under pledge "stdio recvfd" on OpenBSD.) and so using cap_enter(2) on FreeBSD is incredibly easy. While the main process can't be sandboxed on FreeBSD (needs to exec the helpers), all the tough work is done by these small libexec helpers; they're the largest attack surface. diff 938cbac05982ceecaddaee35d88f610b077af09c 48e953d21e39fc0873e200640b8d1260631c24c8 blob - 84c18d08658195752f0bf61d826c1f78d5127026 blob + 6cc8083dc2e768ace9adaf6c9c9a767b69b82e4d --- include/got_compat.h +++ include/got_compat.h @@ -69,6 +69,12 @@ #define unveil(s, p) (0) #endif +#ifdef __FreeBSD__ +#include +#else +#define cap_enter() (0) +#endif + #ifndef HAVE_LINUX_LANDLOCK_H #define landlock_no_fs() (0) #else blob - 7b6521625b84fc12679b84419662568f5f0852a1 blob + 1e6bf21a70b5d71aa3b12453c7427e1cad9f6980 --- libexec/got-fetch-pack/got-fetch-pack.c +++ libexec/got-fetch-pack/got-fetch-pack.c @@ -806,6 +806,11 @@ main(int argc, char **argv) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif err = got_privsep_recv_imsg(&imsg, &ibuf, 0); if (err) { blob - bdacb5506ed2ddd855aa4c7392923248c0f2b660 blob + 69517e0d0138f02236f127c0f31b2113c5a9e1f9 --- libexec/got-index-pack/got-index-pack.c +++ libexec/got-index-pack/got-index-pack.c @@ -1026,6 +1026,11 @@ main(int argc, char **argv) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif err = got_privsep_recv_imsg(&imsg, &ibuf, 0); if (err) blob - cea6f43adac14aa61fc01c67ea2223fe2ec4b367 blob + 299dfb1ae0a14b4b599bb567807748669f2fe2cc --- libexec/got-read-blob/got-read-blob.c +++ libexec/got-read-blob/got-read-blob.c @@ -72,6 +72,11 @@ main(int argc, char *argv[]) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif for (;;) { blob - 75b69cf033167c2237a8a02aeebd0f48a8d649ea blob + 31d32d460579f8928aefb999066e715216e80c1b --- libexec/got-read-commit/got-read-commit.c +++ libexec/got-read-commit/got-read-commit.c @@ -126,6 +126,11 @@ main(int argc, char *argv[]) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif for (;;) { blob - 9a8444f947cbb287dff1d1c50162e40102463510 blob + f97c7ff67358e322a048152177e2f9d0b5b81712 --- libexec/got-read-gitconfig/got-read-gitconfig.c +++ libexec/got-read-gitconfig/got-read-gitconfig.c @@ -336,6 +336,11 @@ main(int argc, char *argv[]) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif for (;;) { blob - 6bfa6e6d2db2689f8b43a6da77858220f198e083 blob + ccb786281d0d837592d77d712cd547f65ec906ad --- libexec/got-read-gotconfig/got-read-gotconfig.c +++ libexec/got-read-gotconfig/got-read-gotconfig.c @@ -501,6 +501,11 @@ main(int argc, char *argv[]) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif if (argc > 1) blob - dc0a31bec0e6ec9ca5b23fbc47165af5c10063e5 blob + 2d058e778766c79c6faacb6f95aba7bc0ffa1b47 --- libexec/got-read-object/got-read-object.c +++ libexec/got-read-object/got-read-object.c @@ -147,6 +147,11 @@ main(int argc, char *argv[]) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif for (;;) { blob - 6afe97bed5c5990ece7bbc7bbc1518be65ff5cca blob + 66de093053efe43cabb8c6026df42632fa3dc36f --- libexec/got-read-pack/got-read-pack.c +++ libexec/got-read-pack/got-read-pack.c @@ -1244,6 +1244,11 @@ main(int argc, char *argv[]) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif err = receive_packidx(&packidx, &ibuf); blob - 054a99b50f0835f1ab90b05dabba1586da811977 blob + 38ae3d3bd2f82906942f9ad5658c3a2e8d186d0a --- libexec/got-read-patch/got-read-patch.c +++ libexec/got-read-patch/got-read-patch.c @@ -494,6 +494,11 @@ main(int argc, char **argv) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif err = got_privsep_recv_imsg(&imsg, &ibuf, 0); blob - 57787944b6605bdc56c8281731a46bb5a54f9442 blob + 83d70fe7b21329db35df0e8293775ac32eefeb90 --- libexec/got-read-tag/got-read-tag.c +++ libexec/got-read-tag/got-read-tag.c @@ -121,6 +121,11 @@ main(int argc, char *argv[]) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif for (;;) { blob - cc2d892a4bf2ba8782971f3d1c9761e522456476 blob + d83b9c856cc4d9c93e359dfd5a23171099a23b73 --- libexec/got-read-tree/got-read-tree.c +++ libexec/got-read-tree/got-read-tree.c @@ -120,6 +120,11 @@ main(int argc, char *argv[]) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif for (;;) { blob - 615521693614965f7f1635a2161b3da35c245f85 blob + 128d46236a43f93321fb66a86cb2e648d82eb2b4 --- libexec/got-send-pack/got-send-pack.c +++ libexec/got-send-pack/got-send-pack.c @@ -600,6 +600,11 @@ main(int argc, char **argv) got_privsep_send_error(&ibuf, err); return 1; } + if (cap_enter() == -1) { + err = got_error_from_errno("cap_enter"); + got_privsep_send_error(&ibuf, err); + return 1; + } #endif if ((err = got_privsep_recv_imsg(&imsg, &ibuf, 0)) != 0) { if (err->code == GOT_ERR_PRIVSEP_PIPE)