From f0971b6909f12ef44290da389c30a003a5bfc620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Sun, 17 Dec 2023 12:31:37 -0500 Subject: [PATCH] Claim that /zip itself is user-modifiable This is in line with what I have learned about the TOCTOU stuff regarding ape executables. If there is ever a check for whether we are running in a secure set-id context, this can be disabled by that check. Adds basic sanity test for zipos stat as well. --- libc/runtime/zipos-stat-impl.c | 7 +++++++ test/libc/runtime/zipos_test.c | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/libc/runtime/zipos-stat-impl.c b/libc/runtime/zipos-stat-impl.c index 7c426fa02..79a2a330a 100644 --- a/libc/runtime/zipos-stat-impl.c +++ b/libc/runtime/zipos-stat-impl.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/struct/stat.h" #include "libc/intrin/atomic.h" @@ -34,6 +35,12 @@ int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) { if (cf == ZIPOS_SYNTHETIC_DIRECTORY) { st->st_mode = S_IFDIR | (0555 & ~atomic_load_explicit( &__umask, memory_order_acquire)); + /* report that /zip is user-modifiable to clarify to programs that check + transitive writability of a secure file like doas.conf. at this time, + doas itself does not actually do this check (it only checks the file) + but it probably ought to. */ + st->st_uid = getuid(); + st->st_mode |= S_IWUSR; } else { lf = GetZipCfileOffset(zipos->map + cf); st->st_mode = GetZipCfileMode(zipos->map + cf); diff --git a/test/libc/runtime/zipos_test.c b/test/libc/runtime/zipos_test.c index 83c036b31..ab5821d8b 100644 --- a/test/libc/runtime/zipos_test.c +++ b/test/libc/runtime/zipos_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" +#include "libc/sysv/consts/s.h" #include "libc/errno.h" #include "libc/limits.h" #include "libc/mem/gc.h" @@ -113,6 +114,18 @@ TEST(zipos, lseek) { EXPECT_SYS(0, 0, close(3)); } +TEST(zipos, stat) { + struct stat st; + umask(0777); + ASSERT_SYS(0, 0, stat("/zip", &st)); + EXPECT_EQ(getuid(), st.st_uid); + EXPECT_TRUE(S_ISDIR(st.st_mode)); + EXPECT_TRUE((st.st_mode & S_IWUSR) != 0); + ASSERT_SYS(0, 0, stat("/zip/libc/testlib/hyperion.txt", &st)); + EXPECT_EQ(0, st.st_uid); + EXPECT_EQ(0100644, st.st_mode); +} + TEST(zipos, closeAfterVfork) { ASSERT_SYS(0, 3, open("/zip/libc/testlib/hyperion.txt", O_RDONLY)); SPAWN(vfork);