commit - 1f480907e29bc783454427371277ef33a25658e4
commit + 97799ccd4b67a81f97039305d4fdd66588da9962
blob - 958a3d67dfe92ddf1caf9fd8e3586f887a36001b
blob + 0b90a45a21dee8de83282118e67277aef5bd3370
--- compat/Makefile.am
+++ compat/Makefile.am
libopenbsd_compat_a_SOURCES += uuid.c
endif
+if HAVE_LINUX_LANDLOCK
+libopenbsd_compat_a_SOURCES += landlock.c
+endif
+
EXTRA_DIST = \
$(top_srcdir)/include/got_compat.h \
imsg.h \
blob - /dev/null
blob + 47a5209dbfe20f149a142f16faaca86ca659120c (mode 644)
--- /dev/null
+++ compat/landlock.c
+/*
+ * Copyright (c) 2021 Omar Polo <op@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/landlock.h>
+#include <linux/prctl.h>
+
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "got_compat.h"
+
+/*
+ * What's the deal with landlock? While distro with linux >= 5.13
+ * have the struct declarations, libc wrappers are missing. The
+ * sample landlock code provided by the authors includes these "shims"
+ * in their example for the landlock API until libc provides them.
+ */
+
+#ifndef landlock_create_ruleset
+static inline int
+landlock_create_ruleset(const struct landlock_ruleset_attr *attr, size_t size,
+ __u32 flags)
+{
+ return syscall(__NR_landlock_create_ruleset, attr, size, flags);
+}
+#endif
+
+#ifndef landlock_add_rule
+static inline int
+landlock_add_rule(int ruleset_fd, enum landlock_rule_type type,
+ const void *attr, __u32 flags)
+{
+ return syscall(__NR_landlock_add_rule, ruleset_fd, type, attr, flags);
+}
+#endif
+
+#ifndef landlock_restrict_self
+static inline int
+landlock_restrict_self(int ruleset_fd, __u32 flags)
+{
+ return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
+}
+#endif
+
+/*
+ * Revoke any fs access.
+ */
+int
+landlock_no_fs(void)
+{
+ struct landlock_ruleset_attr rattr = {
+ /*
+ * handled_access_fs can't be zero! Even if we don't
+ * add any path at all with landlock_add_rule, and thus
+ * rejecting *any* filesystem access, we still have to
+ * list some "possible actions" here.
+ */
+ .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
+ };
+ int fd, saved_errno;
+
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
+ return -1;
+
+ fd = landlock_create_ruleset(&rattr, sizeof(rattr), 0);
+ if (fd == -1) {
+ /* this kernel doesn't have landlock built in */
+ if (errno == ENOSYS || errno == ENOTSUP)
+ return 0;
+ return -1;
+ }
+
+ if (landlock_restrict_self(fd, 0)) {
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
blob - a9b188be681d73c01d831cd71a266058697cd6ab
blob + 44604f740f93329e013205265626d19b5450fe04
--- configure.ac
+++ configure.ac
fcntl.h \
langinfo.h \
limits.h \
+ linux/landlock.h \
locale.h \
netdb.h \
netinet/in.h \
AM_CONDITIONAL([HOST_FREEBSD], [test "$PLATFORM" = "freebsd"])
AM_CONDITIONAL([HOST_LINUX], [test "$PLATFORM" = "linux"])
+# Landlock detection.
+AC_MSG_CHECKING([for landlock])
+AM_CONDITIONAL([HAVE_LINUX_LANDLOCK],
+ [test "x$ac_cv_header_linux_landlock_h" = "xyes"])
+if test "x$ac_cv_header_linux_landlock_h" = "xyes"; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
# Clang sanitizers wrap reallocarray even if it isn't available on the target
# system. When compiled it always returns NULL and crashes the program. To
# detect this we need a more complicated test.
blob - c07416a808a6799841c0c9978d004659680beda2
blob + 43e2e48d8e287757aa51bd8b89fa4d136904b88d
--- include/got_compat.h
+++ include/got_compat.h
#ifndef __OpenBSD__
#define pledge(s, p) (0)
#define unveil(s, p) (0)
+#endif
+
+#ifndef HAVE_LINUX_LANDLOCK_H
+#define landlock_no_fs() (0)
+#else
+int landlock_no_fs(void);
#endif
#ifndef INFTIM
blob - 65c075409a0f6850f37b585385b6429b80a143ed
blob + 5d5fc4944fb66148926a3e2aa218adf907063461
--- libexec/got-fetch-pack/got-fetch-pack.c
+++ libexec/got-fetch-pack/got-fetch-pack.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
blob - b8572cfe5b35acf5d04456dc811ef5e1cf3b918d
blob + bfaf074f9691171d53deb75a04179c2f13c5fbc3
--- libexec/got-index-pack/got-index-pack.c
+++ libexec/got-index-pack/got-index-pack.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err)
blob - 24a9911b4e2319200c86e0be0d525a3980763d80
blob + cea6f43adac14aa61fc01c67ea2223fe2ec4b367
--- libexec/got-read-blob/got-read-blob.c
+++ libexec/got-read-blob/got-read-blob.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
for (;;) {
blob - f324bf809bdb1dbc68030ee2676b88f4ec11dc4e
blob + 75b69cf033167c2237a8a02aeebd0f48a8d649ea
--- libexec/got-read-commit/got-read-commit.c
+++ libexec/got-read-commit/got-read-commit.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
for (;;) {
blob - 9820c8bd9e58d215598df363fdb6e25fbd81323d
blob + 1ccc67e3c4467f8056bf23a367d62431de5219bd
--- libexec/got-read-gitconfig/got-read-gitconfig.c
+++ libexec/got-read-gitconfig/got-read-gitconfig.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
for (;;) {
blob - 69f6999b8df42a9f230c521287de6e5aadebd128
blob + 3b954345ac46a733c1c785bd2af8facdac0a4f34
--- libexec/got-read-gotconfig/got-read-gotconfig.c
+++ libexec/got-read-gotconfig/got-read-gotconfig.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
if (argc > 1)
blob - 3d9bc64ad66ca532a2c58b8d50e3d4ab51abb4db
blob + dc0a31bec0e6ec9ca5b23fbc47165af5c10063e5
--- libexec/got-read-object/got-read-object.c
+++ libexec/got-read-object/got-read-object.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
for (;;) {
blob - 760a54783d11db6cc8fed461bc956854e6b5f2ed
blob + 722e0c736645f1324e288c3f065a34ec6f45c449
--- libexec/got-read-pack/got-read-pack.c
+++ libexec/got-read-pack/got-read-pack.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
err = receive_packidx(&packidx, &ibuf);
blob - 870e8ca6c8d4439248bc960e5d6797861de4de07
blob + 57787944b6605bdc56c8281731a46bb5a54f9442
--- libexec/got-read-tag/got-read-tag.c
+++ libexec/got-read-tag/got-read-tag.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
for (;;) {
blob - 35323190d763a2a21c96e0b0f6c3d19f6687f007
blob + 7a53a1be870ee3435986176c3800ecefc8647a04
--- libexec/got-read-tree/got-read-tree.c
+++ libexec/got-read-tree/got-read-tree.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
#endif
for (;;) {
blob - 5a7564d43fbe801786356a9a6036bb9372e66c68
blob + be27709918c6e0c9c853297e6344ade339339ed4
--- libexec/got-send-pack/got-send-pack.c
+++ libexec/got-send-pack/got-send-pack.c
got_privsep_send_error(&ibuf, err);
return 1;
}
+
+ /* revoke fs access */
+ if (landlock_no_fs() == -1) {
+ err = got_error_from_errno("landlock_no_fs");
+ 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)