Refactor pledge() to be more configurable

The earlier iterations did too much guesswork when it came to things
like stderr logging and syscall origin verification. This change will
make things more conformant to existing practices. The __pledge_mode
extension now can be configured in a better way.

There's also a new `-q` flag added to pledge.com, e.g.

    o//tool/build/pledge.com -qv. ls

Is a good way to disable warnings about `tty` access attempts.
This commit is contained in:
Justine Tunney 2022-08-11 11:27:25 -07:00
parent 6b8b58fdf5
commit 625aa365f1
36 changed files with 203 additions and 168 deletions

View file

@ -61,7 +61,7 @@ void SetUp(void) {
TEST(pledge, testSoftError) {
if (IsOpenbsd()) return;
SPAWN(fork);
__pledge_mode = kPledgeModeErrno;
__pledge_mode = PLEDGE_PENALTY_RETURN_EPERM;
ASSERT_SYS(0, 0, pledge("stdio", 0));
ASSERT_SYS(EPERM, -1, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
_Exit(7);
@ -70,7 +70,7 @@ TEST(pledge, testSoftError) {
TEST(pledge, testKillThreadMode) {
SPAWN(fork);
__pledge_mode = kPledgeModeKillThread;
__pledge_mode = PLEDGE_PENALTY_KILL_THREAD | PLEDGE_STDERR_LOGGING;
ASSERT_SYS(0, 0, pledge("stdio", 0));
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
TERMS(SIGABRT);
@ -78,7 +78,7 @@ TEST(pledge, testKillThreadMode) {
TEST(pledge, testKillProcessMode) {
SPAWN(fork);
__pledge_mode = kPledgeModeKillProcess;
__pledge_mode = PLEDGE_PENALTY_KILL_PROCESS | PLEDGE_STDERR_LOGGING;
ASSERT_SYS(0, 0, pledge("stdio", 0));
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
TERMS(SIGABRT);
@ -90,7 +90,7 @@ TEST(pledge, testLogMessage_inSoftyMode) {
char msg[256] = {0};
ASSERT_SYS(0, 0, pipe(fds));
SPAWN(fork);
__pledge_mode = kPledgeModeErrno;
__pledge_mode = PLEDGE_PENALTY_RETURN_EPERM | PLEDGE_STDERR_LOGGING;
ASSERT_SYS(0, 2, dup2(fds[1], 2));
ASSERT_SYS(0, 0, pledge("stdio", 0));
ASSERT_SYS(EPERM, -1, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
@ -108,7 +108,7 @@ TEST(pledge, testLogMessage_onKillProcess) {
char msg[256] = {0};
ASSERT_SYS(0, 0, pipe(fds));
SPAWN(fork);
__pledge_mode = kPledgeModeKillThread;
__pledge_mode = PLEDGE_PENALTY_KILL_THREAD | PLEDGE_STDERR_LOGGING;
ASSERT_SYS(0, 2, dup2(fds[1], 2));
ASSERT_SYS(0, 0, pledge("stdio", 0));
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@ -121,25 +121,18 @@ TEST(pledge, testLogMessage_onKillProcess) {
}
}
TEST(pledge, testNoLogOrAbrtsignoPossibleSadly_becausePledgedExec) {
int fds[2];
char msg[256] = {0};
ASSERT_SYS(0, 0, pipe(fds));
SPAWN(fork);
ASSERT_SYS(0, 2, dup2(fds[1], 2));
ASSERT_SYS(0, 0, pledge("stdio exec", "stdio exec"));
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
TERMS(IsOpenbsd() ? SIGABRT : SIGSYS);
close(fds[1]);
read(fds[0], msg, sizeof(msg));
close(fds[0]);
ASSERT_STREQ("", msg);
}
TEST(pledge, testDoublePledge_isFine) {
SPAWN(fork);
__pledge_mode = kPledgeModeKillThread;
__pledge_mode = PLEDGE_PENALTY_KILL_THREAD;
ASSERT_SYS(0, 0, pledge("stdio", 0));
ASSERT_SYS(0, 0, pledge("stdio", 0));
EXITS(0);
}
TEST(pledge, testEmptyPledge_doesntUseTrapping) {
SPAWN(fork);
__pledge_mode = PLEDGE_PENALTY_KILL_PROCESS;
ASSERT_SYS(0, 0, pledge("", 0));
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
TERMS(IsOpenbsd() ? SIGABRT : SIGSYS);
}

View file

@ -86,7 +86,7 @@ void SetUp(void) {
if (!__is_linux_2_6_23() && !IsOpenbsd()) exit(0);
ASSERT_SYS(0, 0, extract("/zip/life.elf", "life.elf", 0755));
ASSERT_SYS(0, 0, extract("/zip/sock.elf", "sock.elf", 0755));
__pledge_mode = kPledgeModeErrno;
__pledge_mode = PLEDGE_PENALTY_RETURN_EPERM;
}
TEST(pledge, default_allowsExit) {
@ -116,7 +116,7 @@ TEST(pledge, execpromises_notok) {
int ws, pid;
ASSERT_NE(-1, (pid = fork()));
if (!pid) {
__pledge_mode = kPledgeModeErrno;
__pledge_mode = PLEDGE_PENALTY_RETURN_EPERM;
ASSERT_SYS(0, 0, pledge("stdio rpath exec", "stdio"));
execl("sock.elf", "sock.elf", 0);
_Exit(127);
@ -158,7 +158,7 @@ TEST(pledge, stdio_forbidsOpeningPasswd1) {
TEST(pledge, stdio_forbidsOpeningPasswd2) {
int ws, pid;
__pledge_mode = kPledgeModeKillProcess;
__pledge_mode = PLEDGE_PENALTY_KILL_PROCESS;
ASSERT_NE(-1, (pid = fork()));
if (!pid) {
ASSERT_SYS(0, 0, pledge("stdio", 0));

View file

@ -375,7 +375,7 @@ TEST(unveil, usedTwice_forbidden_worksWithPledge) {
ASSERT_NE(-1, wait(&ws));
ASSERT_TRUE(*gotsome);
ASSERT_TRUE(WIFSIGNALED(ws));
ASSERT_EQ(SIGABRT, WTERMSIG(ws));
ASSERT_EQ(IsOpenbsd() ? SIGABRT : SIGSYS, WTERMSIG(ws));
EXPECT_SYS(0, 0, munmap(gotsome, FRAMESIZE));
}

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge("stdio")
assert(unix.pledge("stdio"))
assert(assert(argon2.hash_encoded("password", "somesalt", {
variant = argon2.variants.argon2_i,

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge('stdio')
assert(unix.pledge('stdio'))
local function test(s, b64)
assert(EncodeBase64(s) == b64)

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge("stdio")
assert(unix.pledge("stdio"))
assert(EncodeJson(nil) == "null")
assert(EncodeJson(true) == "true")

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge("stdio")
assert(unix.pledge("stdio"))
assert(EncodeLua(nil) == "nil")
assert(EncodeLua(true) == "true")

View file

@ -1,4 +1,4 @@
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail11.json

View file

@ -1,4 +1,4 @@
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: pass1.json

View file

@ -26,7 +26,7 @@
-- SOFTWARE.
--
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- these test cases are prefixed with n_
-- ljson should reject all of them as invalid

View file

@ -26,7 +26,7 @@
-- SOFTWARE.
--
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- these test cases are prefixed with n_
-- ljson should reject all of them as invalid

View file

@ -26,7 +26,7 @@
-- SOFTWARE.
--
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- these test cases are prefixed with n_
-- ljson should reject all of them as invalid

View file

@ -26,7 +26,7 @@
-- SOFTWARE.
--
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- these test cases are prefixed with n_
-- ljson should reject all of them as invalid

View file

@ -26,7 +26,7 @@
-- SOFTWARE.
--
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- these test cases are prefixed with i_
-- ljson is free to accept or reject,

View file

@ -26,7 +26,7 @@
-- SOFTWARE.
--
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- these test cases are prefixed with y_
-- ljson should accept all of them as valid

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge("stdio")
assert(unix.pledge("stdio"))
x = Rdtsc()
y = Rdtsc()

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge("stdio")
assert(unix.pledge("stdio"))
assert(EncodeLua(assert(DecodeJson[[ 0 ]])) == '0' )
assert(EncodeLua(assert(DecodeJson[[ [1] ]])) == '{1}')

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge("stdio")
assert(unix.pledge("stdio"))
assert(string.match("127.123.231.1", "%d+.%d+.%d+.%d+"))
assert(re.search([[^\d{1,3}(\.\d{1,3}){3}$]], "127.123.231.1"))

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge("stdio")
assert(unix.pledge("stdio"))
-- test redbean lua language extensions
assert(0b100 == 4)

View file

@ -59,7 +59,7 @@ function UnixTest()
-- fork
-- basic subprocess creation
if assert(unix.fork()) == 0 then
unix.pledge("")
assert(unix.pledge(""))
unix.exit(42)
end
pid, ws = assert(unix.wait())
@ -82,7 +82,7 @@ function UnixTest()
unix.close(reader)
pid, ws = assert(unix.wait())
assert(unix.WIFSIGNALED(ws))
assert(unix.WTERMSIG(ws) == unix.SIGABRT)
assert(unix.WTERMSIG(ws) == unix.SIGSYS)
elseif GetHostOs() == "OPENBSD" then
if assert(unix.fork()) == 0 then
assert(unix.pledge("stdio"))
@ -160,7 +160,7 @@ function main()
assert(unix.makedirs(tmpdir))
unix.unveil(tmpdir, "rwc")
unix.unveil(nil, nil)
unix.pledge("stdio rpath wpath cpath proc")
assert(unix.pledge("stdio rpath wpath cpath proc"))
ok, err = pcall(UnixTest)
if ok then
assert(unix.rmrf(tmpdir))

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge('stdio')
assert(unix.pledge('stdio'))
assert(Md5(nil) == nil)

View file

@ -13,7 +13,7 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
unix.pledge("stdio")
assert(unix.pledge("stdio"))
assert("/usr/lib" == path.dirname("/usr/lib/foo.bar"))
assert("/usr" == path.dirname("/usr/lib"))

View file

@ -19,7 +19,7 @@
-- 5869). As with RFC 4634, code to perform SHA-based Hashed Message
-- Authentication Codes (HMACs) is also included.
unix.pledge('stdio')
assert(unix.pledge('stdio'))
-- SHA-1
assert(Sha1(nil) == nil)

View file

@ -40,7 +40,7 @@ local function main()
assert(unix.makedirs(tmpdir))
unix.unveil(tmpdir, "rwc")
unix.unveil(nil, nil)
unix.pledge("stdio rpath wpath cpath")
assert(unix.pledge("stdio rpath wpath cpath"))
ok, err = pcall(SlurpTest)
if ok then
assert(unix.rmrf(tmpdir))