From daca5499b9fc954811db3099adbd49b04a642e53 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 2 Oct 2022 14:58:14 -0700 Subject: [PATCH] Add some tests for execve() --- libc/calls/execve.c | 8 ++-- libc/stdio/getrandom.c | 12 ++++-- test/libc/calls/execve_test.c | 60 +++++++++++++++++++++++++++++ test/libc/calls/mkntcmdline_test.c | 4 +- test/libc/runtime/getdosargv_test.c | 4 +- test/libc/stdio/getrandom_test.c | 7 +++- 6 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 test/libc/calls/execve_test.c diff --git a/libc/calls/execve.c b/libc/calls/execve.c index df661b858..4a186b218 100644 --- a/libc/calls/execve.c +++ b/libc/calls/execve.c @@ -35,11 +35,9 @@ /** * Replaces current process with program. * - * Warning: Our implementation of argument escaping on Windows hasn't - * been security reviewed for optimal handling of malicious arguments - * when interoperating with commonly used software. We make an effort - * to follow the same conventions as other FOSS software, e.g. PuTTY, - * however each WIN32 app is permitted to tokenize args how it wants. + * On Windows, `argv` and `envp` can't contain binary strings. They need + * to be valid UTF-8 in order to round-trip the WIN32 API, without being + * corrupted. * * @param program will not be PATH searched, see commandv() * @param argv[0] is the name of the program to run diff --git a/libc/stdio/getrandom.c b/libc/stdio/getrandom.c index 1d0400c48..7f1a8e6a6 100644 --- a/libc/stdio/getrandom.c +++ b/libc/stdio/getrandom.c @@ -56,9 +56,9 @@ static bool have_getrandom; * * The following flags may be specified: * - * - GRND_RANDOM: Halt the entire system while I tap an entropy pool + * - `GRND_RANDOM`: Halt the entire system while I tap an entropy pool * so small that it's hard to use statistics to test if it's random - * - GRND_NONBLOCK: Do not wait for i/o events or me to jiggle my + * - `GRND_NONBLOCK`: Do not wait for i/o events or me to jiggle my * mouse, and instead return immediately the moment data isn't * available, even if the result needs to be -1 w/ EAGAIN * @@ -68,6 +68,8 @@ static bool have_getrandom; * @note this function could block a nontrivial time on old computers * @note this function is indeed intended for cryptography * @note this function takes around 900 cycles + * @raise EINVAL if `f` is invalid + * @raise ENOSYS on bare metal * @asyncsignalsafe * @restartable * @vforksafe @@ -81,8 +83,10 @@ ssize_t getrandom(void *p, size_t n, unsigned f) { const char *via; sigset_t neu, old; if (n > 256) n = 256; - if ((f & ~(GRND_RANDOM | GRND_NONBLOCK))) return einval(); - if (IsWindows()) { + if ((f & ~(GRND_RANDOM | GRND_NONBLOCK))) { + rc = einval(); + via = "n/a"; + } else if (IsWindows()) { via = "RtlGenRandom"; if (RtlGenRandom(p, n)) { rc = n; diff --git a/test/libc/calls/execve_test.c b/test/libc/calls/execve_test.c new file mode 100644 index 000000000..9b563462a --- /dev/null +++ b/test/libc/calls/execve_test.c @@ -0,0 +1,60 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or 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 "libc/calls/calls.h" +#include "libc/fmt/conv.h" +#include "libc/fmt/itoa.h" +#include "libc/runtime/runtime.h" +#include "libc/str/str.h" +#include "libc/testlib/subprocess.h" +#include "libc/testlib/testlib.h" + +#define N 127 + +char *GenBuf(char buf[8], int x) { + int i; + bzero(buf, 8); + for (i = 0; i < 7; ++i) { + buf[i] = x & 127; // nt doesn't respect invalid unicode? + x >>= 1; + } + return buf; +} + +__attribute__((__constructor__)) static void init(void) { + char buf[8]; + if (__argc == 4 && !strcmp(__argv[1], "-")) { + ASSERT_STREQ(GenBuf(buf, atoi(__argv[2])), __argv[3]); + exit(0); + } +} + +TEST(execve, testArgPassing) { + int i; + char ibuf[12], buf[8]; + for (i = 0; i < N; ++i) { + FormatInt32(ibuf, i); + GenBuf(buf, i); + SPAWN(vfork); + execve(GetProgramExecutableName(), + (char *const[]){GetProgramExecutableName(), "-", ibuf, buf, 0}, + (char *const[]){0}); + notpossible; + EXITS(0); + } +} diff --git a/test/libc/calls/mkntcmdline_test.c b/test/libc/calls/mkntcmdline_test.c index 8e36a71b1..1102c66cc 100644 --- a/test/libc/calls/mkntcmdline_test.c +++ b/test/libc/calls/mkntcmdline_test.c @@ -100,6 +100,6 @@ TEST(mkntcmdline, fixAsBestAsWeCanForNow2) { TEST(mkntcmdline, testWut) { char *argv[] = {"redbean.com", "--strace", NULL}; - EXPECT_NE(-1, mkntcmdline(cmdline, "C:\\Users\\jart\\redbean.com", argv)); - EXPECT_STREQ(u"C:\\Users\\jart\\redbean.com --strace", cmdline); + EXPECT_NE(-1, mkntcmdline(cmdline, "C:\\Users\\jart\\𝑟𝑒𝑑𝑏𝑒𝑎𝑛.com", argv)); + EXPECT_STREQ(u"C:\\Users\\jart\\𝑟𝑒𝑑𝑏𝑒𝑎𝑛.com --strace", cmdline); } diff --git a/test/libc/runtime/getdosargv_test.c b/test/libc/runtime/getdosargv_test.c index 80010ac87..172b53af4 100644 --- a/test/libc/runtime/getdosargv_test.c +++ b/test/libc/runtime/getdosargv_test.c @@ -175,11 +175,11 @@ TEST(GetDosArgv, cmdToil) { size_t size = ARG_MAX / 2; char *buf = malloc(size * sizeof(char)); char **argv = malloc(max * sizeof(char *)); - EXPECT_EQ(3, GetDosArgv(u"cmd.exe /C \"echo hi >\"\"\"foo bar.txt\"\"\"\"", + EXPECT_EQ(3, GetDosArgv(u"cmd.exe /C \"echo hi >\"\"\"𝑓𝑜𝑜 bar.txt\"\"\"\"", buf, size, argv, max)); EXPECT_STREQ("cmd.exe", argv[0]); EXPECT_STREQ("/C", argv[1]); - EXPECT_STREQ("echo hi >\"foo bar.txt\"", argv[2]); + EXPECT_STREQ("echo hi >\"𝑓𝑜𝑜 bar.txt\"", argv[2]); EXPECT_EQ(NULL, argv[3]); free(argv); free(buf); diff --git a/test/libc/stdio/getrandom_test.c b/test/libc/stdio/getrandom_test.c index 231754861..d274997b8 100644 --- a/test/libc/stdio/getrandom_test.c +++ b/test/libc/stdio/getrandom_test.c @@ -16,13 +16,14 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/errno.h" #include "libc/intrin/bits.h" #include "libc/log/check.h" #include "libc/math.h" #include "libc/nexgen32e/x86feature.h" +#include "libc/runtime/runtime.h" #include "libc/stdio/lcg.internal.h" #include "libc/stdio/rand.h" -#include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/sysv/consts/grnd.h" #include "libc/testlib/ezbench.h" @@ -241,3 +242,7 @@ TEST(getrandom, sanityTest) { } } } + +TEST(getrandom, badflags_einval) { + ASSERT_SYS(EINVAL, -1, getrandom(0, 0, -1)); +}