Snap for 8730993 from 70e1cac63d9545c24b6667f99813e868f6c75c80 to mainline-tzdata3-release

Change-Id: Id09474bbc20323009fb714a1f89c6a2313887bdc
diff --git a/.github/mistaken-pull-closer.yml b/.github/mistaken-pull-closer.yml
new file mode 100644
index 0000000..eb4cb89
--- /dev/null
+++ b/.github/mistaken-pull-closer.yml
@@ -0,0 +1,17 @@
+# The JSONPath filter expression used to identify which PRs to close.
+# The data filtered is the pull request data along with other metadata passed in
+# by probot.
+# See https://goessner.net/articles/JsonPath/
+# `true` will close all PRs.
+filters:
+  - true
+
+# The message to post to the closed PR.
+commentBody: |
+  Thanks for your contribution!  Unfortunately, we don't use GitHub pull
+  requests to manage code contributions to this repository.  Instead, please
+  see [README.md](../blob/master/README.md) which provides full instructions
+  on how to get involved.
+
+# Whether to add a label to the closed PR.
+addLabel: false
diff --git a/.github/workflows/build-test-ci.yml b/.github/workflows/build-test-ci.yml
index 74a95aa..bed8a43 100644
--- a/.github/workflows/build-test-ci.yml
+++ b/.github/workflows/build-test-ci.yml
@@ -8,14 +8,6 @@
     branches: [master]
     tags: [linux-v*]
 
-  schedule:
-    # The GH mirroring from Google GoB does not trigger push actions.
-    # Fire it every other day to provide some coverage.  This will run ~8 AM PT.
-    - cron: '39 3 */2 * *'
-
-  # Allow for manual triggers from the web.
-  workflow_dispatch:
-
 jobs:
   build-test:
     strategy:
diff --git a/.github/workflows/close-pull-request.yml b/.github/workflows/close-pull-request.yml
deleted file mode 100644
index da11c4a..0000000
--- a/.github/workflows/close-pull-request.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# GitHub actions workflow.
-# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions
-
-# https://github.com/superbrothers/close-pull-request
-name: Close Pull Request
-
-on:
-  pull_request_target:
-    types: [opened]
-
-jobs:
-  run:
-    runs-on: ubuntu-latest
-    steps:
-    - uses: superbrothers/close-pull-request@v3
-      with:
-        comment: >
-          Thanks for your contribution!
-          Unfortunately, we don't use GitHub pull requests to manage code
-          contributions to this repository.
-          Instead, please see [README.md](../blob/HEAD/README.md) which
-          provides full instructions on how to get involved.
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
deleted file mode 100644
index 42839cc..0000000
--- a/.github/workflows/coverity.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-# GitHub actions workflow.
-# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions
-
-# https://scan.coverity.com/projects/google-minijail
-name: Coverity Scan
-
-on:
-  push:
-    branches: [master]
-
-  schedule:
-    # The GH mirroring from Google GoB does not trigger push actions.
-    # Fire it once a week to provide some coverage.
-    - cron: '39 2 * * WED'
-
-  # Allow for manual triggers from the web.
-  workflow_dispatch:
-
-jobs:
-  coverity:
-    strategy:
-      matrix:
-        os: [ubuntu-latest]
-        cc: [clang]
-    runs-on: ${{ matrix.os }}
-    env:
-      CC: ${{ matrix.cc }}
-    steps:
-    - uses: actions/checkout@v2
-    - name: Install system packages
-      run: sudo apt-get install -y libcap-dev
-    - uses: vapier/coverity-scan-action@v0
-      with:
-        project: google%2Fminijail
-        email: [email protected]
-        token: ${{ secrets.COVERITY_SCAN_TOKEN }}
diff --git a/.gitignore b/.gitignore
index a0038c4..9ce33c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,9 +24,13 @@
 
 # Executables when compiling in-tree.
 /dump_constants
+/libminijail_unittest
 /minijail0
+/minijail0_cli_unittest
+/syscall_filter_unittest
+/system_unittest
+/util_unittest
 /parse_seccomp_policy
-/*_unittest
 
 # common.mk TEST().
 *.test
diff --git a/Android.bp b/Android.bp
index 0a80f77..e98cdad 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,7 +62,6 @@
 
 unittestSrcFiles = [
     "testrunner.cc",
-    "test_util.cc",
 ]
 
 minijailCommonLibraries = ["libcap"]
@@ -92,6 +91,7 @@
     vendor_available: true,
     product_available: true,
     recovery_available: true,
+    header_libs: ["libc_headers"], // TODO(b/153662223): Clean this up.
     srcs: ["gen_syscalls.c"],
     cflags: [
         "-dD",
@@ -102,7 +102,6 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
-        "com.android.compos",
         "com.android.media.swcodec",
         "com.android.virt",
     ],
@@ -121,7 +120,6 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
-        "com.android.compos",
         "com.android.media.swcodec",
         "com.android.virt",
     ],
@@ -132,6 +130,7 @@
     vendor_available: true,
     product_available: true,
     recovery_available: true,
+    header_libs: ["libc_headers"], // TODO(b/153662223): Clean this up.
     srcs: ["gen_constants.c"],
     cflags: [
         "-dD",
@@ -142,7 +141,6 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
-        "com.android.compos",
         "com.android.media.swcodec",
         "com.android.virt",
     ],
@@ -161,7 +159,6 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
-        "com.android.compos",
         "com.android.media.swcodec",
         "com.android.virt",
     ],
@@ -192,7 +189,6 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
-        "com.android.compos",
         "com.android.media.swcodec",
         "com.android.virt",
     ],
@@ -205,6 +201,7 @@
     product_available: true,
     recovery_available: true,
     host_supported: true,
+    header_libs: ["libc_headers"], // TODO(b/153662223): Clean this up.
     cflags: [
         "-S",
         "-O0",
@@ -227,6 +224,7 @@
     product_available: true,
     recovery_available: true,
     host_supported: true,
+    header_libs: ["libc_headers"], // TODO(b/153662223): Clean this up.
     cflags: [
         "-S",
         "-O0",
@@ -279,7 +277,6 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
-        "com.android.compos",
         "com.android.media.swcodec",
         "com.android.virt",
     ],
@@ -444,7 +441,6 @@
         "-DPRELOADPATH=\"/invalid\"",
     ],
     srcs: libminijailSrcFiles + [
-        "config_parser.c",
         "elfparse.c",
         "minijail0_cli.c",
         "minijail0_cli_unittest.cc",
@@ -458,41 +454,6 @@
             test_suites: ["device-tests"],
         },
     },
-    data: ["test/*"],
-}
-
-
-// Configuration file parser functionality unit tests using gtest.
-//
-// For a device, run with:
-// adb shell /data/nativetest/config_parser_unittest_gtest/config_parser_unittest_gtest
-//
-// For host, run with:
-// out/host/linux-x86/nativetest(64)/config_parser_unittest_gtest/config_parser_unittest_gtest
-// =========================================================
-cc_test {
-    name: "config_parser_unittest_gtest",
-    defaults: ["libminijail_flags"],
-    host_supported: true,
-
-    srcs: [
-        "config_parser.c",
-        "util.c",
-        "config_parser_unittest.cc",
-    ] + unittestSrcFiles,
-
-    static_libs: ["libminijail_generated"],
-    shared_libs: minijailCommonLibraries,
-
-    target: {
-        android: {
-            test_suites: ["device-tests"],
-        },
-    },
-    test_options: {
-        unit_test: true,
-    },
-    data: ["test/*"],
 }
 
 // libminijail_test executable for brillo_Minijail test.
@@ -541,7 +502,6 @@
         "-DPRELOADPATH=\"/invalidminijailpreload.so\"",
     ],
     srcs: [
-        "config_parser.c",
         "elfparse.c",
         "minijail0.c",
         "minijail0_cli.c",
@@ -578,7 +538,6 @@
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.compos",
         "com.android.virt",
     ],
 }
@@ -598,7 +557,6 @@
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.compos",
         "com.android.virt",
     ],
 }
diff --git a/DIR_METADATA b/DIR_METADATA
deleted file mode 100644
index 4a465c7..0000000
--- a/DIR_METADATA
+++ /dev/null
@@ -1,17 +0,0 @@
-# Metadata information for this directory.
-#
-# For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md
-#
-# For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-
-buganizer {
-  component_id: 1099158  # ChromeOS > Security > Minijail
-}
-
-monorail {
-  component: "OS>Systems>Minijail"
-}
-
-team_email: "[email protected]"
diff --git a/Makefile b/Makefile
index f44f867..b7022b5 100644
--- a/Makefile
+++ b/Makefile
@@ -10,9 +10,6 @@
 PRELOADPATH = "$(LIBDIR)/$(PRELOADNAME)"
 CPPFLAGS += -DPRELOADPATH='$(PRELOADPATH)'
 
-# We don't build static libs by default.
-BUILD_STATIC_LIBS ?= no
-
 # Defines the pivot root path used by the minimalistic-mountns profile.
 DEFAULT_PIVOT_ROOT ?= /var/empty
 CPPFLAGS += -DDEFAULT_PIVOT_ROOT='"$(DEFAULT_PIVOT_ROOT)"'
@@ -21,23 +18,10 @@
 CPPFLAGS += -DUSE_SECCOMP_SOFTFAIL
 endif
 
-BLOCK_NOEXEC_CONF ?= no
-ifeq ($(BLOCK_NOEXEC_CONF),yes)
-CPPFLAGS += -DBLOCK_NOEXEC_CONF
-endif
-
-ENFORCE_ROOTFS_CONF ?= no
-ifeq ($(ENFORCE_ROOTFS_CONF),yes)
-CPPFLAGS += -DENFORCE_ROOTFS_CONF
-endif
-
 # Allow people to use -L and related flags.
 ALLOW_DEBUG_LOGGING ?= yes
 ifeq ($(ALLOW_DEBUG_LOGGING),yes)
 CPPFLAGS += -DALLOW_DEBUG_LOGGING
-ifeq ($(SECCOMP_DEFAULT_RET_LOG),yes)
-CPPFLAGS += -DSECCOMP_DEFAULT_RET_LOG
-endif
 endif
 
 ifeq ($(USE_ASAN),yes)
@@ -62,27 +46,20 @@
 CFLAGS += $(MJ_COMMON_FLAGS)
 CXXFLAGS += $(MJ_COMMON_FLAGS)
 
-# Dependencies that all gtest based unittests should have.
-UNITTEST_LIBS := -lcap
-UNITTEST_DEPS := testrunner.o test_util.o
-
 USE_SYSTEM_GTEST ?= no
 ifeq ($(USE_SYSTEM_GTEST),no)
 GTEST_CXXFLAGS := -std=gnu++14
 GTEST_LIBS := gtest.a
-UNITTEST_DEPS += $(GTEST_LIBS)
 else
 GTEST_CXXFLAGS := $(shell gtest-config --cxxflags 2>/dev/null || \
   echo "-pthread")
 GTEST_LIBS := $(shell gtest-config --libs 2>/dev/null || \
   echo "-lgtest -pthread -lpthread")
 endif
-UNITTEST_LIBS += $(GTEST_LIBS)
 
 CORE_OBJECT_FILES := libminijail.o syscall_filter.o signal_handler.o \
 		bpf.o util.o system.o syscall_wrapper.o \
-		config_parser.o libconstants.gen.o libsyscalls.gen.o
-UNITTEST_DEPS += $(CORE_OBJECT_FILES)
+		libconstants.gen.o libsyscalls.gen.o
 
 all: CC_BINARY(minijail0) CC_LIBRARY(libminijail.so) \
 	CC_LIBRARY(libminijailpreload.so)
@@ -95,7 +72,7 @@
 	TEST(CXX_BINARY(syscall_filter_unittest)) \
 	TEST(CXX_BINARY(system_unittest)) \
 	TEST(CXX_BINARY(util_unittest)) \
-	TEST(CXX_BINARY(config_parser_unittest))
+
 
 CC_BINARY(minijail0): LDLIBS += -lcap -ldl
 CC_BINARY(minijail0): $(CORE_OBJECT_FILES) \
@@ -111,14 +88,14 @@
 CC_STATIC_LIBRARY(libminijail.pie.a): $(CORE_OBJECT_FILES)
 clean: CLEAN(libminijail.*.a)
 
-ifeq ($(BUILD_STATIC_LIBS),yes)
-all: CC_STATIC_LIBRARY(libminijail.pic.a) CC_STATIC_LIBRARY(libminijail.pie.a)
-endif
-
 CXX_BINARY(libminijail_unittest): CXXFLAGS += -Wno-write-strings \
 						$(GTEST_CXXFLAGS)
-CXX_BINARY(libminijail_unittest): LDLIBS += $(UNITTEST_LIBS)
-CXX_BINARY(libminijail_unittest): $(UNITTEST_DEPS) libminijail_unittest.o
+CXX_BINARY(libminijail_unittest): LDLIBS += -lcap $(GTEST_LIBS)
+ifeq ($(USE_SYSTEM_GTEST),no)
+CXX_BINARY(libminijail_unittest): $(GTEST_LIBS)
+endif
+CXX_BINARY(libminijail_unittest): libminijail_unittest.o $(CORE_OBJECT_FILES) \
+		testrunner.o
 clean: CLEAN(libminijail_unittest)
 
 TEST(CXX_BINARY(libminijail_unittest)): CC_LIBRARY(libminijailpreload.so)
@@ -130,33 +107,43 @@
 
 
 CXX_BINARY(minijail0_cli_unittest): CXXFLAGS += $(GTEST_CXXFLAGS)
-CXX_BINARY(minijail0_cli_unittest): LDLIBS += $(UNITTEST_LIBS)
-CXX_BINARY(minijail0_cli_unittest): $(UNITTEST_DEPS) minijail0_cli_unittest.o \
-		minijail0_cli.o elfparse.o
+CXX_BINARY(minijail0_cli_unittest): LDLIBS += -lcap $(GTEST_LIBS)
+ifeq ($(USE_SYSTEM_GTEST),no)
+CXX_BINARY(minijail0_cli_unittest): $(GTEST_LIBS)
+endif
+CXX_BINARY(minijail0_cli_unittest): minijail0_cli_unittest.o \
+		$(CORE_OBJECT_FILES) minijail0_cli.o elfparse.o testrunner.o
 clean: CLEAN(minijail0_cli_unittest)
 
 
-CXX_BINARY(config_parser_unittest): CXXFLAGS += $(GTEST_CXXFLAGS)
-CXX_BINARY(config_parser_unittest): LDLIBS += $(UNITTEST_LIBS)
-CXX_BINARY(config_parser_unittest): $(UNITTEST_DEPS) config_parser_unittest.o
-clean: CLEAN(config_parser_unittest)
-
 CXX_BINARY(syscall_filter_unittest): CXXFLAGS += -Wno-write-strings \
 						$(GTEST_CXXFLAGS)
-CXX_BINARY(syscall_filter_unittest): LDLIBS += $(UNITTEST_LIBS)
-CXX_BINARY(syscall_filter_unittest): $(UNITTEST_DEPS) syscall_filter_unittest.o
+CXX_BINARY(syscall_filter_unittest): LDLIBS += -lcap $(GTEST_LIBS)
+ifeq ($(USE_SYSTEM_GTEST),no)
+CXX_BINARY(syscall_filter_unittest): $(GTEST_LIBS)
+endif
+CXX_BINARY(syscall_filter_unittest): syscall_filter_unittest.o \
+		$(CORE_OBJECT_FILES) testrunner.o
 clean: CLEAN(syscall_filter_unittest)
 
 
 CXX_BINARY(system_unittest): CXXFLAGS += $(GTEST_CXXFLAGS)
-CXX_BINARY(system_unittest): LDLIBS += $(UNITTEST_LIBS)
-CXX_BINARY(system_unittest): $(UNITTEST_DEPS) system_unittest.o
+CXX_BINARY(system_unittest): LDLIBS += -lcap $(GTEST_LIBS)
+ifeq ($(USE_SYSTEM_GTEST),no)
+CXX_BINARY(system_unittest): $(GTEST_LIBS)
+endif
+CXX_BINARY(system_unittest): system_unittest.o \
+		$(CORE_OBJECT_FILES) testrunner.o
 clean: CLEAN(system_unittest)
 
 
 CXX_BINARY(util_unittest): CXXFLAGS += $(GTEST_CXXFLAGS)
-CXX_BINARY(util_unittest): LDLIBS += $(UNITTEST_LIBS)
-CXX_BINARY(util_unittest): $(UNITTEST_DEPS) util_unittest.o
+CXX_BINARY(util_unittest): LDLIBS += -lcap $(GTEST_LIBS)
+ifeq ($(USE_SYSTEM_GTEST),no)
+CXX_BINARY(util_unittest): $(GTEST_LIBS)
+endif
+CXX_BINARY(util_unittest): util_unittest.o \
+		$(CORE_OBJECT_FILES) testrunner.o
 clean: CLEAN(util_unittest)
 
 
@@ -183,9 +170,10 @@
 
 # Only regenerate libsyscalls.gen.c if the Makefile or header changes.
 # NOTE! This will not detect if the file is not appropriate for the target.
-libsyscalls.gen.c: $(SRC)/libsyscalls.h $(SRC)/Makefile
-	@/bin/echo -e "GEN		$(subst $(SRC)/,,$<) ->  $@"
+libsyscalls.gen.c: $(SRC)/Makefile $(SRC)/libsyscalls.h
+	@printf "Generating target-arch specific $@...\n"
 	$(QUIET)CC="$(CC)" $(SRC)/gen_syscalls.sh "$@"
+	@printf "$@ done.\n"
 clean: CLEAN(libsyscalls.gen.c)
 
 $(eval $(call add_object_rules,libsyscalls.gen.o,CC,c,CFLAGS))
@@ -196,9 +184,10 @@
 
 # Only regenerate libconstants.gen.c if the Makefile or header changes.
 # NOTE! This will not detect if the file is not appropriate for the target.
-libconstants.gen.c: $(SRC)/libconstants.h $(SRC)/Makefile
-	@/bin/echo -e "GEN		$(subst $(SRC)/,,$<) ->  $@"
+libconstants.gen.c: $(SRC)/Makefile $(SRC)/libconstants.h
+	@printf "Generating target-arch specific $@...\n"
 	$(QUIET)CC="$(CC)" $(SRC)/gen_constants.sh "$@"
+	@printf "$@ done.\n"
 clean: CLEAN(libconstants.gen.c)
 
 $(eval $(call add_object_rules,libconstants.gen.o,CC,c,CFLAGS))
@@ -210,7 +199,7 @@
 ifeq ($(USE_SYSTEM_GTEST),no)
 # Points to the root of Google Test, relative to where this file is.
 # Remember to tweak this if you move this file.
-GTEST_DIR = googletest-release-1.11.0/googletest
+GTEST_DIR = googletest-release-1.10.0/googletest
 
 # Flags passed to the preprocessor.
 # Set Google Test's header directory as a system directory, such that
@@ -229,7 +218,7 @@
 clean: clean_gtest
 
 clean_gtest:
-	$(QUIET)rm -f gtest.a gtest_main.a *.o
+	rm -f gtest.a gtest_main.a *.o
 
 # Builds gtest.a and gtest_main.a.
 
diff --git a/OWNERS b/OWNERS
index 2823db3..ebadeca 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,5 @@
 set noparent
-include OWNERS_GENERAL
-# Emeritus.
[email protected]
 [email protected]
 [email protected]
[email protected]
diff --git a/OWNERS_GENERAL b/OWNERS_GENERAL
deleted file mode 100644
index e5179ef..0000000
--- a/OWNERS_GENERAL
+++ /dev/null
@@ -1,3 +0,0 @@
[email protected]
[email protected]
[email protected]
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
index a7ce524..d76d432 100644
--- a/PRESUBMIT.cfg
+++ b/PRESUBMIT.cfg
@@ -6,6 +6,3 @@
 # This is an AOSP project, but we still use a BSD license.
 cros_license_check: true
 aosp_license_check: false
-
-[Hook Overrides Options]
-cros_license_check: --exclude_regex=^test/
diff --git a/README.md b/README.md
index 71a34c6..3b528e5 100644
--- a/README.md
+++ b/README.md
@@ -114,51 +114,3 @@
 https://crrev.com/c/4585/ added the original implementation.
 
 Source: Conversations with original authors, ellyjones@ and wad@.
-
-## How to manually upgrade Minijail on Chrome OS
-
-Minijail is manually upgraded on Chrome OS so that there is a way to test
-changes in the Chrome OS commit queue. Committed changes have already passed
-Android's presubmit checks, but the ebuild upgrade CL goes through the Chrome
-OS commit queue and must pass the tests before any additional changes are
-available for use on Chrome OS. To upgrade minijail on Chrome OS, complete the
-following steps.
-
-```bash
-# Sync Minijail repo
-cd ~/chromiumos/src/aosp/external/minijail
-git checkout m/main
-repo sync .
-
-# Set up local branch.
-cd ~/trunk/src/third_party/chromiumos-overlay/
-repo start minijail .  # replace minijail with the local branch name you want.
-
-# Run upgrade script.
-~/trunk/chromite/scripts/cros_uprev --force --overlay-type public \
-  --packages chromeos-base/minijail:dev-rust/minijail-sys:dev-rust/minijail
-```
-
-At this point the Minijail-related packages should be upgraded, so you may want
-to add the changes to a commit and do some local testing before uploading a
-change list. Here are the recommended local tests to try (make sure you are
-**not** working on the minijail packages first i.e. `cros_workon list-all`):
-
-```bash
-# Check build.
-./build_packages --board=${BOARD}
-
-# Check unit tests.
-FEATURES=test emerge-${BOARD} chromeos-base/minijail dev-rust/minijail-sys \
-  dev-rust/minijail
-
-# Check integration tests.
-cros deploy <DUT> chromeos-base/minijail
-tast run <DUT> security.Minijail.* security.MinijailSeccomp
-```
-
-Finally, when uploading the CL make sure to include the list of changes
-since the last uprev. The command to generate the list is as follows:
-```bash
-git log --oneline --no-merges <previous hash in ebuild file>..HEAD
-```
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 539379e..bdded19 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -12,19 +12,5 @@
     {
       "name": "syscall_filter_unittest_gtest"
     }
-  ],
-  "hwasan-postsubmit": [
-    {
-      "name": "libminijail_unittest_gtest"
-    },
-    {
-      "name": "mj_system_unittest_gtest"
-    },
-    {
-      "name": "mj_util_unittest_gtest"
-    },
-    {
-      "name": "syscall_filter_unittest_gtest"
-    }
   ]
 }
diff --git a/arch.h b/arch.h
index 253b45f..e027831 100644
--- a/arch.h
+++ b/arch.h
@@ -62,17 +62,6 @@
 #elif defined(__powerpc__)
 #  define MINIJAIL_ARCH_NR AUDIT_ARCH_PPC
 #  define MINIJAIL_ARCH_NAME "ppc"
-#elif defined(__riscv)
-#  if defined(__riscv_xlen)
-#    if (__riscv_xlen == 64)
-#      define MINIJAIL_ARCH_NR AUDIT_ARCH_RISCV64
-#      define MINIJAIL_ARCH_NAME "riscv64"
-#    else
-#      error "Only 64bit riscv is supported"
-#    endif
-#  else
-#    error "AUDIT_ARCH value unavailable"
-#  endif
 #elif defined(__s390x__)
 #  define MINIJAIL_ARCH_NR AUDIT_ARCH_S390X
 #  define MINIJAIL_ARCH_NAME "s390x"
diff --git a/config_parser.c b/config_parser.c
deleted file mode 100644
index 4972cf5..0000000
--- a/config_parser.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config_parser.h"
-
-#include "util.h"
-
-#define LIST_DEFAULT_SIZE (100)
-
-struct config_entry_list *new_config_entry_list(void)
-{
-	/*
-	 * There are <100 CLI options, configuration file will likely have
-	 * a similar number of config entries.
-	 */
-	struct config_entry *entries =
-	    calloc(LIST_DEFAULT_SIZE, sizeof(struct config_entry));
-	if (!entries)
-		return NULL;
-
-	struct config_entry_list *list =
-	    calloc(1, sizeof(struct config_entry_list));
-	if (!list) {
-		free(entries);
-		return NULL;
-	}
-	list->entries = entries;
-	list->num_allocated_ = LIST_DEFAULT_SIZE;
-	list->num_entries = 0;
-	return list;
-}
-
-void clear_config_entry(struct config_entry *entry)
-{
-	free((char *)entry->key);
-	free((char *)entry->value);
-}
-
-void free_config_entry_list(struct config_entry_list *list)
-{
-	if (!list)
-		return;
-	for (size_t i = 0; i < list->num_entries; i++) {
-		clear_config_entry(&list->entries[i]);
-	}
-	free(list->entries);
-	free(list);
-}
-
-bool parse_config_line(const char *config_line, struct config_entry *entry)
-{
-	/* Parsing will modify |config_line| in place, so make a copy. */
-	attribute_cleanup_str char *line = strdup(config_line);
-	if (!line)
-		return false;
-	char *value = line;
-
-	/* After tokenize call, |value| will point to a substring after '='.
-	 * If there is no '=' in the string, |key| will contain the entire
-	 * string while |value| will be NULL.
-	 */
-	char *key = tokenize(&value, "=");
-	if (key)
-		key = strip(key);
-	if (value)
-		value = strip(value);
-	if (!key || key[0] == '\0' || (value && value[0] == '\0')) {
-		warn("unable to parse %s", config_line);
-		return false;
-	}
-	entry->key = strdup(key);
-	entry->value = value ? strdup(value) : NULL;
-	if (!entry->key || (value && !entry->value)) {
-		clear_config_entry(entry);
-		return false;
-	}
-	return true;
-}
-
-static bool match_special_directive(const char *line)
-{
-	return (strcmp(line, "% minijail-config-file v0\n") == 0);
-}
-
-bool parse_config_file(FILE *config_file, struct config_entry_list *list)
-{
-	attribute_cleanup_str char *line = NULL;
-	size_t len = 0;
-
-	/* The first line must match the special directive */
-	if (getline(&line, &len, config_file) == -1 ||
-	    !match_special_directive(line))
-		return false;
-	while (getmultiline(&line, &len, config_file) != -1) {
-		char *stripped_line = strip(line);
-		/*
-		 * Skip blank lines and all comments. Comment lines start with
-		 * '#'.
-		 */
-		if (stripped_line[0] == '\0' || stripped_line[0] == '#')
-			continue;
-
-		/*
-		 * Check if the list is full, and reallocate with doubled
-		 * capacity if so.
-		 */
-		if (list->num_entries >= list->num_allocated_) {
-			list->num_allocated_ = list->num_allocated_ * 2;
-			list->entries = realloc(
-			    list->entries,
-			    list->num_allocated_ * sizeof(struct config_entry));
-			if (list->entries == NULL) {
-				return false;
-			}
-		}
-
-		struct config_entry *entry = &list->entries[list->num_entries];
-		if (!parse_config_line(stripped_line, entry)) {
-			return false;
-		}
-		++list->num_entries;
-	}
-	/*
-	 * getmultiline() behaves similarly with getline(3). It returns -1
-	 * when read into EOF or the following errors.
-	 */
-	if (errno == EINVAL || errno == ENOMEM) {
-		return false;
-	}
-
-	/* Shrink the list to save memory. */
-	if (list->num_entries < list->num_allocated_) {
-		list->entries =
-		    realloc(list->entries,
-			    list->num_entries * sizeof(struct config_entry));
-		list->num_allocated_ = list->num_entries;
-	}
-
-	return true;
-}
diff --git a/config_parser.h b/config_parser.h
deleted file mode 100644
index 36c96db..0000000
--- a/config_parser.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef CONFIG_PARSER_H
-#define CONFIG_PARSER_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct config_entry {
-	const char *key;
-	const char *value;
-};
-
-struct config_entry_list {
-	struct config_entry *entries;
-	size_t num_entries;
-	size_t num_allocated_;
-};
-
-/* Allocate a new |config_entry_list| struct. */
-struct config_entry_list *new_config_entry_list(void);
-
-/* Free allocated pointers in |config_entry|. */
-void clear_config_entry(struct config_entry *entry);
-
-/* Free a |config_entry_list| struct. */
-void free_config_entry_list(struct config_entry_list *list);
-
-/*
- * Parse one config line into a entry.
- *
- * Returns true for success, otherwise false for parsing failures.
- */
-bool parse_config_line(const char *config_line, struct config_entry *entry);
-
-/*
- * Parse a minijail config file into a |config_entry_list|.
- *
- * Returns true for success, otherwise false for parsing failures.
- */
-bool parse_config_file(FILE *config_file, struct config_entry_list *list);
-
-#ifdef __cplusplus
-}; /* extern "C" */
-#endif
-
-#endif /* CONFIG_PARSER_H */
diff --git a/config_parser_unittest.cc b/config_parser_unittest.cc
deleted file mode 100644
index a9c6571..0000000
--- a/config_parser_unittest.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-/* Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Test config_parser.c using gtest.
- */
-
-#include <gtest/gtest.h>
-#include <string>
-
-#include "config_parser.h"
-#include "test_util.h"
-#include "util.h"
-
-namespace {
-
-class ConfigFileTest : public ::testing::Test {
-protected:
-  virtual void SetUp() {
-    list_ = new_config_entry_list();
-    ASSERT_NE(list_, nullptr);
-  }
-  virtual void TearDown() { free_config_entry_list(list_); }
-  struct config_entry_list *list_;
-};
-
-} // namespace
-
-TEST(ParsingConfigTest, valid_config_line) {
-  ScopedConfigEntry entry(
-      (config_entry *)calloc(1, sizeof(struct config_entry)));
-  const std::vector<std::string> valid_conf_lines = {
-      "mount=none",
-      "valueless_key"
-      "binding = none",
-      "  xyz = abc  ",
-  };
-
-  for (const auto& conf_line : valid_conf_lines) {
-    ASSERT_TRUE(parse_config_line(conf_line.c_str(), entry.get()));
-    clear_config_entry(entry.get());
-  }
-}
-
-TEST(ParsingConfigTest, invalid_config_line) {
-  ScopedConfigEntry entry(
-      (config_entry *)calloc(1, sizeof(struct config_entry)));
-  const std::vector<std::string> invalid_conf_lines = {
-      "= none",
-      "",
-      "empty_arg=",
-      "empty_arg=   ",
-  };
-
-  for (const auto& conf_line : invalid_conf_lines) {
-    ASSERT_FALSE(parse_config_line(conf_line.c_str(), entry.get()));
-  }
-}
-
-TEST_F(ConfigFileTest, malformed_config_line) {
-  std::string config = "% minijail-config-file v0\n"
-                       "=malformed";
-  ScopedFILE config_file(write_to_pipe(config));
-  ASSERT_NE(config_file.get(), nullptr);
-
-  bool res = parse_config_file(config_file.get(), list_);
-
-  // Policy is malformed, but process should not crash.
-  ASSERT_FALSE(res);
-  ASSERT_EQ(list_->num_entries, 0);
-}
-
-TEST_F(ConfigFileTest, bad_directive) {
-  std::string config = "% bad-directive\n"
-                       "# comments";
-  ScopedFILE config_file(write_to_pipe(config));
-  ASSERT_NE(config_file.get(), nullptr);
-
-  bool res = parse_config_file(config_file.get(), list_);
-
-  // Policy is malformed, but process should not crash.
-  ASSERT_FALSE(res);
-  ASSERT_EQ(list_->num_entries, 0);
-}
-
-TEST_F(ConfigFileTest, wellformed_single_line) {
-  std::string config = "% minijail-config-file v0\n"
-                       "# Comments \n"
-                       "\n"
-                       "uts\n"
-                       "mount= xyz\n"
-                       "binding = none,/tmp";
-  ScopedFILE config_file(write_to_pipe(config));
-  ASSERT_NE(config_file.get(), nullptr);
-
-  bool res = parse_config_file(config_file.get(), list_);
-
-  ASSERT_TRUE(res);
-  ASSERT_EQ(list_->num_entries, 3);
-  struct config_entry *first_entry = list_->entries;
-  struct config_entry *second_entry = list_->entries + 1;
-  struct config_entry *third_entry = list_->entries + 2;
-  ASSERT_EQ(std::string(first_entry->key), "uts");
-  ASSERT_EQ(first_entry->value, nullptr);
-  ASSERT_EQ(std::string(second_entry->key), "mount");
-  ASSERT_EQ(std::string(second_entry->value), "xyz");
-  ASSERT_EQ(std::string(third_entry->key), "binding");
-  ASSERT_EQ(std::string(third_entry->value), "none,/tmp");
-}
-
-TEST_F(ConfigFileTest, wellformed_multi_line) {
-  std::string config = "% minijail-config-file v0\n"
-                       "# Comments \n"
-                       "\n"
-                       "mount = \\\n"
-                       "none\n"
-                       "binding = none,\\\n"
-                       "/tmp";
-  ScopedFILE config_file(write_to_pipe(config));
-  ASSERT_NE(config_file.get(), nullptr);
-
-  int res = parse_config_file(config_file.get(), list_);
-
-  ASSERT_TRUE(res);
-  ASSERT_EQ(list_->num_entries, 2);
-  struct config_entry *first_entry = list_->entries;
-  struct config_entry *second_entry = list_->entries + 1;
-  ASSERT_EQ(std::string(first_entry->key), "mount");
-  ASSERT_EQ(std::string(first_entry->value), "none");
-  ASSERT_EQ(std::string(second_entry->key), "binding");
-  ASSERT_EQ(std::string(second_entry->value), "none, /tmp");
-}
diff --git a/elfparse.c b/elfparse.c
index 96caa59..e76ebc4 100644
--- a/elfparse.c
+++ b/elfparse.c
@@ -11,7 +11,6 @@
 #include <unistd.h>
 
 #include "elfparse.h"
-#include "util.h"
 
 int is_elf_magic (const uint8_t *buf)
 {
@@ -68,7 +67,7 @@
 ElfType get_elf_linkage(const char *path)
 {
 	ElfType ret = ELFERROR;
-	attribute_cleanup_fp FILE *elf_file = NULL;
+	FILE *elf_file = NULL;
 	uint8_t pHeader[HEADERSIZE] = "";
 
 	elf_file = fopen(path, "re");
@@ -113,6 +112,7 @@
 			 */
 			ret = ELFDYNAMIC;
 		}
+		fclose(elf_file);
 	}
 	return ret;
 }
diff --git a/gen_syscalls-inl.h b/gen_syscalls-inl.h
index d7c43aa..2004f7a 100644
--- a/gen_syscalls-inl.h
+++ b/gen_syscalls-inl.h
@@ -73,7 +73,3 @@
 #ifndef __NR_io_uring_setup
 #define __NR_io_uring_setup 425
 #endif
-
-#ifndef __NR_faccessat2
-#define __NR_faccessat2 439
-#endif
diff --git a/get_googletest.sh b/get_googletest.sh
index 07910b4..b379441 100755
--- a/get_googletest.sh
+++ b/get_googletest.sh
@@ -1,6 +1,6 @@
 #/bin/bash
 
-PV="1.11.0"
+PV="1.10.0"
 
 wget -q -nc --secure-protocol=TLSv1 "https://github.com/google/googletest/archive/release-${PV}.tar.gz" -O "googletest-release-${PV}.tar.gz"
 tar zxvf "googletest-release-${PV}.tar.gz"
diff --git a/libminijail-private.h b/libminijail-private.h
index 8feec55..503f09b 100644
--- a/libminijail-private.h
+++ b/libminijail-private.h
@@ -19,9 +19,8 @@
  */
 #define API __attribute__((__visibility__("default")))
 
-static const char kFdEnvVar[] = "__MINIJAIL_FD";
-static const char kLdPreloadEnvVar[] = "LD_PRELOAD";
-static const char kSeccompPolicyPathEnvVar[] = "SECCOMP_POLICY_PATH";
+static const char *kFdEnvVar = "__MINIJAIL_FD";
+static const char *kLdPreloadEnvVar = "LD_PRELOAD";
 
 struct minijail;
 
@@ -47,7 +46,9 @@
  * The marshalled data is not robust to differences between the child
  * and parent process (personality, etc).
  */
-extern int minijail_marshal(const struct minijail *j, char *buf, size_t size);
+extern int minijail_marshal(const struct minijail *j,
+                            char *buf,
+                            size_t size);
 
 /* minijail_unmarshal: initializes @j from @serialized
  * @j          minijail to initialize
@@ -56,8 +57,9 @@
  *
  * Returns 0 on success.
  */
-extern int minijail_unmarshal(struct minijail *j, char *serialized,
-			      size_t length);
+extern int minijail_unmarshal(struct minijail *j,
+                              char *serialized,
+                              size_t length);
 
 /* minijail_from_fd: builds @j from @fd
  * @j  minijail to initialize
diff --git a/libminijail.c b/libminijail.c
index aab1294..0820dbb 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -36,8 +36,8 @@
 #include <syscall.h>
 #include <unistd.h>
 
-#include "libminijail-private.h"
 #include "libminijail.h"
+#include "libminijail-private.h"
 
 #include "signal_handler.h"
 #include "syscall_filter.h"
@@ -47,19 +47,19 @@
 
 /* Until these are reliably available in linux/prctl.h. */
 #ifndef PR_ALT_SYSCALL
-#define PR_ALT_SYSCALL 0x43724f53
+# define PR_ALT_SYSCALL 0x43724f53
 #endif
 
 /* New cgroup namespace might not be in linux-headers yet. */
 #ifndef CLONE_NEWCGROUP
-#define CLONE_NEWCGROUP 0x02000000
+# define CLONE_NEWCGROUP 0x02000000
 #endif
 
 #define MAX_CGROUPS 10 /* 10 different controllers supported by Linux. */
 
 #define MAX_RLIMITS 32 /* Currently there are 15 supported by Linux. */
 
-#define MAX_PRESERVED_FDS 128U
+#define MAX_PRESERVED_FDS 32U
 
 /* Keyctl commands. */
 #define KEYCTL_JOIN_SESSION_KEYRING 1
@@ -189,17 +189,11 @@
 	struct hook *hooks_tail;
 	struct preserved_fd preserved_fds[MAX_PRESERVED_FDS];
 	size_t preserved_fd_count;
-	char *seccomp_policy_path;
 };
 
 static void run_hooks_or_die(const struct minijail *j,
 			     minijail_hook_event_t event);
 
-static bool seccomp_is_logging_allowed(const struct minijail *j)
-{
-	return seccomp_default_ret_log() || j->flags.seccomp_filter_logging;
-}
-
 static void free_mounts_list(struct minijail *j)
 {
 	while (j->mounts_head) {
@@ -374,8 +368,7 @@
 	j->flags.set_suppl_gids = 1;
 }
 
-void API minijail_keep_supplementary_gids(struct minijail *j)
-{
+void API minijail_keep_supplementary_gids(struct minijail *j) {
 	j->flags.keep_suppl_gids = 1;
 }
 
@@ -426,7 +419,7 @@
 		    "before minijail_parse_seccomp_filters()");
 	}
 
-	if (seccomp_is_logging_allowed(j) && !seccomp_ret_log_available()) {
+	if (j->flags.seccomp_filter_logging && !seccomp_ret_log_available()) {
 		/*
 		 * If SECCOMP_RET_LOG is not available, we don't want to use
 		 * SECCOMP_RET_TRAP to both kill the entire process and report
@@ -462,8 +455,8 @@
 		 * SECCOMP_RET_TRAP to both kill the entire process and report
 		 * failing syscalls, since it will be brittle. Just bail.
 		 */
-		die("SECCOMP_RET_LOG not available, cannot use thread sync "
-		    "with logging at the same time");
+		die("SECCOMP_RET_LOG not available, cannot use thread sync with "
+		    "logging at the same time");
 	}
 
 	if (debug_logging_allowed()) {
@@ -730,7 +723,7 @@
 		 */
 		if (!strncmp(b->dest, path_inside_chroot, strlen(b->dest))) {
 			const char *relative_path =
-			    path_inside_chroot + strlen(b->dest);
+				path_inside_chroot + strlen(b->dest);
 			return path_join(b->src, relative_path);
 		}
 		b = b->next;
@@ -806,8 +799,7 @@
 	return 0;
 }
 
-int API minijail_create_session(struct minijail *j)
-{
+int API minijail_create_session(struct minijail *j) {
 	j->flags.setsid = 1;
 	return 0;
 }
@@ -985,10 +977,6 @@
 	j->filter_len = 0;
 	j->filter_prog = NULL;
 	j->flags.no_new_privs = 0;
-	if (j->seccomp_policy_path) {
-		free(j->seccomp_policy_path);
-	}
-	j->seccomp_policy_path = NULL;
 }
 
 static int seccomp_should_use_filters(struct minijail *j)
@@ -1098,7 +1086,7 @@
 	 * Allow logging?
 	 */
 	filteropts.allow_logging =
-	    debug_logging_allowed() && seccomp_is_logging_allowed(j);
+	    debug_logging_allowed() && j->flags.seccomp_filter_logging;
 
 	/* What to do on a blocked system call? */
 	if (filteropts.allow_logging) {
@@ -1141,7 +1129,7 @@
 	if (!seccomp_should_use_filters(j))
 		return;
 
-	attribute_cleanup_fp FILE *file = fopen(path, "re");
+	FILE *file = fopen(path, "re");
 	if (!file) {
 		pdie("failed to open seccomp filter file '%s'", path);
 	}
@@ -1150,16 +1138,13 @@
 		die("failed to compile seccomp filter BPF program in '%s'",
 		    path);
 	}
-	if (j->seccomp_policy_path) {
-		free(j->seccomp_policy_path);
-	}
-	j->seccomp_policy_path = strdup(path);
+	fclose(file);
 }
 
 void API minijail_parse_seccomp_filters_from_fd(struct minijail *j, int fd)
 {
 	char *fd_path, *path;
-	attribute_cleanup_fp FILE *file = NULL;
+	FILE *file;
 
 	if (!seccomp_should_use_filters(j))
 		return;
@@ -1180,10 +1165,8 @@
 		die("failed to compile seccomp filter BPF program from fd %d",
 		    fd);
 	}
-	if (j->seccomp_policy_path) {
-		free(j->seccomp_policy_path);
-	}
-	j->seccomp_policy_path = path;
+	free(path);
+	fclose(file);
 }
 
 void API minijail_set_seccomp_filters(struct minijail *j,
@@ -1192,7 +1175,7 @@
 	if (!seccomp_should_use_filters(j))
 		return;
 
-	if (seccomp_is_logging_allowed(j)) {
+	if (j->flags.seccomp_filter_logging) {
 		die("minijail_log_seccomp_filter_failures() is incompatible "
 		    "with minijail_set_seccomp_filters()");
 	}
@@ -1293,8 +1276,6 @@
 	}
 	for (i = 0; i < j->cgroup_count; ++i)
 		marshal_append_string(state, j->cgroups[i]);
-	if (j->seccomp_policy_path)
-		marshal_append_string(state, j->seccomp_policy_path);
 }
 
 size_t API minijail_size(const struct minijail *j)
@@ -1338,7 +1319,7 @@
 	j->hooks_head = NULL;
 	j->hooks_tail = NULL;
 
-	if (j->user) { /* stale pointer */
+	if (j->user) {		/* stale pointer */
 		char *user = consumestr(&serialized, &length);
 		if (!user)
 			goto clear_pointers;
@@ -1347,7 +1328,7 @@
 			goto clear_pointers;
 	}
 
-	if (j->suppl_gid_list) { /* stale pointer */
+	if (j->suppl_gid_list) {	/* stale pointer */
 		if (j->suppl_gid_count > NGROUPS_MAX) {
 			goto bad_gid_list;
 		}
@@ -1364,7 +1345,7 @@
 		memcpy(j->suppl_gid_list, gid_list_bytes, gid_list_size);
 	}
 
-	if (j->chrootdir) { /* stale pointer */
+	if (j->chrootdir) {	/* stale pointer */
 		char *chrootdir = consumestr(&serialized, &length);
 		if (!chrootdir)
 			goto bad_chrootdir;
@@ -1373,7 +1354,7 @@
 			goto bad_chrootdir;
 	}
 
-	if (j->hostname) { /* stale pointer */
+	if (j->hostname) {	/* stale pointer */
 		char *hostname = consumestr(&serialized, &length);
 		if (!hostname)
 			goto bad_hostname;
@@ -1382,7 +1363,7 @@
 			goto bad_hostname;
 	}
 
-	if (j->alt_syscall_table) { /* stale pointer */
+	if (j->alt_syscall_table) {	/* stale pointer */
 		char *alt_syscall_table = consumestr(&serialized, &length);
 		if (!alt_syscall_table)
 			goto bad_syscall_table;
@@ -1431,8 +1412,8 @@
 		type = consumestr(&serialized, &length);
 		if (!type)
 			goto bad_mounts;
-		has_data =
-		    consumebytes(sizeof(*has_data), &serialized, &length);
+		has_data = consumebytes(sizeof(*has_data), &serialized,
+					&length);
 		if (!has_data)
 			goto bad_mounts;
 		if (*has_data) {
@@ -1459,23 +1440,8 @@
 		++j->cgroup_count;
 	}
 
-	if (j->seccomp_policy_path) { /* stale pointer */
-		char *seccomp_policy_path = consumestr(&serialized, &length);
-		if (!seccomp_policy_path)
-			goto bad_cgroups;
-		j->seccomp_policy_path = strdup(seccomp_policy_path);
-		if (!j->seccomp_policy_path)
-			goto bad_cgroups;
-	}
-
 	return 0;
 
-	/*
-	 * If more is added after j->seccomp_policy_path, then this is needed:
-	 * if (j->seccomp_policy_path)
-	 * 	free(j->seccomp_policy_path);
-	 */
-
 bad_cgroups:
 	free_mounts_list(j);
 	free_remounts_list(j);
@@ -1491,12 +1457,12 @@
 	if (j->alt_syscall_table)
 		free(j->alt_syscall_table);
 bad_syscall_table:
-	if (j->hostname)
-		free(j->hostname);
-bad_hostname:
 	if (j->chrootdir)
 		free(j->chrootdir);
 bad_chrootdir:
+	if (j->hostname)
+		free(j->hostname);
+bad_hostname:
 	if (j->suppl_gid_list)
 		free(j->suppl_gid_list);
 bad_gid_list:
@@ -1509,7 +1475,6 @@
 	j->hostname = NULL;
 	j->alt_syscall_table = NULL;
 	j->cgroup_count = 0;
-	j->seccomp_policy_path = NULL;
 out:
 	return ret;
 }
@@ -1520,56 +1485,39 @@
 	dev_t major, minor;
 };
 
-// clang-format off
 static const struct dev_spec device_nodes[] = {
-    {
-"null",
-	S_IFCHR | 0666, 1, 3,
-    },
-    {
-	"zero",
-	S_IFCHR | 0666, 1, 5,
-    },
-    {
-	"full",
-	S_IFCHR | 0666, 1, 7,
-    },
-    {
-	"urandom",
-	S_IFCHR | 0444, 1, 9,
-    },
-    {
-	"tty",
-	S_IFCHR | 0666, 5, 0,
-    },
+	{
+		"null",
+		S_IFCHR | 0666, 1, 3,
+	},
+	{
+		"zero",
+		S_IFCHR | 0666, 1, 5,
+	},
+	{
+		"full",
+		S_IFCHR | 0666, 1, 7,
+	},
+	{
+		"urandom",
+		S_IFCHR | 0444, 1, 9,
+	},
+	{
+		"tty",
+		S_IFCHR | 0666, 5, 0,
+	},
 };
-// clang-format on
 
 struct dev_sym_spec {
 	const char *source, *dest;
 };
 
 static const struct dev_sym_spec device_symlinks[] = {
-    {
-	"ptmx",
-	"pts/ptmx",
-    },
-    {
-	"fd",
-	"/proc/self/fd",
-    },
-    {
-	"stdin",
-	"fd/0",
-    },
-    {
-	"stdout",
-	"fd/1",
-    },
-    {
-	"stderr",
-	"fd/2",
-    },
+	{ "ptmx", "pts/ptmx", },
+	{ "fd", "/proc/self/fd", },
+	{ "stdin", "fd/0", },
+	{ "stdout", "fd/1", },
+	{ "stderr", "fd/2", },
 };
 
 /*
@@ -1590,7 +1538,7 @@
 static int mount_dev(char **dev_path_ret)
 {
 	int ret;
-	attribute_cleanup_fd int dev_fd = -1;
+	int dev_fd;
 	size_t i;
 	mode_t mask;
 	char *dev_path;
@@ -1604,8 +1552,8 @@
 		pdie("could not create temp path for /dev");
 
 	/* Set up the empty /dev mount point first. */
-	ret = mount("minijail-devfs", dev_path, "tmpfs", MS_NOEXEC | MS_NOSUID,
-		    "size=5M,mode=755");
+	ret = mount("minijail-devfs", dev_path, "tmpfs",
+	            MS_NOEXEC | MS_NOSUID, "size=5M,mode=755");
 	if (ret) {
 		rmdir(dev_path);
 		return ret;
@@ -1615,7 +1563,7 @@
 	mask = umask(0);
 
 	/* Get a handle to the temp dev path for *at funcs below. */
-	dev_fd = open(dev_path, O_DIRECTORY | O_PATH | O_CLOEXEC);
+	dev_fd = open(dev_path, O_DIRECTORY|O_PATH|O_CLOEXEC);
 	if (dev_fd < 0) {
 		ret = 1;
 		goto done;
@@ -1625,7 +1573,7 @@
 	for (i = 0; i < ARRAY_SIZE(device_nodes); ++i) {
 		const struct dev_spec *ds = &device_nodes[i];
 		ret = mknodat(dev_fd, ds->name, ds->mode,
-			      makedev(ds->major, ds->minor));
+		              makedev(ds->major, ds->minor));
 		if (ret)
 			goto done;
 	}
@@ -1644,7 +1592,8 @@
 		goto done;
 
 	/* Restore old mask. */
-done:
+ done:
+	close(dev_fd);
 	umask(mask);
 
 	if (ret)
@@ -1667,14 +1616,14 @@
 	if (umount2("/dev", MNT_DETACH))
 		goto done;
 
-	if (asprintf(&dest, "%s/dev", j->chrootdir ?: "") < 0)
+	if (asprintf(&dest, "%s/dev", j->chrootdir ? : "") < 0)
 		goto done;
 
 	if (mount(dev_path, dest, NULL, MS_MOVE, NULL))
 		goto done;
 
 	ret = 0;
-done:
+ done:
 	free(dest);
 	mount_dev_cleanup(dev_path);
 
@@ -1803,8 +1752,7 @@
 
 static int enter_pivot_root(const struct minijail *j)
 {
-	attribute_cleanup_fd int oldroot = -1;
-	attribute_cleanup_fd int newroot = -1;
+	int oldroot, newroot;
 
 	run_hooks_or_die(j, MINIJAIL_HOOK_EVENT_PRE_CHROOT);
 
@@ -1854,6 +1802,10 @@
 	/* Change back to the new root. */
 	if (fchdir(newroot))
 		return -errno;
+	if (close(oldroot))
+		return -errno;
+	if (close(newroot))
+		return -errno;
 	if (chroot("/"))
 		return -errno;
 	/* Set correct CWD for getcwd(3). */
@@ -1972,10 +1924,7 @@
 		int ret = write_proc_file(j->initpid, "deny", "setgroups");
 		if (ret != 0) {
 			if (ret == -ENOENT) {
-				/*
-				 * See
-				 * http://man7.org/linux/man-pages/man7/user_namespaces.7.html.
-				 */
+				/* See http://man7.org/linux/man-pages/man7/user_namespaces.7.html. */
 				warn("could not disable setgroups(2)");
 			} else
 				kill_child_and_die(
@@ -2025,8 +1974,7 @@
 static void drop_ugid(const struct minijail *j)
 {
 	if (j->flags.inherit_suppl_gids + j->flags.keep_suppl_gids +
-		j->flags.set_suppl_gids >
-	    1) {
+	    j->flags.set_suppl_gids > 1) {
 		die("can only do one of inherit, keep, or set supplementary "
 		    "groups");
 	}
@@ -2191,7 +2139,7 @@
 	}
 
 	if (j->flags.seccomp_filter) {
-		if (seccomp_is_logging_allowed(j)) {
+		if (j->flags.seccomp_filter_logging) {
 			warn("logging seccomp filter failures");
 			if (!seccomp_ret_log_available()) {
 				/*
@@ -2241,7 +2189,8 @@
 
 static pid_t forward_pid = -1;
 
-static void forward_signal(int sig, siginfo_t *siginfo attribute_unused,
+static void forward_signal(int sig,
+			   siginfo_t *siginfo attribute_unused,
 			   void *void_context attribute_unused)
 {
 	if (forward_pid != -1) {
@@ -2367,12 +2316,12 @@
 				if (mount(NULL, temp->mount_name, NULL,
 					  MS_REC | temp->remount_mode, NULL))
 					pdie("mount(NULL, %s, NULL, "
-					     "MS_REC | temp->remount_mode, "
-					     "NULL) failed",
-					     temp->mount_name);
+					     "MS_REC | temp->remount_mode, NULL) "
+					     "failed", temp->mount_name);
 				temp = temp->next;
 			}
 		}
+
 	}
 
 	if (j->flags.ipc && unshare(CLONE_NEWIPC)) {
@@ -2383,8 +2332,7 @@
 		if (unshare(CLONE_NEWUTS))
 			pdie("unshare(CLONE_NEWUTS) failed");
 
-		if (j->hostname &&
-		    sethostname(j->hostname, strlen(j->hostname)))
+		if (j->hostname && sethostname(j->hostname, strlen(j->hostname)))
 			pdie("sethostname(%s) failed", j->hostname);
 	}
 
@@ -2525,19 +2473,22 @@
 {
 	size_t sz = 0;
 	size_t bytes = read(fd, &sz, sizeof(sz));
-	attribute_cleanup_str char *buf = NULL;
+	char *buf;
 	int r;
 	if (sizeof(sz) != bytes)
 		return -EINVAL;
-	if (sz > USHRT_MAX) /* arbitrary check */
+	if (sz > USHRT_MAX)	/* arbitrary sanity check */
 		return -E2BIG;
 	buf = malloc(sz);
 	if (!buf)
 		return -ENOMEM;
 	bytes = read(fd, buf, sz);
-	if (bytes != sz)
+	if (bytes != sz) {
+		free(buf);
 		return -EINVAL;
+	}
 	r = minijail_unmarshal(j, buf, sz);
+	free(buf);
 	return r;
 }
 
@@ -2547,20 +2498,24 @@
 	if (!sz)
 		return -EINVAL;
 
-	attribute_cleanup_str char *buf = malloc(sz);
+	char *buf = malloc(sz);
 	if (!buf)
 		return -ENOMEM;
 
 	int err = minijail_marshal(j, buf, sz);
 	if (err)
-		return err;
+		goto error;
 
 	/* Sends [size][minijail]. */
 	err = write_exactly(fd, &sz, sizeof(sz));
 	if (err)
-		return err;
+		goto error;
 
-	return write_exactly(fd, buf, sz);
+	err = write_exactly(fd, buf, sz);
+
+error:
+	free(buf);
+	return err;
 }
 
 int API minijail_copy_jail(const struct minijail *from, struct minijail *out)
@@ -2569,15 +2524,18 @@
 	if (!sz)
 		return -EINVAL;
 
-	attribute_cleanup_str char *buf = malloc(sz);
+	char *buf = malloc(sz);
 	if (!buf)
 		return -ENOMEM;
 
 	int err = minijail_marshal(from, buf, sz);
 	if (err)
-		return err;
+		goto error;
 
-	return minijail_unmarshal(out, buf, sz);
+	err = minijail_unmarshal(out, buf, sz);
+error:
+	free(buf);
+	return err;
 }
 
 static int setup_preload(const struct minijail *j attribute_unused,
@@ -2590,7 +2548,7 @@
 	const char *preload_path = j->preload_path ?: PRELOADPATH;
 	char *newenv = NULL;
 	int ret = 0;
-	const char *oldenv = minijail_getenv(*child_env, kLdPreloadEnvVar);
+	const char *oldenv = getenv(kLdPreloadEnvVar);
 
 	if (!oldenv)
 		oldenv = "";
@@ -2607,19 +2565,6 @@
 #endif
 }
 
-/*
- * This is for logging purposes and does not change the enforced seccomp
- * filter.
- */
-static int setup_seccomp_policy_path(const struct minijail *j,
-				     char ***child_env)
-{
-	return minijail_setenv(child_env, kSeccompPolicyPathEnvVar,
-			       j->seccomp_policy_path ? j->seccomp_policy_path
-						      : "NO-LABEL",
-			       1 /* overwrite */);
-}
-
 static int setup_pipe(char ***child_env, int fds[2])
 {
 	int r = pipe(fds);
@@ -2678,11 +2623,11 @@
 static_assert(FD_SETSIZE >= MAX_PRESERVED_FDS * 2 - 1,
 	      "If true, ensure_no_fd_conflict will always find an unused fd.");
 
-/* If parent_fd will be used by a child fd, move it to an unused fd. */
-static int ensure_no_fd_conflict(const fd_set *child_fds, int child_fd,
-				 int *parent_fd)
+/* If p->parent_fd will be used by a child_fd, move it to an unused fd. */
+static int ensure_no_fd_conflict(const fd_set* child_fds,
+				 struct preserved_fd* p)
 {
-	if (!FD_ISSET(*parent_fd, child_fds)) {
+	if (!FD_ISSET(p->parent_fd, child_fds)){
 		return 0;
 	}
 
@@ -2690,8 +2635,8 @@
 	 * If no other parent_fd matches the child_fd then use it instead of a
 	 * temporary.
 	 */
-	int fd = child_fd;
-	if (fd == -1 || fd_is_open(fd)) {
+	int fd = p->child_fd;
+	if (fd_is_open(fd)) {
 		fd = FD_SETSIZE - 1;
 		while (FD_ISSET(fd, child_fds) || fd_is_open(fd)) {
 			--fd;
@@ -2701,45 +2646,61 @@
 		}
 	}
 
-	int ret = dup2(*parent_fd, fd);
+	int ret = dup2(p->parent_fd, fd);
 	/*
 	 * warn() opens a file descriptor so it needs to happen after dup2 to
 	 * avoid unintended side effects. This can be avoided by reordering the
 	 * mapping requests so that the source fds with overlap are mapped
 	 * first (unless there are cycles).
 	 */
-	warn("mapped fd overlap: moving %d to %d", *parent_fd, fd);
+	warn("mapped fd overlap: moving %d to %d", p->parent_fd, fd);
 	if (ret == -1) {
 		return -1;
 	}
 
-	*parent_fd = fd;
+	p->parent_fd = fd;
 	return 0;
 }
 
-/*
- * Populate child_fds_out with the set of file descriptors that will be replaced
- * by redirect_fds().
- *
- * NOTE: This creates temporaries for parent file descriptors that would
- * otherwise be overwritten during redirect_fds().
- */
-static int get_child_fds(struct minijail *j, fd_set *child_fds_out)
+static int redirect_fds(struct minijail *j)
 {
+	fd_set child_fds;
+	FD_ZERO(&child_fds);
+
 	/* Relocate parent_fds that would be replaced by a child_fd. */
 	for (size_t i = 0; i < j->preserved_fd_count; i++) {
 		int child_fd = j->preserved_fds[i].child_fd;
-		if (FD_ISSET(child_fd, child_fds_out)) {
+		if (FD_ISSET(child_fd, &child_fds)) {
 			die("fd %d is mapped more than once", child_fd);
 		}
 
-		int *parent_fd = &j->preserved_fds[i].parent_fd;
-		if (ensure_no_fd_conflict(child_fds_out, child_fd, parent_fd) ==
-		    -1) {
+		if (ensure_no_fd_conflict(&child_fds,
+					  &j->preserved_fds[i]) == -1) {
 			return -1;
 		}
 
-		FD_SET(child_fd, child_fds_out);
+		FD_SET(child_fd, &child_fds);
+	}
+
+	for (size_t i = 0; i < j->preserved_fd_count; i++) {
+		if (j->preserved_fds[i].parent_fd ==
+		    j->preserved_fds[i].child_fd) {
+			continue;
+		}
+		if (dup2(j->preserved_fds[i].parent_fd,
+			 j->preserved_fds[i].child_fd) == -1) {
+			return -1;
+		}
+	}
+	/*
+	 * After all fds have been duped, we are now free to close all parent
+	 * fds that are *not* child fds.
+	 */
+	for (size_t i = 0; i < j->preserved_fd_count; i++) {
+		int parent_fd = j->preserved_fds[i].parent_fd;
+		if (!FD_ISSET(parent_fd, &child_fds)) {
+			close(parent_fd);
+		}
 	}
 	return 0;
 }
@@ -2757,80 +2718,6 @@
 	char **child_env;
 };
 
-/*
- * Move pipe_fds if they conflict with a child_fd.
- */
-static int avoid_pipe_conflicts(struct minijail_run_state *state,
-				fd_set *child_fds_out)
-{
-	int *pipe_fds[] = {
-	    state->pipe_fds,   state->child_sync_pipe_fds, state->stdin_fds,
-	    state->stdout_fds, state->stderr_fds,
-	};
-	for (size_t i = 0; i < ARRAY_SIZE(pipe_fds); ++i) {
-		if (pipe_fds[i][0] != -1 &&
-		    ensure_no_fd_conflict(child_fds_out, -1, &pipe_fds[i][0]) ==
-			-1) {
-			return -1;
-		}
-		if (pipe_fds[i][1] != -1 &&
-		    ensure_no_fd_conflict(child_fds_out, -1, &pipe_fds[i][1]) ==
-			-1) {
-			return -1;
-		}
-	}
-	return 0;
-}
-
-/*
- * Redirect j->preserved_fds from the parent_fd to the child_fd.
- *
- * NOTE: This will clear FD_CLOEXEC since otherwise the child_fd would not be
- * inherited after the exec call.
- */
-static int redirect_fds(struct minijail *j, fd_set *child_fds)
-{
-	for (size_t i = 0; i < j->preserved_fd_count; i++) {
-		if (j->preserved_fds[i].parent_fd ==
-		    j->preserved_fds[i].child_fd) {
-			// Clear CLOEXEC if it is set so the FD will be
-			// inherited by the child.
-			int flags =
-			    fcntl(j->preserved_fds[i].child_fd, F_GETFD);
-			if (flags == -1 || (flags & FD_CLOEXEC) == 0) {
-				continue;
-			}
-
-			// Currently FD_CLOEXEC is cleared without being
-			// restored. It may make sense to track when this
-			// happens and restore FD_CLOEXEC in the child process.
-			flags &= ~FD_CLOEXEC;
-			if (fcntl(j->preserved_fds[i].child_fd, F_SETFD,
-				  flags) == -1) {
-				pwarn("failed to clear CLOEXEC for %d",
-				      j->preserved_fds[i].parent_fd);
-			}
-			continue;
-		}
-		if (dup2(j->preserved_fds[i].parent_fd,
-			 j->preserved_fds[i].child_fd) == -1) {
-			return -1;
-		}
-	}
-
-	/*
-	 * After all fds have been duped, we are now free to close all parent
-	 * fds that are *not* child fds.
-	 */
-	for (size_t i = 0; i < j->preserved_fd_count; i++) {
-		int parent_fd = j->preserved_fds[i].parent_fd;
-		if (!FD_ISSET(parent_fd, child_fds)) {
-			close(parent_fd);
-		}
-	}
-	return 0;
-}
-
 static void minijail_free_run_state(struct minijail_run_state *state)
 {
 	state->child_pid = -1;
@@ -2889,21 +2776,13 @@
 		if (setsid() < 0) {
 			pdie("setsid() failed");
 		}
-
-		if (isatty(STDIN_FILENO)) {
-			if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) != 0) {
-				pwarn("failed to set controlling terminal");
-			}
-		}
 	}
 }
 
 /*
  * Structure that specifies how to start a minijail.
  *
- * filename - The program to exec in the child. Should be NULL if elf_fd is set.
- * elf_fd - A fd to be used with fexecve. Should be -1 if filename is set.
- *   NOTE: either filename or elf_fd is required if |exec_in_child| = 1.
+ * filename - The program to exec in the child. Required if |exec_in_child| = 1.
  * argv - Arguments for the child program. Required if |exec_in_child| = 1.
  * envp - Environment for the child program. Available if |exec_in_child| = 1.
  * use_preload - If true use LD_PRELOAD.
@@ -2916,7 +2795,6 @@
  */
 struct minijail_run_config {
 	const char *filename;
-	int elf_fd;
 	char *const *argv;
 	char *const *envp;
 	int use_preload;
@@ -2936,7 +2814,6 @@
 {
 	struct minijail_run_config config = {
 	    .filename = filename,
-	    .elf_fd = -1,
 	    .argv = argv,
 	    .envp = NULL,
 	    .use_preload = true,
@@ -2945,26 +2822,11 @@
 	return minijail_run_config_internal(j, &config);
 }
 
-int API minijail_run_env(struct minijail *j, const char *filename,
-			 char *const argv[], char *const envp[])
-{
-	struct minijail_run_config config = {
-	    .filename = filename,
-	    .elf_fd = -1,
-	    .argv = argv,
-	    .envp = envp,
-	    .use_preload = true,
-	    .exec_in_child = true,
-	};
-	return minijail_run_config_internal(j, &config);
-}
-
 int API minijail_run_pid(struct minijail *j, const char *filename,
 			 char *const argv[], pid_t *pchild_pid)
 {
 	struct minijail_run_config config = {
 	    .filename = filename,
-	    .elf_fd = -1,
 	    .argv = argv,
 	    .envp = NULL,
 	    .use_preload = true,
@@ -2979,7 +2841,6 @@
 {
 	struct minijail_run_config config = {
 	    .filename = filename,
-	    .elf_fd = -1,
 	    .argv = argv,
 	    .envp = NULL,
 	    .use_preload = true,
@@ -2995,7 +2856,6 @@
 {
 	struct minijail_run_config config = {
 	    .filename = filename,
-	    .elf_fd = -1,
 	    .argv = argv,
 	    .envp = NULL,
 	    .use_preload = true,
@@ -3015,27 +2875,6 @@
 {
 	struct minijail_run_config config = {
 	    .filename = filename,
-	    .elf_fd = -1,
-	    .argv = argv,
-	    .envp = envp,
-	    .use_preload = true,
-	    .exec_in_child = true,
-	    .pstdin_fd = pstdin_fd,
-	    .pstdout_fd = pstdout_fd,
-	    .pstderr_fd = pstderr_fd,
-	    .pchild_pid = pchild_pid,
-	};
-	return minijail_run_config_internal(j, &config);
-}
-
-int API minijail_run_fd_env_pid_pipes(struct minijail *j, int elf_fd,
-				      char *const argv[], char *const envp[],
-				      pid_t *pchild_pid, int *pstdin_fd,
-				      int *pstdout_fd, int *pstderr_fd)
-{
-	struct minijail_run_config config = {
-	    .filename = NULL,
-	    .elf_fd = elf_fd,
 	    .argv = argv,
 	    .envp = envp,
 	    .use_preload = true,
@@ -3053,7 +2892,6 @@
 {
 	struct minijail_run_config config = {
 	    .filename = filename,
-	    .elf_fd = -1,
 	    .argv = argv,
 	    .envp = NULL,
 	    .use_preload = false,
@@ -3064,13 +2902,14 @@
 
 int API minijail_run_pid_pipes_no_preload(struct minijail *j,
 					  const char *filename,
-					  char *const argv[], pid_t *pchild_pid,
-					  int *pstdin_fd, int *pstdout_fd,
+					  char *const argv[],
+					  pid_t *pchild_pid,
+					  int *pstdin_fd,
+					  int *pstdout_fd,
 					  int *pstderr_fd)
 {
 	struct minijail_run_config config = {
 	    .filename = filename,
-	    .elf_fd = -1,
 	    .argv = argv,
 	    .envp = NULL,
 	    .use_preload = false,
@@ -3092,7 +2931,6 @@
 {
 	struct minijail_run_config config = {
 	    .filename = filename,
-	    .elf_fd = -1,
 	    .argv = argv,
 	    .envp = envp,
 	    .use_preload = false,
@@ -3107,9 +2945,7 @@
 
 pid_t API minijail_fork(struct minijail *j)
 {
-	struct minijail_run_config config = {
-	    .elf_fd = -1,
-	};
+	struct minijail_run_config config = {};
 	return minijail_run_config_internal(j, &config);
 }
 
@@ -3128,25 +2964,6 @@
 	int do_init = j->flags.do_init && !j->flags.run_as_init;
 	int use_preload = config->use_preload;
 
-	if (config->filename != NULL && config->elf_fd != -1) {
-		die("filename and elf_fd cannot be set at the same time");
-	}
-
-	/*
-	 * Only copy the environment if we need to modify it. If this is done
-	 * unconditionally, it triggers odd behavior in the ARC container.
-	 */
-	if (use_preload || j->seccomp_policy_path) {
-		state_out->child_env =
-		    minijail_copy_env(config->envp ? config->envp : environ);
-		if (!state_out->child_env)
-			return ENOMEM;
-	}
-
-	if (j->seccomp_policy_path &&
-	    setup_seccomp_policy_path(j, &state_out->child_env))
-		return -EFAULT;
-
 	if (use_preload) {
 		if (j->hooks_head != NULL)
 			die("Minijail hooks are not supported with LD_PRELOAD");
@@ -3157,6 +2974,10 @@
 		 * Before we fork(2) and execve(2) the child process, we need
 		 * to open a pipe(2) to send the minijail configuration over.
 		 */
+		state_out->child_env =
+		    minijail_copy_env(config->envp ? config->envp : environ);
+		if (!state_out->child_env)
+			return ENOMEM;
 		if (setup_preload(j, &state_out->child_env) ||
 		    setup_pipe(&state_out->child_env, state_out->pipe_fds))
 			return -EFAULT;
@@ -3249,9 +3070,8 @@
 
 		if (child_pid < 0) {
 			if (errno == EPERM)
-				pdie("clone(CLONE_NEWPID | ...) failed with "
-				     "EPERM; is this process missing "
-				     "CAP_SYS_ADMIN?");
+				pdie("clone(CLONE_NEWPID | ...) failed with EPERM; "
+				     "is this process missing CAP_SYS_ADMIN?");
 			pdie("clone(CLONE_NEWPID | ...) failed");
 		}
 	} else {
@@ -3317,15 +3137,13 @@
 			/* Accept any pending SIGPIPE. */
 			while (true) {
 				const struct timespec zero_time = {0, 0};
-				const int sig =
-				    sigtimedwait(&to_block, NULL, &zero_time);
+				const int sig = sigtimedwait(&to_block, NULL, &zero_time);
 				if (sig < 0) {
 					if (errno != EINTR)
 						break;
 				} else {
 					if (sig != SIGPIPE)
-						die("unexpected signal %d",
-						    sig);
+						die("unexpected signal %d", sig);
 				}
 			}
 
@@ -3368,7 +3186,7 @@
 	}
 
 	if (j->flags.close_open_fds) {
-		const size_t kMaxInheritableFdsSize = 11 + MAX_PRESERVED_FDS;
+		const size_t kMaxInheritableFdsSize = 10 + MAX_PRESERVED_FDS;
 		int inheritable_fds[kMaxInheritableFdsSize];
 		size_t size = 0;
 
@@ -3405,29 +3223,11 @@
 			inheritable_fds[size++] = j->preserved_fds[i].parent_fd;
 		}
 
-		if (config->elf_fd > -1) {
-			inheritable_fds[size++] = config->elf_fd;
-		}
-
 		if (close_open_fds(inheritable_fds, size) < 0)
 			die("failed to close open file descriptors");
 	}
 
-	/* The set of fds will be replaced. */
-	fd_set child_fds;
-	FD_ZERO(&child_fds);
-	if (get_child_fds(j, &child_fds))
-		die("failed to set up fd redirections");
-
-	if (avoid_pipe_conflicts(state_out, &child_fds))
-		die("failed to redirect conflicting pipes");
-
-	/* The elf_fd needs to be mutable so use a stack copy from now on. */
-	int elf_fd = config->elf_fd;
-	if (elf_fd != -1 && ensure_no_fd_conflict(&child_fds, -1, &elf_fd))
-		die("failed to redirect elf_fd");
-
-	if (redirect_fds(j, &child_fds))
+	if (redirect_fds(j))
 		die("failed to set up fd redirections");
 
 	if (sync_child)
@@ -3482,7 +3282,7 @@
 			 * Best effort. Don't bother checking the return value.
 			 */
 			prctl(PR_SET_NAME, "minijail-init");
-			init(child_pid); /* Never returns. */
+			init(child_pid);	/* Never returns. */
 		}
 		state_out->child_pid = child_pid;
 	}
@@ -3517,16 +3317,10 @@
 	 */
 	if (!child_env)
 		child_env = config->envp ? config->envp : environ;
-	if (elf_fd > -1) {
-		fexecve(elf_fd, config->argv, child_env);
-		pwarn("fexecve(%d) failed", config->elf_fd);
-	} else {
-		execve(config->filename, config->argv, child_env);
-		pwarn("execve(%s) failed", config->filename);
-	}
+	execve(config->filename, config->argv, child_env);
 
-	ret = (errno == ENOENT ? MINIJAIL_ERR_NO_COMMAND
-			       : MINIJAIL_ERR_NO_ACCESS);
+	ret = (errno == ENOENT ? MINIJAIL_ERR_NO_COMMAND : MINIJAIL_ERR_NO_ACCESS);
+	pwarn("execve(%s) failed", config->filename);
 	_exit(ret);
 }
 
@@ -3591,38 +3385,32 @@
 
 	if (!WIFEXITED(st)) {
 		int error_status = st;
-		if (!WIFSIGNALED(st)) {
-			return error_status;
-		}
-
-		int signum = WTERMSIG(st);
-		/*
-		 * We return MINIJAIL_ERR_JAIL if the process received
-		 * SIGSYS, which happens when a syscall is blocked by
-		 * seccomp filters.
-		 * If not, we do what bash(1) does:
-		 * $? = 128 + signum
-		 */
-		if (signum == SIGSYS) {
-			warn("child process %d had a policy violation (%s)",
-			     j->initpid,
-			     j->seccomp_policy_path ? j->seccomp_policy_path
-						    : "NO-LABEL");
-			error_status = MINIJAIL_ERR_JAIL;
-		} else {
+		if (WIFSIGNALED(st)) {
+			int signum = WTERMSIG(st);
 			if (signum != expected_signal) {
 				warn("child process %d received signal %d",
 				     j->initpid, signum);
 			}
-			error_status = MINIJAIL_ERR_SIG_BASE + signum;
+			/*
+			 * We return MINIJAIL_ERR_JAIL if the process received
+			 * SIGSYS, which happens when a syscall is blocked by
+			 * seccomp filters.
+			 * If not, we do what bash(1) does:
+			 * $? = 128 + signum
+			 */
+			if (signum == SIGSYS) {
+				error_status = MINIJAIL_ERR_JAIL;
+			} else {
+				error_status = MINIJAIL_ERR_SIG_BASE + signum;
+			}
 		}
 		return error_status;
 	}
 
 	int exit_status = WEXITSTATUS(st);
 	if (exit_status != 0)
-		info("child process %d exited with status %d", j->initpid,
-		     exit_status);
+		info("child process %d exited with status %d",
+		     j->initpid, exit_status);
 
 	return exit_status;
 }
@@ -3679,8 +3467,6 @@
 		free(j->alt_syscall_table);
 	for (i = 0; i < j->cgroup_count; ++i)
 		free(j->cgroups[i]);
-	if (j->seccomp_policy_path)
-		free(j->seccomp_policy_path);
 	free(j);
 }
 
diff --git a/libminijail.h b/libminijail.h
index d2dce7a..cfd42d2 100644
--- a/libminijail.h
+++ b/libminijail.h
@@ -344,13 +344,6 @@
 
 /*
  * Run the specified command in the given minijail, execve(2)-style.
- * Pass |envp| as the full environment for the child.
- */
-int minijail_run_env(struct minijail *j, const char *filename,
-		     char *const argv[], char *const envp[]);
-
-/*
- * Run the specified command in the given minijail, execve(2)-style.
  * If minijail_namespace_pids() or minijail_namespace_user() are used,
  * this or minijail_fork() is required instead of minijail_enter().
  */
@@ -411,23 +404,6 @@
 			       int *pstdout_fd, int *pstderr_fd);
 
 /*
- * Execute the specified file descriptor in the given minijail,
- * fexecve(3)-style.
- * Pass |envp| as the full environment for the child or NULL to inherit.
- * Update |*pchild_pid| with the pid of the child.
- * Update |*pstdin_fd| with a fd that allows writing to the child's
- * standard input.
- * Update |*pstdout_fd| with a fd that allows reading from the child's
- * standard output.
- * Update |*pstderr_fd| with a fd that allows reading from the child's
- * standard error.
- */
-int minijail_run_fd_env_pid_pipes(struct minijail *j, int elf_fd,
-			          char *const argv[], char *const envp[],
-				  pid_t *pchild_pid, int *pstdin_fd,
-				  int *pstdout_fd, int *pstderr_fd);
-
-/*
  * Run the specified command in the given minijail, execve(2)-style.
  * Update |*pchild_pid| with the pid of the child.
  * Update |*pstdin_fd| with a fd that allows writing to the child's
diff --git a/libminijail_unittest.cc b/libminijail_unittest.cc
index 868b7d7..78e3cfb 100644
--- a/libminijail_unittest.cc
+++ b/libminijail_unittest.cc
@@ -9,7 +9,6 @@
 
 #include <dirent.h>
 #include <fcntl.h>
-#include <sys/mman.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -474,94 +473,6 @@
   EXPECT_EQ(minijail_wait(j.get()), 42);
 }
 
-TEST(Test, minijail_no_clobber_pipe_fd) {
-  const ScopedMinijail j(minijail_new());
-  char* const script = R"(
-      echo Hi >&1;
-      exec 1>&-;
-      exec 4>&-;
-      exec 7>&-;
-      read line1;
-      read line2;
-      echo "$line1$line2 and Goodbye" >&2;
-      exit 42;
-    )";
-  char* const argv[] = {"sh", "-c", script, nullptr};
-
-  const int npipes = 3;
-  int fds[npipes][2];
-
-  // Create pipes.
-  for (int i = 0; i < npipes; ++i) {
-    ASSERT_EQ(pipe(fds[i]), 0);
-  }
-
-  // All pipes are output pipes except for the first one which is used as
-  // input pipe.
-  std::swap(fds[0][0], fds[0][1]);
-
-  // Generate a lot of mappings to try to clobber any file descriptors generated
-  // by libminijail.
-  for (int offset = 0; offset < npipes * 3; offset += npipes) {
-    for (int i = 0 ; i < npipes; ++i) {
-      const int fd = fds[i][1];
-      minijail_preserve_fd(j.get(), fd, i + offset);
-    }
-  }
-
-  minijail_close_open_fds(j.get());
-
-  EXPECT_EQ(minijail_run_no_preload(j.get(), kShellPath, argv), 0);
-
-  // Close unused end of pipes.
-  for (int i = 0; i < npipes; ++i) {
-    const int fd = fds[i][1];
-    ASSERT_EQ(close(fd), 0);
-  }
-
-  const int in = fds[0][0];
-  const int out = fds[1][0];
-  const int err = fds[2][0];
-
-  char buf[PIPE_BUF];
-  ssize_t nbytes;
-
-  // Check that stdout pipe works.
-  nbytes = read(out, buf, PIPE_BUF);
-  ASSERT_GT(nbytes, 0);
-  EXPECT_EQ(std::string(buf, nbytes), "Hi\n");
-
-  // Check that the write end of stdout pipe got closed by the child process. If
-  // the child process kept other file descriptors connected to stdout, then the
-  // parent process wouldn't be able to detect that all write ends of this pipe
-  // are closed and it would block here.
-  EXPECT_EQ(read(out, buf, PIPE_BUF), 0);
-  ASSERT_EQ(close(out), 0);
-
-  // Check that stdin pipe works.
-  const std::string s = "Greetings\n";
-  EXPECT_EQ(write(in, s.data(), s.size()), s.size());
-
-  // Close write end of pipe connected to child's stdin. If there was another
-  // file descriptor connected to this write end, then the child process
-  // wouldn't be able to detect that this write end is closed and it would
-  // block.
-  ASSERT_EQ(close(in), 0);
-
-  // Check that child process continued and ended.
-  nbytes = read(err, buf, PIPE_BUF);
-  ASSERT_GT(nbytes, 0);
-  EXPECT_EQ(std::string(buf, nbytes), "Greetings and Goodbye\n");
-
-  // Check that the write end of the stderr pipe is closed when the child
-  // process finishes.
-  EXPECT_EQ(read(err, buf, PIPE_BUF), 0);
-  ASSERT_EQ(close(err), 0);
-
-  // Check the child process termination status.
-  EXPECT_EQ(minijail_wait(j.get()), 42);
-}
-
 TEST(Test, minijail_run_env_pid_pipes) {
   // TODO(crbug.com/895875): The preload library interferes with ASan since they
   // both need to use LD_PRELOAD.
@@ -625,56 +536,6 @@
   EXPECT_EQ(WEXITSTATUS(status), 0);
 }
 
-TEST(Test, minijail_run_fd_env_pid_pipes) {
-  // TODO(crbug.com/895875): The preload library interferes with ASan since they
-  // both need to use LD_PRELOAD.
-  if (running_with_asan())
-    GTEST_SKIP();
-
-  ScopedMinijail j(minijail_new());
-  minijail_set_preload_path(j.get(), kPreloadPath);
-
-  char *argv[4];
-  argv[0] = const_cast<char*>(kShellPath);
-  argv[1] = "-c";
-  argv[2] = "echo \"${TEST_PARENT+set}|${TEST_VAR}\" >&2\n";
-  argv[3] = nullptr;
-
-  char *envp[2];
-  envp[0] = "TEST_VAR=test";
-  envp[1] = nullptr;
-
-  // Set a canary env var in the parent that should not be present in the child.
-  ASSERT_EQ(setenv("TEST_PARENT", "test", 1 /*overwrite*/), 0);
-
-  int elf_fd = open(const_cast<char*>(kShellPath), O_RDONLY | O_CLOEXEC);
-  ASSERT_NE(elf_fd, -1);
-
-  int dev_null = open("/dev/null", O_RDONLY);
-  ASSERT_NE(dev_null, -1);
-  // Create a mapping to dev_null that would clobber elf_fd if it is not
-  // relocated.
-  minijail_preserve_fd(j.get(), dev_null, elf_fd);
-
-  pid_t pid;
-  int child_stdin, child_stdout, child_stderr;
-  int mj_run_ret =
-      minijail_run_fd_env_pid_pipes(j.get(), elf_fd, argv, envp, &pid,
-                                    &child_stdin, &child_stdout, &child_stderr);
-  EXPECT_EQ(mj_run_ret, 0);
-  close(dev_null);
-
-  char buf[kBufferSize] = {};
-  ssize_t read_ret = read(child_stderr, buf, sizeof(buf) - 1);
-  EXPECT_GE(read_ret, 0);
-  EXPECT_STREQ(buf, "|test\n");
-
-  int status;
-  EXPECT_EQ(waitpid(pid, &status, 0), pid);
-  ASSERT_TRUE(WIFEXITED(status));
-  EXPECT_EQ(WEXITSTATUS(status), 0);
-}
-
 TEST(Test, minijail_run_env_pid_pipes_with_local_preload) {
   // TODO(crbug.com/895875): The preload library interferes with ASan since they
   // both need to use LD_PRELOAD.
@@ -740,56 +601,6 @@
   EXPECT_EQ(WEXITSTATUS(status), 0);
 }
 
-TEST(Test, test_minijail_no_clobber_fds) {
-  int dev_null = open("/dev/null", O_RDONLY);
-  ASSERT_NE(dev_null, -1);
-
-  ScopedMinijail j(minijail_new());
-
-  // Keep stderr.
-  minijail_preserve_fd(j.get(), 2, 2);
-  // Create a lot of mappings to dev_null to possibly clobber libminijail.c fds.
-  for (int i = 3; i < 15; ++i) {
-    minijail_preserve_fd(j.get(), dev_null, i);
-  }
-
-  char *argv[4];
-  argv[0] = const_cast<char*>(kShellPath);
-  argv[1] = "-c";
-  argv[2] = "echo Hello; read line1; echo \"${line1}\" >&2";
-  argv[3] = nullptr;
-
-  pid_t pid;
-  int child_stdin;
-  int child_stdout;
-  int child_stderr;
-  int mj_run_ret = minijail_run_pid_pipes_no_preload(
-      j.get(), argv[0], argv, &pid, &child_stdin, &child_stdout, &child_stderr);
-  EXPECT_EQ(mj_run_ret, 0);
-
-  char buf[kBufferSize];
-  ssize_t read_ret = read(child_stdout, buf, sizeof(buf));
-  EXPECT_GE(read_ret, 0);
-  buf[read_ret] = '\0';
-  EXPECT_STREQ(buf, "Hello\n");
-
-  constexpr char to_write[] = "test in and err\n";
-  ssize_t write_ret = write(child_stdin, to_write, sizeof(to_write));
-  EXPECT_EQ(write_ret, sizeof(to_write));
-
-  read_ret = read(child_stderr, buf, sizeof(buf));
-  EXPECT_GE(read_ret, 0);
-  buf[read_ret] = '\0';
-  EXPECT_STREQ(buf, to_write);
-
-  int status;
-  waitpid(pid, &status, 0);
-  ASSERT_TRUE(WIFEXITED(status));
-  EXPECT_EQ(WEXITSTATUS(status), 0);
-
-  close(dev_null);
-}
-
 TEST(Test, test_minijail_no_fd_leaks) {
   pid_t pid;
   int child_stdout;
@@ -1281,7 +1092,7 @@
   argv[0] = const_cast<char*>(kShellPath);
   argv[1] = "-c";
   argv[2] = "grep -E 'shared:|master:|propagate_from:|unbindable:' "
-            "/proc/self/mountinfo";
+	    "/proc/self/mountinfo";
   argv[3] = NULL;
   mj_run_ret = minijail_run_pid_pipes_no_preload(
       j, argv[0], argv, &pid, NULL, &child_stdout, NULL);
diff --git a/libminijailpreload.c b/libminijailpreload.c
index b5a3c75..a98b736 100644
--- a/libminijailpreload.c
+++ b/libminijailpreload.c
@@ -11,7 +11,6 @@
 
 #include "libminijail.h"
 #include "libminijail-private.h"
-#include "util.h"
 
 #include <dlfcn.h>
 #include <stdio.h>
@@ -24,24 +23,18 @@
 static int (*real_main) (int, char **, char **);
 static void *libc_handle;
 
-static void truncate_preload_env(char **envp, const char *name)
+static void die(const char *failed)
 {
-	char *env_value = minijail_getenv(envp, name);
-	if (env_value) {
-		/*
-		 * if we have more than just libminijailpreload.so in
-		 * LD_PRELOAD, cut out libminijailpreload.so from it,
-		 * as it is guaranteed to always be last in the
-		 * LD_PRELOAD list.
-		 */
-		char *last_space = strrchr(env_value, ' ');
-		if (last_space) {
-			*last_space = '\0';
-		} else {
-			/* Only our lib was in LD_PRELOAD, just unset it. */
-			minijail_unsetenv(envp, name);
-		}
-	}
+	syslog(LOG_ERR, "libminijail: %s", failed);
+	abort();
+}
+
+static void unset_in_env(char **envp, const char *name)
+{
+	int i;
+	for (i = 0; envp[i]; i++)
+		if (!strncmp(envp[i], name, strlen(name)))
+			envp[i][0] = '\0';
 }
 
 /** @brief Fake main(), spliced in before the real call to main() by
@@ -78,10 +71,12 @@
 		die("preload: failed to parse minijail from parent");
 	close(fd);
 
-	minijail_unsetenv(envp, kFdEnvVar);
-
-	truncate_preload_env(envp, kLdPreloadEnvVar);
-
+	unset_in_env(envp, kFdEnvVar);
+	/* TODO(ellyjones): this trashes existing preloads, so one can't do:
+	 * LD_PRELOAD="/tmp/test.so libminijailpreload.so" prog; the
+	 * descendants of prog will have no LD_PRELOAD set at all.
+	 */
+	unset_in_env(envp, kLdPreloadEnvVar);
 	/* Strip out flags meant for the parent. */
 	minijail_preenter(j);
 	minijail_enter(j);
diff --git a/linux-x86/libsyscalls.gen.c b/linux-x86/libsyscalls.gen.c
index 1403380..e0b2e53 100644
--- a/linux-x86/libsyscalls.gen.c
+++ b/linux-x86/libsyscalls.gen.c
@@ -1038,27 +1038,6 @@
 #ifdef __NR_fspick
 { "fspick", __NR_fspick },
 #endif
-#ifdef __NR_pidfd_open
-{ "pidfd_open", __NR_pidfd_open },
-#endif
-#ifdef __NR_clone3
-{ "clone3", __NR_clone3 },
-#endif
-#ifdef __NR_close_range
-{ "close_range", __NR_close_range },
-#endif
-#ifdef __NR_openat2
-{ "openat2", __NR_openat2 },
-#endif
-#ifdef __NR_pidfd_getfd
-{ "pidfd_getfd", __NR_pidfd_getfd },
-#endif
-#ifdef __NR_faccessat2
-{ "faccessat2", __NR_faccessat2 },
-#endif
-#ifdef __NR_process_madvise
-{ "process_madvise", __NR_process_madvise },
-#endif
   { NULL, -1 },
 };
 
diff --git a/minijail0.1 b/minijail0.1
index a53ec6f..7dc6f74 100644
--- a/minijail0.1
+++ b/minijail0.1
@@ -12,7 +12,7 @@
 Run using the alternate syscall table named \fItable\fR. Only available on kernels
 and architectures that support the \fBPR_ALT_SYSCALL\fR option of \fBprctl\fR(2).
 .TP
-\fB-b <src>[,[dest][,<writeable>]]\fR, \fB--bind-mount=<src>[,[dest][,<writeable>]]\fR
+\fB-b <src>[,[dest][,<writeable>]]
 Bind-mount \fIsrc\fR into the chroot directory at \fIdest\fR, optionally writeable.
 The \fIsrc\fR path must be an absolute path.
 
@@ -116,7 +116,7 @@
 the first minijail process outside of the pid namespace while the \fB-I\fR
 option controls the minijail process inside of the pid namespace.
 .TP
-\fB-k <src>,<dest>,<type>[,<flags>[,<data>]]\fR, \fB--mount=<src>,<dest>,<type>[,<flags>[,<data>]]\fR
+\fB-k <src>,<dest>,<type>[,<flags>[,<data>]]\fR
 Mount \fIsrc\fR, a \fItype\fR filesystem, at \fIdest\fR.  If a chroot or pivot
 root is active, \fIdest\fR will automatically be placed below that path.
 
@@ -257,7 +257,7 @@
 \fB-U\fR
 Enter a new user namespace (implies \fB-p\fR).
 .TP
-\fB-v\fR, \fB--ns-mount\fR
+\fB-v\fR
 Run inside a new VFS namespace. This option prevents mounts performed by the
 program from affecting the rest of the system (but see \fB-K\fR).
 .TP
@@ -289,16 +289,6 @@
 Create a new UTS/hostname namespace, and optionally set the hostname in the new
 namespace to \fIhostname\fR.
 .TP
-\fB--env-reset\fR
-Clear the current environment instead of having the program inherit the active
-environment. This is often used to start the program with a minimal
-sanitized environment.
-.TP
-\fB--env-add <NAME=value>\fR
-Adds or replace the specified environment variable \fINAME\fR in the program's
-environment before starting it, and set it to the specified \fIvalue\fR.
-This option can be used several times to set any number of environment variables.
-.TP
 \fB--logging=<system>\fR
 Use \fIsystem\fR as the logging system. \fIsystem\fR must be one of
 \fBauto\fR (the default), \fBsyslog\fR, or \fBstderr\fR.
@@ -337,11 +327,6 @@
 
 See the kernel documentation \fIDocumentation/userspace-api/spec_ctrl.rst\fR
 and \fIDocumentation/admin-guide/hw-vuln/spectre.rst\fR for more information.
-.TP
-\fB--config <file path>\fR
-Use a Minijail configuration file to set options, through
-commandline-option-equivalent key-value pairs.
-See \fBminijail0\fR(5) for more details on the format of the configuration file.
 .SH SANDBOXING PROFILES
 The following sandboxing profiles are supported:
 .TP
diff --git a/minijail0.5 b/minijail0.5
index 3e4f114..65d1626 100644
--- a/minijail0.5
+++ b/minijail0.5
@@ -157,31 +157,6 @@
 no active implementation for this, but something like
 code.google.com/p/seccompsandbox is one possible runtime variant.
 
-.SH CONFIGURATION FILE
-A configuration file can be used to specify command line options and other
-settings.
-
-It supports the following syntax:
-  \fB% minijail-config-file v0\fR
-  \fB<option>\fR=\fB<argument>\fR
-  \fB<no-argument-option>\fR
-  \fB<empty line>\fR
-  \fB# any single line comment\fR
-
-Long lines may be broken up using \\ at the end.
-
-The special directive "% minijail-config-file v0" must occupy the first line.
-"v0" also declares the version of the config file format.
-
-Keys contain only alphabetic characters and '-'. Values can be any non-empty
-string. Leading and trailing whitespaces around keys and
-values are permitted but will be stripped before processing.
-
-Currently all long options are supported such as
-\fBmount\fR, \fBbind-mount\fR. For a option that has no argument, the option
-will occupy a single line, without '=' and value. Otherwise, any string that
-is given after the '=' is interpreted as the argument.
-
 .SH AUTHOR
 The Chromium OS Authors <[email protected]>
 .SH COPYRIGHT
diff --git a/minijail0.c b/minijail0.c
index 9b1fcf3..f216d6e 100644
--- a/minijail0.c
+++ b/minijail0.c
@@ -4,7 +4,6 @@
  */
 
 #include <dlfcn.h>
-#include <err.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -16,17 +15,15 @@
 #include "minijail0_cli.h"
 #include "util.h"
 
-int main(int argc, char *argv[], char *environ[])
+int main(int argc, char *argv[])
 {
 	struct minijail *j = minijail_new();
 	const char *dl_mesg = NULL;
 	const char *preload_path = PRELOADPATH;
 	int exit_immediately = 0;
 	ElfType elftype = ELFERROR;
-	char **envp = NULL;
-	int consumed = parse_args(j, argc, argv, environ,
-				  &exit_immediately, &elftype,
-				  &preload_path, &envp);
+	int consumed = parse_args(j, argc, argv, &exit_immediately, &elftype,
+				  &preload_path);
 	argc -= consumed;
 	argv += consumed;
 
@@ -40,8 +37,10 @@
 	 * the process is already a process group leader.
 	 */
 	if (setpgid(0 /* use calling PID */, 0 /* make PGID = PID */)) {
-		if (errno != EPERM)
-			err(1, "setpgid(0, 0) failed");
+		if (errno != EPERM) {
+			fprintf(stderr, "setpgid(0, 0) failed\n");
+			exit(1);
+		}
 	}
 
 	if (elftype == ELFSTATIC) {
@@ -59,17 +58,16 @@
 		/* Check that we can dlopen() libminijailpreload.so. */
 		if (!dlopen(preload_path, RTLD_LAZY | RTLD_LOCAL)) {
 			dl_mesg = dlerror();
-			errx(1, "dlopen(): %s", dl_mesg);
+			fprintf(stderr, "dlopen(): %s\n", dl_mesg);
 			return 1;
 		}
 		minijail_set_preload_path(j, preload_path);
-		if (envp) {
-			minijail_run_env(j, argv[0], argv, envp);
-		} else {
-			minijail_run(j, argv[0], argv);
-		}
+		minijail_run(j, argv[0], argv);
 	} else {
-		errx(1, "Target program '%s' is not a valid ELF file", argv[0]);
+		fprintf(stderr,
+			"Target program '%s' is not a valid ELF file.\n",
+			argv[0]);
+		return 1;
 	}
 
 	if (exit_immediately)
diff --git a/minijail0_cli.c b/minijail0_cli.c
index e366846..3461579 100644
--- a/minijail0_cli.c
+++ b/minijail0_cli.c
@@ -4,9 +4,7 @@
  */
 
 #include <dlfcn.h>
-#include <err.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <getopt.h>
 #include <inttypes.h>
 #include <stdbool.h>
@@ -15,9 +13,7 @@
 #include <string.h>
 #include <sys/capability.h>
 #include <sys/mount.h>
-#include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/vfs.h>
 #include <unistd.h>
 
 #include <linux/filter.h>
@@ -25,7 +21,6 @@
 #include "libminijail.h"
 #include "libsyscalls.h"
 
-#include "config_parser.h"
 #include "elfparse.h"
 #include "minijail0_cli.h"
 #include "system.h"
@@ -41,16 +36,20 @@
 static void *xmalloc(size_t size)
 {
 	void *ret = malloc(size);
-	if (!ret)
-		err(1, "malloc() failed");
+	if (!ret) {
+		perror("malloc() failed");
+		exit(1);
+	}
 	return ret;
 }
 
 static char *xstrdup(const char *s)
 {
 	char *ret = strdup(s);
-	if (!ret)
-		err(1, "strdup() failed");
+	if (!ret) {
+		perror("strdup() failed");
+		exit(1);
+	}
 	return ret;
 }
 
@@ -58,7 +57,7 @@
 		     gid_t *out_gid)
 {
 	char *end = NULL;
-	uid_t uid = strtoul(arg, &end, 10);
+	int uid = strtod(arg, &end);
 	if (!*end && *arg) {
 		*out_uid = uid;
 		minijail_change_uid(j, uid);
@@ -67,21 +66,22 @@
 
 	int ret = lookup_user(arg, out_uid, out_gid);
 	if (ret) {
-		errno = -ret;
-		err(1, "Bad user '%s'", arg);
+		fprintf(stderr, "Bad user '%s': %s\n", arg, strerror(-ret));
+		exit(1);
 	}
 
 	ret = minijail_change_user(j, arg);
 	if (ret) {
-		errno = -ret;
-		err(1, "minijail_change_user('%s') failed", arg);
+		fprintf(stderr, "minijail_change_user('%s') failed: %s\n", arg,
+			strerror(-ret));
+		exit(1);
 	}
 }
 
 static void set_group(struct minijail *j, const char *arg, gid_t *out_gid)
 {
 	char *end = NULL;
-	gid_t gid = strtoul(arg, &end, 10);
+	int gid = strtod(arg, &end);
 	if (!*end && *arg) {
 		*out_gid = gid;
 		minijail_change_gid(j, gid);
@@ -90,8 +90,8 @@
 
 	int ret = lookup_group(arg, out_gid);
 	if (ret) {
-		errno = -ret;
-		err(1, "Bad group '%s'", arg);
+		fprintf(stderr, "Bad group '%s': %s\n", arg, strerror(-ret));
+		exit(1);
 	}
 
 	minijail_change_gid(j, *out_gid);
@@ -102,30 +102,33 @@
  * to build the supplementary gids array.
  */
 static void suppl_group_add(size_t *suppl_gids_count, gid_t **suppl_gids,
-			    char *arg)
-{
+                            char *arg) {
 	char *end = NULL;
-	gid_t gid = strtoul(arg, &end, 10);
+	int groupid = strtod(arg, &end);
+	gid_t gid;
 	int ret;
 	if (!*end && *arg) {
 		/* A gid number has been specified, proceed. */
+		gid = groupid;
 	} else if ((ret = lookup_group(arg, &gid))) {
 		/*
 		 * A group name has been specified,
 		 * but doesn't exist: we bail out.
 		 */
-		errno = -ret;
-		err(1, "Bad group '%s'", arg);
+		fprintf(stderr, "Bad group '%s': %s\n", arg, strerror(-ret));
+		exit(1);
 	}
 
 	/*
 	 * From here, gid is guaranteed to be set and valid,
 	 * we add it to our supplementary gids array.
 	 */
-	*suppl_gids =
-	    realloc(*suppl_gids, sizeof(gid_t) * ++(*suppl_gids_count));
-	if (!suppl_gids)
-		err(1, "failed to allocate memory");
+	*suppl_gids = realloc(*suppl_gids,
+			      sizeof(gid_t) * ++(*suppl_gids_count));
+	if (!suppl_gids) {
+		fprintf(stderr, "failed to allocate memory.\n");
+		exit(1);
+	}
 
 	(*suppl_gids)[*suppl_gids_count - 1] = gid;
 }
@@ -135,8 +138,10 @@
 	uint64_t securebits_skip_mask;
 	char *end = NULL;
 	securebits_skip_mask = strtoull(arg, &end, 16);
-	if (*end)
-		errx(1, "Invalid securebit mask: '%s'", arg);
+	if (*end) {
+		fprintf(stderr, "Invalid securebit mask: '%s'\n", arg);
+		exit(1);
+	}
 	minijail_skip_setting_securebits(j, securebits_skip_mask);
 }
 
@@ -162,10 +167,11 @@
 					 */
 					continue;
 				}
-				err(1,
-				    "Could not get the value of the %d-th "
-				    "capability",
-				    i);
+				fprintf(stderr,
+					"Could not get the value of "
+					"the %d-th capability: %m\n",
+					i);
+				exit(1);
 			}
 			if (cap_value == CAP_SET)
 				caps |= (one << i);
@@ -174,8 +180,10 @@
 	} else {
 		char *end = NULL;
 		caps = strtoull(arg, &end, 16);
-		if (*end)
-			errx(1, "Invalid cap set: '%s'", arg);
+		if (*end) {
+			fprintf(stderr, "Invalid cap set: '%s'\n", arg);
+			exit(1);
+		}
 	}
 
 	minijail_use_caps(j, caps);
@@ -186,8 +194,10 @@
 	char *src = tokenize(&arg, ",");
 	char *dest = tokenize(&arg, ",");
 	char *flags = tokenize(&arg, ",");
-	if (!src || src[0] == '\0' || arg != NULL)
-		errx(1, "Bad binding: %s %s", src, dest);
+	if (!src || src[0] == '\0' || arg != NULL) {
+		fprintf(stderr, "Bad binding: %s %s\n", src, dest);
+		exit(1);
+	}
 	if (dest == NULL || dest[0] == '\0')
 		dest = src;
 	int writable;
@@ -195,10 +205,14 @@
 		writable = 0;
 	else if (!strcmp(flags, "1"))
 		writable = 1;
-	else
-		errx(1, "Bad value for <writable>: %s", flags);
-	if (minijail_bind(j, src, dest, writable))
-		errx(1, "minijail_bind failed");
+	else {
+		fprintf(stderr, "Bad value for <writable>: %s\n", flags);
+		exit(1);
+	}
+	if (minijail_bind(j, src, dest, writable)) {
+		fprintf(stderr, "minijail_bind failed.\n");
+		exit(1);
+	}
 }
 
 static void add_rlimit(struct minijail *j, char *arg)
@@ -207,9 +221,10 @@
 	char *cur = tokenize(&arg, ",");
 	char *max = tokenize(&arg, ",");
 	char *end;
-	if (!type || type[0] == '\0' || !cur || cur[0] == '\0' || !max ||
-	    max[0] == '\0' || arg != NULL) {
-		errx(1, "Bad rlimit '%s'", arg);
+	if (!type || type[0] == '\0' || !cur || cur[0] == '\0' ||
+	    !max || max[0] == '\0' || arg != NULL) {
+		fprintf(stderr, "Bad rlimit '%s'.\n", arg);
+		exit(1);
 	}
 	rlim_t cur_rlim;
 	rlim_t max_rlim;
@@ -218,25 +233,34 @@
 	} else {
 		end = NULL;
 		cur_rlim = strtoul(cur, &end, 0);
-		if (*end)
-			errx(1, "Bad soft limit: '%s'", cur);
+		if (*end) {
+			fprintf(stderr, "Bad soft limit: '%s'.\n", cur);
+			exit(1);
+		}
 	}
 	if (!strcmp(max, "unlimited")) {
 		max_rlim = RLIM_INFINITY;
 	} else {
 		end = NULL;
 		max_rlim = strtoul(max, &end, 0);
-		if (*end)
-			errx(1, "Bad hard limit: '%s'", max);
+		if (*end) {
+			fprintf(stderr, "Bad hard limit: '%s'.\n", max);
+			exit(1);
+		}
 	}
 
 	end = NULL;
 	int resource = parse_single_constant(type, &end);
-	if (type == end)
-		errx(1, "Bad rlimit: '%s'", type);
+	if (type == end) {
+		fprintf(stderr, "Bad rlimit: '%s'.\n", type);
+		exit(1);
+	}
 
-	if (minijail_rlimit(j, resource, cur_rlim, max_rlim))
-		errx(1, "minijail_rlimit '%s,%s,%s' failed", type, cur, max);
+	if (minijail_rlimit(j, resource, cur_rlim, max_rlim)) {
+		fprintf(stderr, "minijail_rlimit '%s,%s,%s' failed.\n", type,
+			cur, max);
+		exit(1);
+	}
 }
 
 static void add_mount(struct minijail *j, char *arg)
@@ -247,9 +271,10 @@
 	char *flags = tokenize(&arg, ",");
 	char *data = tokenize(&arg, ",");
 	char *end;
-	if (!src || src[0] == '\0' || !dest || dest[0] == '\0' || !type ||
-	    type[0] == '\0') {
-		errx(1, "Bad mount: %s %s %s", src, dest, type);
+	if (!src || src[0] == '\0' || !dest || dest[0] == '\0' ||
+	    !type || type[0] == '\0') {
+		fprintf(stderr, "Bad mount: %s %s %s\n", src, dest, type);
+		exit(1);
 	}
 
 	/*
@@ -272,12 +297,17 @@
 	} else {
 		end = NULL;
 		mountflags = parse_constant(flags, &end);
-		if (flags == end)
-			errx(1, "Bad mount flags: %s", flags);
+		if (flags == end) {
+			fprintf(stderr, "Bad mount flags: %s\n", flags);
+			exit(1);
+		}
 	}
 
-	if (minijail_mount_with_data(j, src, dest, type, mountflags, data))
-		errx(1, "minijail_mount failed");
+	if (minijail_mount_with_data(j, src, dest, type,
+				     mountflags, data)) {
+		fprintf(stderr, "minijail_mount failed.\n");
+		exit(1);
+	}
 }
 
 static char *build_idmap(id_t id, id_t lowerid)
@@ -287,7 +317,8 @@
 	ret = snprintf(idmap, IDMAP_LEN, "%d %d 1", id, lowerid);
 	if (ret < 0 || (size_t)ret >= IDMAP_LEN) {
 		free(idmap);
-		errx(1, "Could not build id map");
+		fprintf(stderr, "Could not build id map.\n");
+		exit(1);
 	}
 	return idmap;
 }
@@ -301,14 +332,20 @@
 		return 0;
 
 	caps = cap_get_proc();
-	if (!caps)
-		err(1, "Could not get process' capabilities");
+	if (!caps) {
+		fprintf(stderr, "Could not get process' capabilities: %m\n");
+		exit(1);
+	}
 
-	if (cap_get_flag(caps, CAP_SETGID, CAP_EFFECTIVE, &cap_value))
-		err(1, "Could not get the value of CAP_SETGID");
+	if (cap_get_flag(caps, CAP_SETGID, CAP_EFFECTIVE, &cap_value)) {
+		fprintf(stderr, "Could not get the value of CAP_SETGID: %m\n");
+		exit(1);
+	}
 
-	if (cap_free(caps))
-		err(1, "Could not free capabilities");
+	if (cap_free(caps)) {
+		fprintf(stderr, "Could not free capabilities: %m\n");
+		exit(1);
+	}
 
 	return cap_value == CAP_SET;
 }
@@ -329,8 +366,10 @@
 			 */
 			uidmap = build_idmap(uid, getuid());
 		}
-		if (0 != minijail_uidmap(j, uidmap))
-			errx(1, "Could not set uid map");
+		if (0 != minijail_uidmap(j, uidmap)) {
+			fprintf(stderr, "Could not set uid map.\n");
+			exit(1);
+		}
 		free(uidmap);
 	}
 	if (set_gidmap) {
@@ -354,8 +393,10 @@
 			 */
 			minijail_namespace_user_disable_setgroups(j);
 		}
-		if (0 != minijail_gidmap(j, gidmap))
-			errx(1, "Could not set gid map");
+		if (0 != minijail_gidmap(j, gidmap)) {
+			fprintf(stderr, "Could not set gid map.\n");
+			exit(1);
+		}
 		free(gidmap);
 	}
 }
@@ -363,20 +404,30 @@
 static void use_chroot(struct minijail *j, const char *path, int *chroot,
 		       int pivot_root)
 {
-	if (pivot_root)
-		errx(1, "Could not set chroot because -P was specified");
-	if (minijail_enter_chroot(j, path))
-		errx(1, "Could not set chroot");
+	if (pivot_root) {
+		fprintf(stderr, "Could not set chroot because "
+				"'-P' was specified.\n");
+		exit(1);
+	}
+	if (minijail_enter_chroot(j, path)) {
+		fprintf(stderr, "Could not set chroot.\n");
+		exit(1);
+	}
 	*chroot = 1;
 }
 
 static void use_pivot_root(struct minijail *j, const char *path,
 			   int *pivot_root, int chroot)
 {
-	if (chroot)
-		errx(1, "Could not set pivot_root because -C was specified");
-	if (minijail_enter_pivot_root(j, path))
-		errx(1, "Could not set pivot_root");
+	if (chroot) {
+		fprintf(stderr, "Could not set pivot_root because "
+				"'-C' was specified.\n");
+		exit(1);
+	}
+	if (minijail_enter_pivot_root(j, path)) {
+		fprintf(stderr, "Could not set pivot_root.\n");
+		exit(1);
+	}
 	minijail_namespace_vfs(j);
 	*pivot_root = 1;
 }
@@ -389,13 +440,19 @@
 	if (!strcmp(profile, "minimalistic-mountns") ||
 	    !strcmp(profile, "minimalistic-mountns-nodev")) {
 		minijail_namespace_vfs(j);
-		if (minijail_bind(j, "/", "/", 0))
-			errx(1, "minijail_bind(/) failed");
-		if (minijail_bind(j, "/proc", "/proc", 0))
-			errx(1, "minijail_bind(/proc) failed");
+		if (minijail_bind(j, "/", "/", 0)) {
+			fprintf(stderr, "minijail_bind(/) failed.\n");
+			exit(1);
+		}
+		if (minijail_bind(j, "/proc", "/proc", 0)) {
+			fprintf(stderr, "minijail_bind(/proc) failed.\n");
+			exit(1);
+		}
 		if (!strcmp(profile, "minimalistic-mountns")) {
-			if (minijail_bind(j, "/dev/log", "/dev/log", 0))
-				errx(1, "minijail_bind(/dev/log) failed");
+			if (minijail_bind(j, "/dev/log", "/dev/log", 0)) {
+				fprintf(stderr, "minijail_bind(/dev/log) failed.\n");
+				exit(1);
+			}
 			minijail_mount_dev(j);
 		}
 		if (!*tmp_size) {
@@ -404,8 +461,10 @@
 		}
 		minijail_remount_proc_readonly(j);
 		use_pivot_root(j, DEFAULT_PIVOT_ROOT, pivot_root, chroot);
-	} else
-		errx(1, "Unrecognized profile name '%s'", profile);
+	} else {
+		fprintf(stderr, "Unrecognized profile name '%s'\n", profile);
+		exit(1);
+	}
 }
 
 static void set_remount_mode(struct minijail *j, const char *mode)
@@ -419,25 +478,35 @@
 		msmode = MS_SLAVE;
 	else if (!strcmp(mode, "unbindable"))
 		msmode = MS_UNBINDABLE;
-	else
-		errx(1, "Unknown remount mode: '%s'", mode);
+	else {
+		fprintf(stderr, "Unknown remount mode: '%s'\n", mode);
+		exit(1);
+	}
 	minijail_remount_mode(j, msmode);
 }
 
 static void read_seccomp_filter(const char *filter_path,
 				struct sock_fprog *filter)
 {
-	attribute_cleanup_fp FILE *f = fopen(filter_path, "re");
-	if (!f)
-		err(1, "failed to open %s", filter_path);
+	FILE *f = fopen(filter_path, "re");
+	if (!f) {
+		fprintf(stderr, "failed to open %s: %m", filter_path);
+		exit(1);
+	}
 	off_t filter_size = 0;
-	if (fseeko(f, 0, SEEK_END) == -1 || (filter_size = ftello(f)) == -1)
-		err(1, "failed to get file size of %s", filter_path);
+	if (fseeko(f, 0, SEEK_END) == -1 || (filter_size = ftello(f)) == -1) {
+		fclose(f);
+		fprintf(stderr, "failed to get file size of %s: %m",
+			filter_path);
+		exit(1);
+	}
 	if (filter_size % sizeof(struct sock_filter) != 0) {
-		errx(1,
-		     "filter size (%" PRId64 ") of %s is not a multiple of"
-		     " %zu",
-		     filter_size, filter_path, sizeof(struct sock_filter));
+		fclose(f);
+		fprintf(stderr,
+			"filter size (%" PRId64
+			") of %s is not a multiple of %zu: %m",
+			filter_size, filter_path, sizeof(struct sock_filter));
+		exit(1);
 	}
 	rewind(f);
 
@@ -445,195 +514,116 @@
 	filter->filter = xmalloc(filter_size);
 	if (fread(filter->filter, sizeof(struct sock_filter), filter->len, f) !=
 	    filter->len) {
-		err(1, "failed read %s", filter_path);
+		fclose(f);
+		fprintf(stderr, "failed read %s: %m", filter_path);
+		exit(1);
 	}
+	fclose(f);
 }
 
-/*
- * Long options use values starting at 0x100 so that they're out of range of
- * bytes which is how command line options are processed.  Practically speaking,
- * we could get by with the (7-bit) ASCII range, but UTF-8 codepoints would be a
- * bit confusing, and honestly there's no reason to "optimize" here.
- *
- * The long enum values are internal to this file and can freely change at any
- * time without breaking anything.  Please keep alphabetically ordered.
- */
-enum {
-	/* Everything after this point only have long options. */
-	LONG_OPTION_BASE = 0x100,
-	OPT_ADD_SUPPL_GROUP,
-	OPT_ALLOW_SPECULATIVE_EXECUTION,
-	OPT_AMBIENT,
-	OPT_CONFIG,
-	OPT_ENV_ADD,
-	OPT_ENV_RESET,
-	OPT_LOGGING,
-	OPT_PRELOAD_LIBRARY,
-	OPT_PROFILE,
-	OPT_SECCOMP_BPF_BINARY,
-	OPT_UTS,
-};
-
-/*
- * NB: When adding new options, prefer long-option only.  Add a short option
- * only if its meaning is intuitive/obvious at a glance.
- *
- * Keep this sorted.
- */
-static const char optstring[] =
-    "+a:b:c:de::f:g:hik:lm::nprst::u:vwyzB:C:GHIK::LM::NP:R:S:T:UV:Y";
-
-static const struct option long_options[] = {
-    {"help", no_argument, 0, 'h'},
-    {"mount-dev", no_argument, 0, 'd'},
-    {"ambient", no_argument, 0, OPT_AMBIENT},
-    {"uts", optional_argument, 0, OPT_UTS},
-    {"logging", required_argument, 0, OPT_LOGGING},
-    {"profile", required_argument, 0, OPT_PROFILE},
-    {"preload-library", required_argument, 0, OPT_PRELOAD_LIBRARY},
-    {"seccomp-bpf-binary", required_argument, 0, OPT_SECCOMP_BPF_BINARY},
-    {"add-suppl-group", required_argument, 0, OPT_ADD_SUPPL_GROUP},
-    {"allow-speculative-execution", no_argument, 0,
-     OPT_ALLOW_SPECULATIVE_EXECUTION},
-    {"config", required_argument, 0, OPT_CONFIG},
-    {"env-add", required_argument, 0, OPT_ENV_ADD},
-    {"env-reset", no_argument, 0, OPT_ENV_RESET},
-    {"mount", required_argument, 0, 'k'},
-    {"bind-mount", required_argument, 0, 'b'},
-    {"ns-mount", no_argument, 0, 'v'},
-    {0, 0, 0, 0},
-};
-
-/*
- * Pull the usage string out into the top-level to help with long-lines.  We
- * want the output to be wrapped at 80 cols when it's shown to the user in the
- * terminal, but we don't want the source wrapped to 80 cols because that will
- * effectively make terminal output wrap to much lower levels (like <70).
- */
-/* clang-format off */
-static const char help_text[] =
-"Account (user/group) options:\n"
-"  -u <user>    Change uid to <user>.\n"
-"  -g <group>   Change gid to <group>.\n"
-"  -G           Inherit supplementary groups from new uid.\n"
-"               Incompatible with -y or --add-suppl-group.\n"
-"  -y           Keep original uid's supplementary groups.\n"
-"               Incompatible with -G or --add-suppl-group.\n"
-"  --add-suppl-group <group>\n"
-"               Add <group> to the proccess' supplementary groups.\n"
-"               Can be specified multiple times to add several groups.\n"
-"               Incompatible with -y or -G.\n"
-"\n"
-"Mount/path options:\n"
-"  -b <src[,dst[,writable]]>, --bind-mount <...>\n"
-"               Bind <src> to <dst>.\n"
-"  -k <src,dst,fstype[,flags[,data]]>, --mount <...>\n"
-"               Mount <src> at <dst>. <flags> and <data> can be specified as\n"
-"               in mount(2). Multiple instances allowed.\n"
-"  -K           Do not change share mode of any existing mounts.\n"
-"  -K<mode>     Mark all existing mounts as <mode> instead of MS_PRIVATE.\n"
-"  -r           Remount /proc read-only (implies -v).\n"
-"  -d, --mount-dev\n"
-"               Create a new /dev with a minimal set of device nodes\n"
-"               (implies -v). See minijail0(1) for exact list.\n"
-"  -t[size]     Mount tmpfs at /tmp (implies -v).\n"
-"               Optional argument specifies size (default \"64M\").\n"
-"  -C <dir>     chroot(2) to <dir>. Incompatible with -P.\n"
-"  -P <dir>     pivot_root(2) to <dir> (implies -v). Incompatible with -C.\n"
-"\n"
-"Namespace options:\n"
-"  -N           Enter a new cgroup namespace.\n"
-"  -l           Enter new IPC namespace.\n"
-"  -v, --ns-mount\n"
-"               Enter new mount namespace.\n"
-"  -V <file>    Enter specified mount namespace.\n"
-"  -e[file]     Enter new network namespace, or existing |file| if provided.\n"
-"  -p           Enter new pid namespace (implies -vr).\n"
-"  -I           Run as init (pid 1) inside a new pid namespace (implies -p).\n"
-"  -U           Enter new user namespace (implies -p).\n"
-"  -m[<uid> <loweruid> <count>]\n"
-"               Set the uid map of a user namespace (implies -pU).\n"
-"               Same arguments as newuidmap(1); mappings are comma separated.\n"
-"               With no mapping, map the current uid to root.\n"
-"               Incompatible with -b without the 'writable' option.\n"
-"  -M[<gid> <lowergid> <count>]\n"
-"               Set the gid map of a user namespace (implies -pU).\n"
-"               Same arguments as newgidmap(1); mappings are comma separated.\n"
-"               With no mapping, map the current gid to root.\n"
-"               Incompatible with -b without the 'writable' option.\n"
-"  --uts[=name] Enter a new UTS namespace (and set hostname).\n"
-"\n"
-"Seccomp options:\n"
-"  -S <file>    Set seccomp filter using <file>.\n"
-"               E.g., '-S /usr/share/filters/<prog>.$(uname -m)'.\n"
-"               Requires -n when not running as root.\n"
-"  --seccomp-bpf-binary=<f>\n"
-"               Set a pre-compiled seccomp filter using <f>.\n"
-"               E.g., '-S /usr/share/filters/<prog>.$(uname -m).bpf'.\n"
-"               Requires -n when not running as root.\n"
-"               The user is responsible for ensuring that the binary\n"
-"               was compiled for the correct architecture / kernel version.\n"
-"  -L           Report blocked syscalls when using seccomp filter.\n"
-"               If the kernel does not support SECCOMP_RET_LOG, some syscalls\n"
-"               will automatically be allowed (see below).\n"
-"  -Y           Synchronize seccomp filters across thread group.\n"
-"  -a <table>   Use alternate syscall table <table>.\n"
-"  -s           Use seccomp mode 1 (not the same as -S).\n"
-"\n"
-"Other options:\n"
-"  --config <file>\n"
-"               Load the Minijail configuration file <file>.\n"
-"               If used, must be specified ahead of other options.\n"
-"  --profile <p>\n"
-"               Configure minijail0 to run with the <p> sandboxing profile,\n"
-"               which is a convenient way to express multiple flags\n"
-"               that are typically used together.\n"
-"               See the minijail0(1) man page for the full list.\n"
-"  -n           Set no_new_privs. See prctl(2) for details.\n"
-"  -c <caps>    Restrict caps to <caps>.\n"
-"  --ambient    Raise ambient capabilities. Requires -c.\n"
-"  -B <mask>    Skip setting <mask> securebits when restricting caps (-c).\n"
-"               By default, SECURE_NOROOT, SECURE_NO_SETUID_FIXUP, and \n"
-"               SECURE_KEEP_CAPS (with their respective locks) are set.\n"
-"  -f <file>    Write the pid of the jailed process to <file>.\n"
-"  -i           Exit immediately after fork(2); i.e. background the program.\n"
-"  -z           Don't forward signals to jailed process.\n"
-"  -R <type,cur,max>\n"
-"               Call setrlimit(3); can be specified multiple times.\n"
-"  -T <type>    Assume <program> is a <type> ELF binary;\n"
-"               <type> may be 'static' or 'dynamic'.\n"
-"               This will avoid accessing <program> binary before execve(2).\n"
-"               Type 'static' will avoid preload hooking.\n"
-"  -w           Create and join a new anonymous session keyring.\n"
-"  --env-reset  Clear the current environment instead of having <program>\n"
-"               inherit the active environment. Often used to start <program>\n"
-"               with a minimal sanitized environment.\n"
-"  --env-add <NAME=value>\n"
-"               Sets the specified environment variable <NAME>\n"
-"               in the <program>'s environment before starting it.\n"
-"\n"
-"Uncommon options:\n"
-"  --allow-speculative-execution\n"
-"               Allow speculative execution by disabling mitigations.\n"
-"  --preload-library=<file>\n"
-"               Overrides the path to \"" PRELOADPATH "\".\n"
-"               This is only really useful for local testing.\n"
-"  --logging=<output>\n"
-"               Set the logging system output: 'auto' (default),\n"
-"               'syslog', or 'stderr'.\n"
-"  -h           Help (this message).\n"
-"  -H           Seccomp filter help message.\n";
-/* clang-format on */
-
 static void usage(const char *progn)
 {
-	printf("Usage: %s [options] [--] <program> [args...]\n\n%s", progn,
-	       help_text);
+	size_t i;
+	/* clang-format off */
+	printf("Usage: %s [-dGhHiIKlLnNprRstUvyYz]\n"
+	       "  [-a <table>]\n"
+	       "  [-b <src>[,[dest][,<writeable>]]] [-k <src>,<dest>,<type>[,<flags>[,<data>]]]\n"
+	       "  [-c <caps>] [-C <dir>] [-P <dir>] [-e[file]] [-f <file>] [-g <group>]\n"
+	       "  [-m[<uid> <loweruid> <count>]*] [-M[<gid> <lowergid> <count>]*] [--profile <name>]\n"
+	       "  [-R <type,cur,max>] [-S <file>] [-t[size]] [-T <type>] [-u <user>] [-V <file>]\n"
+	       "  <program> [args...]\n"
+	       "  -a <table>:   Use alternate syscall table <table>.\n"
+	       "  -b <...>:     Bind <src> to <dest> in chroot.\n"
+	       "                Multiple instances allowed.\n"
+	       "  -B <mask>:    Skip setting securebits in <mask> when restricting capabilities (-c).\n"
+	       "                By default, SECURE_NOROOT, SECURE_NO_SETUID_FIXUP, and \n"
+	       "                SECURE_KEEP_CAPS (together with their respective locks) are set.\n"
+	       "                There are eight securebits in total.\n"
+	       "  -k <...>:     Mount <src> at <dest> in chroot.\n"
+	       "                <flags> and <data> can be specified as in mount(2).\n"
+	       "                Multiple instances allowed.\n"
+	       "  -c <caps>:    Restrict caps to <caps>.\n"
+	       "  -C <dir>:     chroot(2) to <dir>.\n"
+	       "                Not compatible with -P.\n"
+	       "  -P <dir>:     pivot_root(2) to <dir> (implies -v).\n"
+	       "                Not compatible with -C.\n"
+	       "  --mount-dev,  Create a new /dev with a minimal set of device nodes (implies -v).\n"
+	       "           -d:  See the minijail0(1) man page for the exact set.\n"
+	       "  -e[file]:     Enter new network namespace, or existing one if |file| is provided.\n"
+	       "  -f <file>:    Write the pid of the jailed process to <file>.\n"
+	       "  -g <group>:   Change gid to <group>.\n"
+	       "  -G:           Inherit supplementary groups from new uid.\n"
+	       "                Not compatible with -y or --add-suppl-group.\n"
+	       "  -y:           Keep original uid's supplementary groups.\n"
+	       "                Not compatible with -G or --add-suppl-group.\n"
+	       "  --add-suppl-group <g>:Add <g> to the proccess' supplementary groups,\n"
+	       "                can be specified multiple times to add several groups.\n"
+	       "                Not compatible with -y or -G.\n"
+	       "  -h:           Help (this message).\n"
+	       "  -H:           Seccomp filter help message.\n"
+	       "  -i:           Exit immediately after fork(2). The jailed process will run\n"
+	       "                in the background.\n"
+	       "  -I:           Run <program> as init (pid 1) inside a new pid namespace (implies -p).\n"
+	       "  -K:           Do not change share mode of any existing mounts.\n"
+	       "  -K<mode>:     Mark all existing mounts as <mode> instead of MS_PRIVATE.\n"
+	       "  -l:           Enter new IPC namespace.\n"
+	       "  -L:           Report blocked syscalls when using seccomp filter.\n"
+	       "                If the kernel does not support SECCOMP_RET_LOG,\n"
+	       "                forces the following syscalls to be allowed:\n"
+	       "                  ", progn);
+	/* clang-format on */
+	for (i = 0; i < log_syscalls_len; i++)
+		printf("%s ", log_syscalls[i]);
 
-	printf("\nsyscalls allowed when logging (-L):\n ");
-	for (size_t i = 0; i < log_syscalls_len; ++i)
-		printf(" %s", log_syscalls[i]);
-	printf("\n");
+	/* clang-format off */
+	printf("\n"
+	       "  -m[map]:      Set the uid map of a user namespace (implies -pU).\n"
+	       "                Same arguments as newuidmap(1), multiple mappings should be separated by ',' (comma).\n"
+	       "                With no mapping, map the current uid to root inside the user namespace.\n"
+	       "                Not compatible with -b without the 'writable' option.\n"
+	       "  -M[map]:      Set the gid map of a user namespace (implies -pU).\n"
+	       "                Same arguments as newgidmap(1), multiple mappings should be separated by ',' (comma).\n"
+	       "                With no mapping, map the current gid to root inside the user namespace.\n"
+	       "                Not compatible with -b without the 'writable' option.\n"
+	       "  -n:           Set no_new_privs.\n"
+	       "  -N:           Enter a new cgroup namespace.\n"
+	       "  -p:           Enter new pid namespace (implies -vr).\n"
+	       "  -r:           Remount /proc read-only (implies -v).\n"
+	       "  -R:           Set rlimits, can be specified multiple times.\n"
+	       "  -s:           Use seccomp mode 1 (not the same as -S).\n"
+	       "  -S <file>:    Set seccomp filter using <file>.\n"
+	       "                E.g., '-S /usr/share/filters/<prog>.$(uname -m)'.\n"
+	       "                Requires -n when not running as root.\n"
+	       "  -t[size]:     Mount tmpfs at /tmp (implies -v).\n"
+	       "                Optional argument specifies size (default \"64M\").\n"
+	       "  -T <type>:    Assume <program> is a <type> ELF binary; <type> can be 'static' or 'dynamic'.\n"
+	       "                This will avoid accessing <program> binary before execve(2).\n"
+	       "                Type 'static' will avoid preload hooking.\n"
+	       "  -u <user>:    Change uid to <user>.\n"
+	       "  -U:           Enter new user namespace (implies -p).\n"
+	       "  -v:           Enter new mount namespace.\n"
+	       "  -V <file>:    Enter specified mount namespace.\n"
+	       "  -w:           Create and join a new anonymous session keyring.\n"
+	       "  -Y:           Synchronize seccomp filters across thread group.\n"
+	       "  -z:           Don't forward signals to jailed process.\n"
+	       "  --ambient:    Raise ambient capabilities. Requires -c.\n"
+	       "  --uts[=name]: Enter a new UTS namespace (and set hostname).\n"
+	       "  --logging=<s>:Use <s> as the logging system.\n"
+	       "                <s> must be 'auto' (default), 'syslog', or 'stderr'.\n"
+	       "  --profile <p>:Configure minijail0 to run with the <p> sandboxing profile,\n"
+	       "                which is a convenient way to express multiple flags\n"
+	       "                that are typically used together.\n"
+	       "                See the minijail0(1) man page for the full list.\n"
+	       "  --preload-library=<f>:Overrides the path to \"" PRELOADPATH "\".\n"
+	       "                This is only really useful for local testing.\n"
+	       "  --seccomp-bpf-binary=<f>:Set a pre-compiled seccomp filter using <f>.\n"
+	       "                E.g., '-S /usr/share/filters/<prog>.$(uname -m).bpf'.\n"
+	       "                Requires -n when not running as root.\n"
+	       "                The user is responsible for ensuring that the binary\n"
+	       "                was compiled for the correct architecture / kernel version.\n"
+	       "  --allow-speculative-execution:Allow speculative execution and disable\n"
+	       "                mitigations for speculative execution attacks.\n");
+	/* clang-format on */
 }
 
 static void seccomp_filter_usage(const char *progn)
@@ -647,98 +637,12 @@
 	printf("\nSee minijail0(5) for example policies.\n");
 }
 
-/*
- * Return the next unconsumed option char/value parsed from
- * |*conf_entry_list|. |optarg| is updated to point to an argument from
- * the entry value. If all options have been consumed, |*conf_entry_list|
- * will be freed and -1 will be returned.
- */
-static int getopt_from_conf(const struct option *longopts,
-			    struct config_entry_list **conf_entry_list,
-			    size_t *conf_index)
-{
-	int opt = -1;
-	/* If we've consumed all the options in the this config, reset it. */
-	if (*conf_index >= (*conf_entry_list)->num_entries) {
-		free_config_entry_list(*conf_entry_list);
-		*conf_entry_list = NULL;
-		*conf_index = 0;
-		return opt;
-	}
-
-	struct config_entry *entry = &(*conf_entry_list)->entries[*conf_index];
-	/* Look up a matching long option. */
-	size_t i = 0;
-	const struct option *curr_opt;
-	for (curr_opt = &longopts[0]; curr_opt->name != NULL;
-	     curr_opt = &longopts[++i])
-		if (strcmp(entry->key, curr_opt->name) == 0)
-			break;
-	if (curr_opt->name == NULL) {
-		errx(1,
-		     "Unable to recognize '%s' as Minijail conf entry key, "
-		     "please refer to minijail0(5) for syntax and examples.",
-		     entry->key);
-	}
-	opt = curr_opt->val;
-	optarg = (char *)entry->value;
-	(*conf_index)++;
-	return opt;
-}
-
-/*
- * Similar to getopt(3), return the next option char/value as it
- * parses through the CLI argument list. Config entries in
- * |*conf_entry_list| will be parsed with precendences over cli options.
- * Same as getopt(3), |optarg| is pointing to the option argument.
- */
-static int getopt_conf_or_cli(int argc, char *const argv[],
-			      struct config_entry_list **conf_entry_list,
-			      size_t *conf_index)
-{
-	int opt = -1;
-	if (*conf_entry_list != NULL)
-		opt =
-		    getopt_from_conf(long_options, conf_entry_list, conf_index);
-	if (opt == -1)
-		opt = getopt_long(argc, argv, optstring, long_options, NULL);
-	return opt;
-}
-
-static void set_child_env(char ***envp, char *arg, char *const environ[])
-{
-	/* We expect VAR=value format for arg. */
-	char *delim = strchr(arg, '=');
-	if (!delim) {
-		errx(1, "Expected an argument of the "
-		        "form VAR=value (got '%s')", arg);
-	}
-	*delim = '\0';
-	const char *env_value = delim + 1;
-	if (!*envp) {
-		/*
-		 * We got our first --env-add. Initialize *envp by
-		 * copying our current env to the future child env.
-		 */
-		*envp = minijail_copy_env(environ);
-		if (!*envp)
-			err(1, "Failed to allocate memory.");
-	}
-	if (minijail_setenv(envp, arg, env_value, 1))
-		err(1, "minijail_setenv() failed.");
-}
-
 int parse_args(struct minijail *j, int argc, char *const argv[],
-	       char *const environ[], int *exit_immediately,
-	       ElfType *elftype, const char **preload_path,
-	       char ***envp)
+	       int *exit_immediately, ElfType *elftype,
+	       const char **preload_path)
 {
-	enum seccomp_type { None, Strict, Filter, BpfBinaryFilter };
-	enum seccomp_type seccomp = None;
 	int opt;
-	int use_seccomp_filter = 0;
-	int use_seccomp_filter_binary = 0;
-	int use_seccomp_log = 0;
+	int use_seccomp_filter = 0, use_seccomp_filter_binary = 0;
 	int forward = 1;
 	int binding = 0;
 	int chroot = 0, pivot_root = 0;
@@ -746,6 +650,7 @@
 	const char *remount_mode = NULL;
 	int inherit_suppl_gids = 0, keep_suppl_gids = 0;
 	int caps = 0, ambient_caps = 0;
+	int seccomp = -1;
 	bool use_uid = false, use_gid = false;
 	uid_t uid = 0;
 	gid_t gid = 0;
@@ -756,21 +661,43 @@
 	size_t tmp_size = 0;
 	const char *filter_path = NULL;
 	int log_to_stderr = -1;
-	struct config_entry_list *conf_entry_list = NULL;
-	size_t conf_index = 0;
 
-	while ((opt = getopt_conf_or_cli(argc, argv, &conf_entry_list,
-					 &conf_index)) != -1) {
+	const char *optstring =
+	    "+u:g:sS:c:C:P:b:B:V:f:m::M::k:a:e::R:T:vrGhHinNplLt::IUK::wyYzd";
+	/* clang-format off */
+	const struct option long_options[] = {
+		{"help", no_argument, 0, 'h'},
+		{"mount-dev", no_argument, 0, 'd'},
+		{"ambient", no_argument, 0, 128},
+		{"uts", optional_argument, 0, 129},
+		{"logging", required_argument, 0, 130},
+		{"profile", required_argument, 0, 131},
+		{"preload-library", required_argument, 0, 132},
+		{"seccomp-bpf-binary", required_argument, 0, 133},
+		{"add-suppl-group", required_argument, 0, 134},
+		{"allow-speculative-execution", no_argument, 0, 135},
+		{0, 0, 0, 0},
+	};
+	/* clang-format on */
+
+	while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) !=
+	       -1) {
 		switch (opt) {
 		case 'u':
-			if (use_uid)
-				errx(1, "-u provided multiple times.");
+			if (use_uid) {
+				fprintf(stderr,
+					"-u provided multiple times.\n");
+				exit(1);
+			}
 			use_uid = true;
 			set_user(j, optarg, &uid, &gid);
 			break;
 		case 'g':
-			if (use_gid)
-				errx(1, "-g provided multiple times.");
+			if (use_gid) {
+				fprintf(stderr,
+					"-g provided multiple times.\n");
+				exit(1);
+			}
 			use_gid = true;
 			set_group(j, optarg, &gid);
 			break;
@@ -778,19 +705,23 @@
 			minijail_no_new_privs(j);
 			break;
 		case 's':
-			if (seccomp != None && seccomp != Strict) {
-				errx(1, "Do not use -s, -S, or "
-					"--seccomp-bpf-binary together");
+			if (seccomp != -1 && seccomp != 1) {
+				fprintf(stderr,
+					"Do not use -s, -S, or "
+					"--seccomp-bpf-binary together.\n");
+				exit(1);
 			}
-			seccomp = Strict;
+			seccomp = 1;
 			minijail_use_seccomp(j);
 			break;
 		case 'S':
-			if (seccomp != None && seccomp != Filter) {
-				errx(1, "Do not use -s, -S, or "
-					"--seccomp-bpf-binary together");
+			if (seccomp != -1 && seccomp != 2) {
+				fprintf(stderr,
+					"Do not use -s, -S, or "
+					"--seccomp-bpf-binary together.\n");
+				exit(1);
 			}
-			seccomp = Filter;
+			seccomp = 2;
 			minijail_use_seccomp_filter(j);
 			filter_path = optarg;
 			use_seccomp_filter = 1;
@@ -799,11 +730,6 @@
 			minijail_namespace_ipc(j);
 			break;
 		case 'L':
-			if (seccomp == BpfBinaryFilter) {
-				errx(1, "-L does not work with "
-					"--seccomp-bpf-binary");
-			}
-			use_seccomp_log = 1;
 			minijail_log_seccomp_filter_failures(j);
 			break;
 		case 'b':
@@ -831,8 +757,11 @@
 			use_pivot_root(j, optarg, &pivot_root, chroot);
 			break;
 		case 'f':
-			if (0 != minijail_write_pid_file(j, optarg))
-				errx(1, "Could not prepare pid file path");
+			if (0 != minijail_write_pid_file(j, optarg)) {
+				fprintf(stderr,
+					"Could not prepare pid file path.\n");
+				exit(1);
+			}
 			break;
 		case 't':
 			minijail_namespace_vfs(j);
@@ -845,7 +774,8 @@
 			}
 			if (optarg != NULL &&
 			    0 != parse_size(&tmp_size, optarg)) {
-				errx(1, "Invalid /tmp tmpfs size");
+				fprintf(stderr, "Invalid /tmp tmpfs size.\n");
+				exit(1);
 			}
 			break;
 		case 'v':
@@ -890,14 +820,20 @@
 			minijail_remount_proc_readonly(j);
 			break;
 		case 'G':
-			if (keep_suppl_gids)
-				errx(1, "-y and -G are not compatible");
+			if (keep_suppl_gids) {
+				fprintf(stderr,
+					"-y and -G are not compatible.\n");
+				exit(1);
+			}
 			minijail_inherit_usergroups(j);
 			inherit_suppl_gids = 1;
 			break;
 		case 'y':
-			if (inherit_suppl_gids)
-				errx(1, "-y and -G are not compatible");
+			if (inherit_suppl_gids) {
+				fprintf(stderr,
+					"-y and -G are not compatible.\n");
+				exit(1);
+			}
 			minijail_keep_supplementary_gids(j);
 			keep_suppl_gids = 1;
 			break;
@@ -946,8 +882,11 @@
 				gidmap = xstrdup(optarg);
 			break;
 		case 'a':
-			if (0 != minijail_use_alt_syscall(j, optarg))
-				errx(1, "Could not set alt-syscall table");
+			if (0 != minijail_use_alt_syscall(j, optarg)) {
+				fprintf(stderr,
+					"Could not set alt-syscall table.\n");
+				exit(1);
+			}
 			break;
 		case 'R':
 			add_rlimit(j, optarg);
@@ -958,8 +897,9 @@
 			else if (!strcmp(optarg, "dynamic"))
 				*elftype = ELFDYNAMIC;
 			else {
-				errx(1, "ELF type must be 'static' or "
-					"'dynamic'");
+				fprintf(stderr, "ELF type must be 'static' or "
+						"'dynamic'.\n");
+				exit(1);
 			}
 			break;
 		case 'w':
@@ -976,125 +916,53 @@
 			minijail_mount_dev(j);
 			break;
 		/* Long options. */
-		case OPT_AMBIENT:
+		case 128: /* Ambient caps. */
 			ambient_caps = 1;
 			minijail_set_ambient_caps(j);
 			break;
-		case OPT_UTS:
+		case 129: /* UTS/hostname namespace. */
 			minijail_namespace_uts(j);
 			if (optarg)
 				minijail_namespace_set_hostname(j, optarg);
 			break;
-		case OPT_LOGGING:
-			if (!strcmp(optarg, "auto"))
+		case 130: /* Logging. */
+			if (!strcmp(optarg, "auto")) {
 				log_to_stderr = -1;
-			else if (!strcmp(optarg, "syslog"))
+			} else if (!strcmp(optarg, "syslog")) {
 				log_to_stderr = 0;
-			else if (!strcmp(optarg, "stderr"))
+			} else if (!strcmp(optarg, "stderr")) {
 				log_to_stderr = 1;
-			else
-				errx(1,
-				     "--logger must be 'syslog' or 'stderr'");
+			} else {
+				fprintf(stderr, "--logger must be 'syslog' or "
+						"'stderr'.\n");
+				exit(1);
+			}
 			break;
-		case OPT_PROFILE:
+		case 131: /* Profile */
 			use_profile(j, optarg, &pivot_root, chroot, &tmp_size);
 			break;
-		case OPT_PRELOAD_LIBRARY:
+		case 132: /* PRELOADPATH */
 			*preload_path = optarg;
 			break;
-		case OPT_SECCOMP_BPF_BINARY:
-			if (seccomp != None && seccomp != BpfBinaryFilter) {
-				errx(1, "Do not use -s, -S, or "
-					"--seccomp-bpf-binary together");
+		case 133: /* seccomp-bpf binary. */
+			if (seccomp != -1 && seccomp != 3) {
+				fprintf(stderr,
+					"Do not use -s, -S, or "
+					"--seccomp-bpf-binary together.\n");
+				exit(1);
 			}
-			if (use_seccomp_log == 1)
-				errx(1, "-L does not work with "
-					"--seccomp-bpf-binary");
-			seccomp = BpfBinaryFilter;
+			seccomp = 3;
 			minijail_use_seccomp_filter(j);
 			filter_path = optarg;
 			use_seccomp_filter_binary = 1;
 			break;
-		case OPT_ADD_SUPPL_GROUP:
-			suppl_group_add(&suppl_gids_count, &suppl_gids, optarg);
+		case 134:
+			suppl_group_add(&suppl_gids_count, &suppl_gids,
+			                optarg);
 			break;
-		case OPT_ALLOW_SPECULATIVE_EXECUTION:
+		case 135:
 			minijail_set_seccomp_filter_allow_speculation(j);
 			break;
-		case OPT_CONFIG: {
-			if (conf_entry_list != NULL) {
-				errx(1, "Nested config file specification is "
-					"not allowed.");
-			}
-			conf_entry_list = new_config_entry_list();
-			conf_index = 0;
-#if defined(BLOCK_NOEXEC_CONF)
-			/*
-			 * Check the conf file is in a exec mount.
-			 * With a W^X invariant, it excludes writable
-			 * mounts.
-			 */
-			struct statfs conf_statfs;
-			if (statfs(optarg, &conf_statfs) != 0)
-				err(1, "statfs(%s) failed.", optarg);
-			if ((conf_statfs.f_flags & MS_NOEXEC) != 0)
-				errx(1,
-				     "Conf file must be in a exec "
-				     "mount: %s",
-				     optarg);
-#endif
-#if defined(ENFORCE_ROOTFS_CONF)
-			/* Make sure the conf file is in the same device as the
-			 * rootfs. */
-			struct stat root_stat;
-			struct stat conf_stat;
-			if (stat("/", &root_stat) != 0)
-				err(1, "stat(/) failed.");
-			if (stat(optarg, &conf_stat) != 0)
-				err(1, "stat(%s) failed.", optarg);
-			if (root_stat.st_dev != conf_stat.st_dev)
-				errx(1, "Conf file must be in the rootfs.");
-#endif
-			attribute_cleanup_fp FILE *config_file =
-			    fopen(optarg, "re");
-			if (!config_file)
-				err(1, "Failed to open %s", optarg);
-			if (!parse_config_file(config_file, conf_entry_list)) {
-				errx(
-				    1,
-				    "Unable to parse %s as Minijail conf file, "
-				    "please refer to minijail0(5) for syntax "
-				    "and examples.",
-				    optarg);
-			}
-			break;
-		}
-		case OPT_ENV_ADD:
-			/*
-			 * We either copy our current env to the child env
-			 * then add the requested envvar to it, or just
-			 * add the requested envvar to the already existing
-			 * envp.
-			 */
-			set_child_env(envp, optarg, environ);
-			break;
-		case OPT_ENV_RESET:
-			if (*envp && *envp != environ) {
-				/*
-				 * We already started to initialize the future
-				 * child env, because we got some --env-add
-				 * earlier on the command-line, so first,
-				 * free the memory we allocated.
-				 * If |*envp| happens to point to |environ|,
-				 * don't attempt to free it.
-				 */
-				minijail_free_env(*envp);
-			}
-			/* Allocate an empty environment for the child. */
-			*envp = calloc(1, sizeof(char *));
-			if (!*envp)
-				err(1, "Failed to allocate memory.");
-			break;
 		default:
 			usage(argv[0]);
 			exit(opt == 'h' ? 0 : 1);
@@ -1112,7 +980,8 @@
 		 */
 		if (0 !=
 		    minijail_preserve_fd(j, STDERR_FILENO, STDERR_FILENO)) {
-			errx(1, "Could not preserve stderr");
+			fprintf(stderr, "Could not preserve stderr.\n");
+			exit(1);
 		}
 	}
 
@@ -1124,8 +993,9 @@
 
 	/* Can only set ambient caps when using regular caps. */
 	if (ambient_caps && !caps) {
-		errx(1, "Can't set ambient capabilities (--ambient) "
-			"without actually using capabilities (-c)");
+		fprintf(stderr, "Can't set ambient capabilities (--ambient) "
+				"without actually using capabilities (-c).\n");
+		exit(1);
 	}
 
 	/* Set up signal handlers in minijail unless asked not to. */
@@ -1137,8 +1007,9 @@
 	 * a new mount namespace.
 	 */
 	if (binding && !(chroot || pivot_root || mount_ns)) {
-		errx(1, "Bind mounts require a chroot, pivot_root, or "
-			" new mount namespace");
+		fprintf(stderr, "Bind mounts require a chroot, pivot_root, or "
+				" new mount namespace.\n");
+		exit(1);
 	}
 
 	/*
@@ -1146,10 +1017,11 @@
 	 * that's set there is no need for the -K/-K<mode> flags.
 	 */
 	if (change_remount && !mount_ns) {
-		errx(1, "No need to use -K (skip remounting '/') or "
-			"-K<mode> (remount '/' as <mode>) "
-			"without -v (new mount namespace).\n"
-			"Do you need to add '-v' explicitly?");
+		fprintf(stderr, "No need to use -K (skip remounting '/') or "
+				"-K<mode> (remount '/' as <mode>)\n"
+				"without -v (new mount namespace).\n"
+				"Do you need to add '-v' explicitly?\n");
+		exit(1);
 	}
 
 	/* Configure the remount flag here to avoid having -v override it. */
@@ -1167,7 +1039,7 @@
 	 */
 	if (suppl_gids_count) {
 		minijail_set_supplementary_gids(j, suppl_gids_count,
-						suppl_gids);
+		                                suppl_gids);
 		free(suppl_gids);
 	}
 
@@ -1189,16 +1061,6 @@
 		minijail_mount_tmp_size(j, tmp_size);
 
 	/*
-	 * Copy our current env to the child if its |*envp| has not
-	 * already been initialized from --env-(reset|add) usage.
-	 */
-	if (!*envp) {
-		*envp = minijail_copy_env(environ);
-		if (!*envp)
-			err(1, "Failed to allocate memory.");
-	}
-
-	/*
 	 * There should be at least one additional unparsed argument: the
 	 * executable name.
 	 */
@@ -1217,8 +1079,10 @@
 
 		/* Check that we can access the target program. */
 		if (access(program_path, X_OK)) {
-			errx(1, "Target program '%s' is not accessible",
-			     argv[optind]);
+			fprintf(stderr,
+				"Target program '%s' is not accessible.\n",
+				argv[optind]);
+			exit(1);
 		}
 
 		/* Check if target is statically or dynamically linked. */
@@ -1232,9 +1096,11 @@
 	 * execve(2).
 	 */
 	if (caps && *elftype == ELFSTATIC && !ambient_caps) {
-		errx(1, "Can't run statically-linked binaries with capabilities"
-			" (-c) without also setting ambient capabilities. "
-			"Try passing --ambient.");
+		fprintf(stderr, "Can't run statically-linked binaries with "
+				"capabilities (-c) without also setting "
+				"ambient capabilities. Try passing "
+				"--ambient.\n");
+		exit(1);
 	}
 
 	return optind;
diff --git a/minijail0_cli.h b/minijail0_cli.h
index cd504b3..583c763 100644
--- a/minijail0_cli.h
+++ b/minijail0_cli.h
@@ -17,9 +17,8 @@
 struct minijail;
 
 int parse_args(struct minijail *j, int argc, char *const argv[],
-	       char *const environ[], int *exit_immediately,
-	       ElfType *elftype, const char **preload_path,
-	       char ***envp);
+	       int *exit_immediately, ElfType *elftype,
+	       const char **preload_path);
 
 #ifdef __cplusplus
 }; /* extern "C" */
diff --git a/minijail0_cli_unittest.cc b/minijail0_cli_unittest.cc
index 7b20ecd..76ff37f 100644
--- a/minijail0_cli_unittest.cc
+++ b/minijail0_cli_unittest.cc
@@ -14,10 +14,8 @@
 
 #include <gtest/gtest.h>
 
-#include "config_parser.h"
 #include "libminijail.h"
 #include "minijail0_cli.h"
-#include "test_util.h"
 
 namespace {
 
@@ -60,10 +58,9 @@
     testing::internal::CaptureStdout();
 
     const char* preload_path = PRELOADPATH;
-    char **envp = NULL;
     int ret =
         parse_args(j, pargv.size(), const_cast<char* const*>(pargv.data()),
-                   NULL, exit_immediately, elftype, &preload_path, &envp);
+                   exit_immediately, elftype, &preload_path);
     testing::internal::GetCapturedStdout();
 
     minijail_destroy(j);
@@ -529,80 +526,3 @@
   argv[1] = "-Kfoo";
   ASSERT_EXIT(parse_args_(argv), testing::ExitedWithCode(1), "");
 }
-
-TEST_F(CliTest, invalid_L_combo) {
-  std::vector<std::string> argv = {"", "", "", "/bin/sh"};
-
-  // Cannot call minijail0 with -L and a pre-compiled seccomp policy.
-  argv[0] = "-L";
-  argv[1] = "--seccomp-bpf-binary";
-  argv[2] = "source";
-  ASSERT_EXIT(parse_args_(argv), testing::ExitedWithCode(1), "");
-
-  argv[0] = "--seccomp-bpf-binary";
-  argv[1] = "source";
-  argv[2] = "-L";
-  ASSERT_EXIT(parse_args_(argv), testing::ExitedWithCode(1), "");
-}
-
-// Valid calls to the clear env option.
-TEST_F(CliTest, valid_clear_env) {
-  std::vector<std::string> argv = {"--env-reset", "/bin/sh"};
-
-  ASSERT_TRUE(parse_args_(argv));
-}
-
-// Valid calls to the set env option.
-TEST_F(CliTest, valid_set_env) {
-  std::vector<std::string> argv1 = {"--env-add", "NAME=value", "/bin/sh"};
-  ASSERT_TRUE(parse_args_(argv1));
-
-  // multiple occurences are allowed.
-  std::vector<std::string> argv2 = {"--env-add", "A=b",
-                                    "--env-add", "b=C=D", "/bin/sh"};
-  ASSERT_TRUE(parse_args_(argv2));
-
-  // --env-reset before any --env-add to not pass our own env.
-  std::vector<std::string> argv3 = {"--env-reset", "--env-add", "A=b", "/bin/sh"};
-  ASSERT_TRUE(parse_args_(argv3));
-
-  // --env-add before an --env-reset doesn't have any effect, but is allowed.
-  std::vector<std::string> argv4 = {"--env-add", "A=b", "--env-reset", "/bin/sh"};
-  ASSERT_TRUE(parse_args_(argv4));
-}
-
-// Invalid calls to the set env options.
-TEST_F(CliTest, invalid_set_env) {
-
-  // invalid env=value arguments.
-  std::vector<std::string> argv2 = {"--env-add", "", "/bin/sh"};
-
-  argv2[1] = "INVALID";
-  ASSERT_EXIT(parse_args_(argv2), testing::ExitedWithCode(1), "");
-
-  argv2[1] = "=";
-  ASSERT_EXIT(parse_args_(argv2), testing::ExitedWithCode(1), "");
-
-  argv2[1] = "=foo";
-  ASSERT_EXIT(parse_args_(argv2), testing::ExitedWithCode(1), "");
-}
-
-// Android unit tests do not support data file yet.
-#if !defined(__ANDROID__)
-
-TEST_F(CliTest, conf_parsing_invalid_key) {
-  std::vector<std::string> argv = {"--config", source_path("test/invalid.conf"),
-                                   "/bin/sh"};
-
-  ASSERT_EXIT(parse_args_(argv), testing::ExitedWithCode(1), "");
-}
-
-TEST_F(CliTest, conf_parsing) {
-  std::vector<std::string> argv = {"--config",
-                                   source_path("test/valid.conf"),
-                                   "/bin/sh"};
-
-  ASSERT_TRUE(parse_args_(argv));
-}
-
-#endif  // !__ANDROID__
diff --git a/parse_seccomp_policy.cc b/parse_seccomp_policy.cc
index a6daac5..000b80d 100644
--- a/parse_seccomp_policy.cc
+++ b/parse_seccomp_policy.cc
@@ -47,8 +47,8 @@
 int main(int argc, char** argv) {
   init_logging(LOG_TO_FD, STDERR_FILENO, LOG_INFO);
 
-  static const char optstring[] = "d:h";
-  static const struct option long_options[] = {
+  const char* optstring = "d:h";
+  const struct option long_options[] = {
       {"help", no_argument, 0, 'h'},
       {"dump", optional_argument, 0, 'd'},
       {0, 0, 0, 0},
diff --git a/rust/OWNERS b/rust/OWNERS
index f8111bb..1db5ac3 100644
--- a/rust/OWNERS
+++ b/rust/OWNERS
@@ -2,5 +2,5 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/rust/minijail-sys/Cargo.toml b/rust/minijail-sys/Cargo.toml
index 4c49c95..934c605 100644
--- a/rust/minijail-sys/Cargo.toml
+++ b/rust/minijail-sys/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "minijail-sys"
-version = "0.0.13"
+version = "0.0.11"
 description = "Provides raw (unsafe) bindings to the libminijail C library."
 authors = ["The Chromium OS Authors"]
 edition = "2018"
@@ -14,4 +14,3 @@
 
 [build-dependencies]
 pkg-config = "0.3"
-which = "4.0.0"
diff --git a/rust/minijail-sys/build.rs b/rust/minijail-sys/build.rs
index f73191c..8c7ea6d 100644
--- a/rust/minijail-sys/build.rs
+++ b/rust/minijail-sys/build.rs
@@ -7,35 +7,10 @@
 /// This script prefers linking against a pkg-config provided libminijail, but will fall back to
 /// building libminijail statically.
 use std::env;
-use std::fs::remove_file;
 use std::io;
-use std::path::Path;
 use std::process::Command;
 
-/// Returns the target triplet prefix for gcc commands. No prefix is required
-/// for native builds.
-fn get_cross_compile_prefix() -> String {
-    if let Ok(cross_compile) = env::var("CROSS_COMPILE") {
-        return cross_compile;
-    }
-
-    let target = env::var("TARGET").unwrap();
-
-    if env::var("HOST").unwrap() == target {
-        return String::from("");
-    }
-
-    let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
-    let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
-    let env = if target.ends_with("-gnueabihf") {
-        String::from("gnueabihf")
-    } else {
-        env::var("CARGO_CFG_TARGET_ENV").unwrap()
-    };
-    return format!("{}-{}-{}-", arch, os, env);
-}
-
-fn set_up_libminijail() -> io::Result<()> {
+fn main() -> io::Result<()> {
     // Minijail requires libcap at runtime.
     pkg_config::Config::new().probe("libcap").unwrap();
 
@@ -52,10 +27,9 @@
         .current_dir(&out_dir)
         .env("OUT", &out_dir)
         .env("MODE", if profile == "release" { "opt" } else { "debug" })
-        .env("CROSS_COMPILE", get_cross_compile_prefix())
-        .env("BUILD_STATIC_LIBS", "yes")
         .arg("-C")
         .arg(&current_dir)
+        .arg("CC_STATIC_LIBRARY(libminijail.pic.a)")
         .status()?;
     if !status.success() {
         std::process::exit(status.code().unwrap_or(1));
@@ -64,53 +38,3 @@
     println!("cargo:rustc-link-lib=static=minijail.pic");
     Ok(())
 }
-
-fn bindings_generation() -> io::Result<()> {
-    let bindgen = match which::which("bindgen") {
-        Ok(v) => v,
-        // Use already generated copy if bindgen is not present.
-        _ => return Ok(()),
-    };
-
-    // If CROS_RUST is set, skip generation.
-    let gen_file = Path::new("./libminijail.rs");
-    if gen_file.exists() {
-        if env::var("CROS_RUST") == Ok(String::from("1")) {
-            return Ok(());
-        }
-        remove_file(gen_file).expect("Failed to remove generated file.");
-    }
-    let header_dir = Path::new("../../");
-    let header_path = header_dir.join("libminijail.h");
-    println!("cargo:rerun-if-changed={}", header_path.display());
-    let status = Command::new(&bindgen)
-        .args(&["--default-enum-style", "rust"])
-        .args(&["--blacklist-type", "__rlim64_t"])
-        .args(&["--raw-line", "pub type __rlim64_t = u64;"])
-        .args(&["--blacklist-type", "__u\\d{1,2}"])
-        .args(&["--raw-line", "pub type __u8 = u8;"])
-        .args(&["--raw-line", "pub type __u16 = u16;"])
-        .args(&["--raw-line", "pub type __u32 = u32;"])
-        .args(&["--blacklist-type", "__uint64_t"])
-        .args(&["--whitelist-function", "^minijail_.*"])
-        .args(&["--whitelist-var", "^MINIJAIL_.*"])
-        .arg("--no-layout-tests")
-        .arg("--disable-header-comment")
-        .args(&["--output", gen_file.to_str().unwrap()])
-        .arg(header_path.to_str().unwrap())
-        .args(&[
-            "--",
-            "-DUSE_BINDGEN",
-            "-D_FILE_OFFSET_BITS=64",
-            "-D_LARGEFILE_SOURCE",
-            "-D_LARGEFILE64_SOURCE",
-        ])
-        .status()?;
-    assert!(status.success());
-    Ok(())
-}
-
-fn main() -> io::Result<()> {
-    set_up_libminijail()?;
-    bindings_generation()
-}
diff --git a/rust/minijail-sys/lib.rs b/rust/minijail-sys/lib.rs
index c418150..59db51e 100644
--- a/rust/minijail-sys/lib.rs
+++ b/rust/minijail-sys/lib.rs
@@ -37,11 +37,6 @@
 //
 // Enum variants in rust are customarily camel case, but bindgen will leave the original names
 // intact.
-#[allow(
-    clippy::all,
-    non_camel_case_types,
-    non_snake_case,
-    non_upper_case_globals
-)]
+#[allow(non_camel_case_types)]
 mod libminijail;
 pub use crate::libminijail::*;
diff --git a/rust/minijail-sys/libminijail.rs b/rust/minijail-sys/libminijail.rs
index 42b1a8d..594a479 100644
--- a/rust/minijail-sys/libminijail.rs
+++ b/rust/minijail-sys/libminijail.rs
@@ -1,3 +1,6 @@
+/* automatically generated by rust-bindgen */
+#![allow(clippy::all)]
+
 pub type __rlim64_t = u64;
 pub type __u8 = u8;
 pub type __u16 = u16;
@@ -10,7 +13,6 @@
 pub type gid_t = __gid_t;
 pub type uid_t = __uid_t;
 pub type pid_t = __pid_t;
-pub type size_t = ::std::os::raw::c_ulong;
 #[repr(C)]
 pub struct sock_filter {
     pub code: __u16,
@@ -27,17 +29,15 @@
 pub const MINIJAIL_ERR_NO_ACCESS: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_NO_ACCESS;
 pub const MINIJAIL_ERR_NO_COMMAND: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_NO_COMMAND;
 pub const MINIJAIL_ERR_SIG_BASE: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_SIG_BASE;
-pub const MINIJAIL_ERR_MOUNT: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_MOUNT;
 pub const MINIJAIL_ERR_PRELOAD: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_PRELOAD;
 pub const MINIJAIL_ERR_JAIL: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_JAIL;
 pub const MINIJAIL_ERR_INIT: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_INIT;
 #[repr(u32)]
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum _bindgen_ty_1 {
     MINIJAIL_ERR_NO_ACCESS = 126,
     MINIJAIL_ERR_NO_COMMAND = 127,
     MINIJAIL_ERR_SIG_BASE = 128,
-    MINIJAIL_ERR_MOUNT = 251,
     MINIJAIL_ERR_PRELOAD = 252,
     MINIJAIL_ERR_JAIL = 253,
     MINIJAIL_ERR_INIT = 254,
@@ -51,7 +51,7 @@
     unsafe extern "C" fn(context: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int,
 >;
 #[repr(u32)]
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum minijail_hook_event_t {
     MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS = 0,
     MINIJAIL_HOOK_EVENT_PRE_EXECVE = 1,
@@ -68,7 +68,7 @@
     pub fn minijail_change_gid(j: *mut minijail, gid: gid_t);
 }
 extern "C" {
-    pub fn minijail_set_supplementary_gids(j: *mut minijail, size: size_t, list: *const gid_t);
+    pub fn minijail_set_supplementary_gids(j: *mut minijail, size: usize, list: *const gid_t);
 }
 extern "C" {
     pub fn minijail_keep_supplementary_gids(j: *mut minijail);
@@ -98,9 +98,6 @@
     pub fn minijail_set_seccomp_filter_tsync(j: *mut minijail);
 }
 extern "C" {
-    pub fn minijail_set_seccomp_filter_allow_speculation(j: *mut minijail);
-}
-extern "C" {
     pub fn minijail_set_seccomp_filters(j: *mut minijail, filter: *const sock_fprog);
 }
 extern "C" {
@@ -256,7 +253,7 @@
     pub fn minijail_mount_tmp(j: *mut minijail);
 }
 extern "C" {
-    pub fn minijail_mount_tmp_size(j: *mut minijail, size: size_t);
+    pub fn minijail_mount_tmp_size(j: *mut minijail, size: usize);
 }
 extern "C" {
     pub fn minijail_mount_dev(j: *mut minijail);
@@ -289,11 +286,7 @@
     ) -> ::std::os::raw::c_int;
 }
 extern "C" {
-    pub fn minijail_add_remount(
-        j: *mut minijail,
-        mount_name: *const ::std::os::raw::c_char,
-        remount_mode: ::std::os::raw::c_ulong,
-    ) -> ::std::os::raw::c_int;
+    pub fn minijail_copy_jail(from: *const minijail, out: *mut minijail) -> ::std::os::raw::c_int;
 }
 extern "C" {
     pub fn minijail_add_hook(
@@ -361,30 +354,6 @@
     ) -> ::std::os::raw::c_int;
 }
 extern "C" {
-    pub fn minijail_run_env_pid_pipes(
-        j: *mut minijail,
-        filename: *const ::std::os::raw::c_char,
-        argv: *const *mut ::std::os::raw::c_char,
-        envp: *const *mut ::std::os::raw::c_char,
-        pchild_pid: *mut pid_t,
-        pstdin_fd: *mut ::std::os::raw::c_int,
-        pstdout_fd: *mut ::std::os::raw::c_int,
-        pstderr_fd: *mut ::std::os::raw::c_int,
-    ) -> ::std::os::raw::c_int;
-}
-extern "C" {
-    pub fn minijail_run_fd_env_pid_pipes(
-        j: *mut minijail,
-        elf_fd: ::std::os::raw::c_int,
-        argv: *const *mut ::std::os::raw::c_char,
-        envp: *const *mut ::std::os::raw::c_char,
-        pchild_pid: *mut pid_t,
-        pstdin_fd: *mut ::std::os::raw::c_int,
-        pstdout_fd: *mut ::std::os::raw::c_int,
-        pstderr_fd: *mut ::std::os::raw::c_int,
-    ) -> ::std::os::raw::c_int;
-}
-extern "C" {
     pub fn minijail_run_pid_pipes_no_preload(
         j: *mut minijail,
         filename: *const ::std::os::raw::c_char,
@@ -420,8 +389,5 @@
     pub fn minijail_destroy(j: *mut minijail);
 }
 extern "C" {
-    pub fn minijail_copy_jail(from: *const minijail, out: *mut minijail) -> ::std::os::raw::c_int;
-}
-extern "C" {
     pub fn minijail_log_to_fd(fd: ::std::os::raw::c_int, min_priority: ::std::os::raw::c_int);
 }
diff --git a/rust/minijail/Cargo.toml b/rust/minijail/Cargo.toml
index e6c08b8..db0652f 100644
--- a/rust/minijail/Cargo.toml
+++ b/rust/minijail/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "minijail"
-version = "0.2.3"
+version = "0.2.1"
 description = "Provides a safe Rust friendly interface to libminijail."
 authors = ["The Chromium OS Authors"]
 edition = "2018"
diff --git a/rust/minijail/src/lib.rs b/rust/minijail/src/lib.rs
index 5028041..ba59075 100644
--- a/rust/minijail/src/lib.rs
+++ b/rust/minijail/src/lib.rs
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+use libc::pid_t;
+use minijail_sys::*;
 use std::ffi::CString;
 use std::fmt::{self, Display};
 use std::fs;
@@ -10,154 +12,6 @@
 use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
 use std::path::{Path, PathBuf};
 use std::ptr::{null, null_mut};
-use std::result::Result as StdResult;
-
-use libc::pid_t;
-use minijail_sys::*;
-
-enum Program {
-    Filename(PathBuf),
-    FileDescriptor(RawFd),
-}
-
-/// Configuration of a command to be run in a jail.
-pub struct Command {
-    program: Program,
-    preserve_fds: Vec<(RawFd, RawFd)>,
-
-    // Ownership of the backing data of args_cptr is provided by args_cstr.
-    args_cstr: Vec<CString>,
-    args_cptr: Vec<*const c_char>,
-
-    // Ownership of the backing data of env_cptr is provided by env_cstr.
-    env_cstr: Option<Vec<CString>>,
-    env_cptr: Option<Vec<*const c_char>>,
-}
-
-impl Command {
-    /// This exposes a subset of what Command can do, before we are ready to commit to a stable
-    /// API.
-    pub fn new_for_path<P: AsRef<Path>, S: AsRef<str>, A: AsRef<str>>(
-        path: P,
-        keep_fds: &[RawFd],
-        args: &[S],
-        env_vars: Option<&[A]>,
-    ) -> Result<Command> {
-        let mut cmd = Command::new(Program::Filename(path.as_ref().to_path_buf()))
-            .keep_fds(keep_fds)
-            .args(args)?;
-        if let Some(env_vars) = env_vars {
-            cmd = cmd.envs(env_vars)?;
-        }
-
-        Ok(cmd)
-    }
-
-    fn new(program: Program) -> Command {
-        Command {
-            program,
-            preserve_fds: Vec::new(),
-            args_cstr: Vec::new(),
-            args_cptr: Vec::new(),
-            env_cstr: None,
-            env_cptr: None,
-        }
-    }
-
-    fn keep_fds(mut self, keep_fds: &[RawFd]) -> Command {
-        self.preserve_fds = keep_fds
-            .iter()
-            .map(|&a| (a, a))
-            .collect::<Vec<(RawFd, RawFd)>>();
-        self
-    }
-
-    fn remap_fds(mut self, remap_fds: &[(RawFd, RawFd)]) -> Command {
-        self.preserve_fds = remap_fds.to_vec();
-        self
-    }
-
-    fn args<S: AsRef<str>>(mut self, args: &[S]) -> Result<Command> {
-        let (args_cstr, args_cptr) = to_execve_cstring_array(args)?;
-        self.args_cstr = args_cstr;
-        self.args_cptr = args_cptr;
-        Ok(self)
-    }
-
-    fn envs<S: AsRef<str>>(mut self, vars: &[S]) -> Result<Command> {
-        let (env_cstr, env_cptr) = to_execve_cstring_array(vars)?;
-        self.env_cstr = Some(env_cstr);
-        self.env_cptr = Some(env_cptr);
-        Ok(self)
-    }
-
-    fn argv(&self) -> *const *mut c_char {
-        self.args_cptr.as_ptr() as *const *mut c_char
-    }
-
-    fn envp(&self) -> *const *mut c_char {
-        (match self.env_cptr {
-            Some(ref env_cptr) => env_cptr.as_ptr(),
-            None => null_mut(),
-        }) as *const *mut c_char
-    }
-}
-
-/// Abstracts paths and executable file descriptors in a way that the run implementation can cover
-/// both.
-trait Runnable {
-    fn run_command(&self, jail: &Minijail, cmd: &Command) -> Result<pid_t>;
-}
-
-impl Runnable for &Path {
-    fn run_command(&self, jail: &Minijail, cmd: &Command) -> Result<pid_t> {
-        let path_str = self
-            .to_str()
-            .ok_or_else(|| Error::PathToCString(self.to_path_buf()))?;
-        let path_cstr =
-            CString::new(path_str).map_err(|_| Error::StrToCString(path_str.to_owned()))?;
-
-        let mut pid: pid_t = 0;
-        let ret = unsafe {
-            minijail_run_env_pid_pipes(
-                jail.jail,
-                path_cstr.as_ptr(),
-                cmd.argv(),
-                cmd.envp(),
-                &mut pid,
-                null_mut(),
-                null_mut(),
-                null_mut(),
-            )
-        };
-        if ret < 0 {
-            return Err(Error::ForkingMinijail(ret));
-        }
-        Ok(pid)
-    }
-}
-
-impl Runnable for RawFd {
-    fn run_command(&self, jail: &Minijail, cmd: &Command) -> Result<pid_t> {
-        let mut pid: pid_t = 0;
-        let ret = unsafe {
-            minijail_run_fd_env_pid_pipes(
-                jail.jail,
-                *self,
-                cmd.argv(),
-                cmd.envp(),
-                &mut pid,
-                null_mut(),
-                null_mut(),
-                null_mut(),
-            )
-        };
-        if ret < 0 {
-            return Err(Error::ForkingMinijail(ret));
-        }
-        Ok(pid)
-    }
-}
 
 #[derive(Debug)]
 pub enum Error {
@@ -229,8 +83,6 @@
     Killed(u8),
     /// Process finished returning a non-zero code.
     ReturnCode(u8),
-    /// Failed to wait the process.
-    Wait(i32),
 }
 
 impl Display for Error {
@@ -319,14 +171,13 @@
             SeccompViolation(s) => write!(f, "seccomp violation syscall #{}", s),
             Killed(s) => write!(f, "killed with signal number {}", s),
             ReturnCode(e) => write!(f, "exited with code {}", e),
-            Wait(errno) => write!(f, "failed to wait: {}", io::Error::from_raw_os_error(*errno)),
         }
     }
 }
 
 impl std::error::Error for Error {}
 
-pub type Result<T> = StdResult<T, Error>;
+pub type Result<T> = std::result::Result<T, Error>;
 
 /// Configuration to jail a process based on wrapping libminijail.
 ///
@@ -382,9 +233,6 @@
     if ret == 0 {
         return Ok(());
     }
-    if ret < 0 {
-        return Err(Error::Wait(ret));
-    }
     if ret == MINIJAIL_ERR_NO_COMMAND as libc::c_int {
         return Err(Error::NoCommand);
     }
@@ -401,7 +249,7 @@
     if ret > 0 && ret <= 0xff {
         return Err(Error::ReturnCode(ret as u8));
     }
-    unreachable!("Unexpected returned value from wait: {}", ret);
+    unreachable!();
 }
 
 impl Minijail {
@@ -465,7 +313,7 @@
     }
     pub fn set_supplementary_gids(&mut self, ids: &[libc::gid_t]) {
         unsafe {
-            minijail_set_supplementary_gids(self.jail, ids.len() as size_t, ids.as_ptr());
+            minijail_set_supplementary_gids(self.jail, ids.len(), ids.as_ptr());
         }
     }
     pub fn keep_supplementary_gids(&mut self) {
@@ -510,9 +358,6 @@
         }
 
         let buffer = fs::read(path).map_err(Error::ReadProgram)?;
-        self.parse_seccomp_bytes(&buffer)
-    }
-    pub fn parse_seccomp_bytes(&mut self, buffer: &[u8]) -> Result<()> {
         if buffer.len() % std::mem::size_of::<sock_filter>() != 0 {
             return Err(Error::WrongProgramSize);
         }
@@ -767,7 +612,7 @@
     }
     pub fn mount_tmp_size(&mut self, size: usize) {
         unsafe {
-            minijail_mount_tmp_size(self.jail, size as size_t);
+            minijail_mount_tmp_size(self.jail, size);
         }
     }
     pub fn mount_bind<P1: AsRef<Path>, P2: AsRef<Path>>(
@@ -817,10 +662,13 @@
         inheritable_fds: &[RawFd],
         args: &[S],
     ) -> Result<pid_t> {
-        self.run_internal(
-            Command::new(Program::Filename(cmd.as_ref().to_path_buf()))
-                .keep_fds(inheritable_fds)
-                .args(args)?,
+        self.run_remap(
+            cmd,
+            &inheritable_fds
+                .iter()
+                .map(|&a| (a, a))
+                .collect::<Vec<(RawFd, RawFd)>>(),
+            args,
         )
     }
 
@@ -832,49 +680,25 @@
         inheritable_fds: &[(RawFd, RawFd)],
         args: &[S],
     ) -> Result<pid_t> {
-        self.run_internal(
-            Command::new(Program::Filename(cmd.as_ref().to_path_buf()))
-                .remap_fds(inheritable_fds)
-                .args(args)?,
-        )
-    }
+        let cmd_os = cmd
+            .as_ref()
+            .to_str()
+            .ok_or_else(|| Error::PathToCString(cmd.as_ref().to_owned()))?;
+        let cmd_cstr = CString::new(cmd_os).map_err(|_| Error::StrToCString(cmd_os.to_owned()))?;
 
-    /// Behaves the same as `run()` except cmd is a file descriptor to the executable.
-    pub fn run_fd<F: AsRawFd, S: AsRef<str>>(
-        &self,
-        cmd: &F,
-        inheritable_fds: &[RawFd],
-        args: &[S],
-    ) -> Result<pid_t> {
-        self.run_internal(
-            Command::new(Program::FileDescriptor(cmd.as_raw_fd()))
-                .keep_fds(inheritable_fds)
-                .args(args)?,
-        )
-    }
+        // Converts each incoming `args` string to a `CString`, and then puts each `CString` pointer
+        // into a null terminated array, suitable for use as an argv parameter to `execve`.
+        let mut args_cstr = Vec::with_capacity(args.len());
+        let mut args_array = Vec::with_capacity(args.len());
+        for arg in args {
+            let arg_cstr = CString::new(arg.as_ref())
+                .map_err(|_| Error::StrToCString(arg.as_ref().to_owned()))?;
+            args_array.push(arg_cstr.as_ptr());
+            args_cstr.push(arg_cstr);
+        }
+        args_array.push(null());
 
-    /// Behaves the same as `run()` except cmd is a file descriptor to the executable, and
-    /// `inheritable_fds` is a list of fd mappings rather than just a list of fds to preserve.
-    pub fn run_fd_remap<F: AsRawFd, S: AsRef<str>>(
-        &self,
-        cmd: &F,
-        inheritable_fds: &[(RawFd, RawFd)],
-        args: &[S],
-    ) -> Result<pid_t> {
-        self.run_internal(
-            Command::new(Program::FileDescriptor(cmd.as_raw_fd()))
-                .remap_fds(inheritable_fds)
-                .args(args)?,
-        )
-    }
-
-    /// A generic version of `run()` that is a super set of all variants.
-    pub fn run_command(&self, cmd: Command) -> Result<pid_t> {
-        self.run_internal(cmd)
-    }
-
-    fn run_internal(&self, cmd: Command) -> Result<pid_t> {
-        for (src_fd, dst_fd) in cmd.preserve_fds.iter() {
+        for (src_fd, dst_fd) in inheritable_fds {
             let ret = unsafe { minijail_preserve_fd(self.jail, *src_fd, *dst_fd) };
             if ret < 0 {
                 return Err(Error::PreservingFd(ret));
@@ -889,7 +713,7 @@
         // Set stdin, stdout, and stderr to /dev/null unless they are in the inherit list.
         // These will only be closed when this process exits.
         for io_fd in &[libc::STDIN_FILENO, libc::STDOUT_FILENO, libc::STDERR_FILENO] {
-            if !cmd.preserve_fds.iter().any(|(_, fd)| *fd == *io_fd) {
+            if !inheritable_fds.iter().any(|(_, fd)| *fd == *io_fd) {
                 let ret = unsafe { minijail_preserve_fd(self.jail, dev_null.as_raw_fd(), *io_fd) };
                 if ret < 0 {
                     return Err(Error::PreservingFd(ret));
@@ -901,10 +725,22 @@
             minijail_close_open_fds(self.jail);
         }
 
-        match cmd.program {
-            Program::Filename(ref path) => path.as_path().run_command(&self, &cmd),
-            Program::FileDescriptor(fd) => fd.run_command(&self, &cmd),
+        let mut pid = 0;
+        let ret = unsafe {
+            minijail_run_pid_pipes(
+                self.jail,
+                cmd_cstr.as_ptr(),
+                args_array.as_ptr() as *const *mut c_char,
+                &mut pid,
+                null_mut(),
+                null_mut(),
+                null_mut(),
+            )
+        };
+        if ret < 0 {
+            return Err(Error::ForkingMinijail(ret));
         }
+        Ok(pid)
     }
 
     /// Forks a child and puts it in the previously configured minijail.
@@ -1024,54 +860,15 @@
     }
 }
 
-fn to_execve_cstring_array<S: AsRef<str>>(
-    slice: &[S],
-) -> Result<(Vec<CString>, Vec<*const c_char>)> {
-    // Converts each incoming `str` to a `CString`, and then puts each `CString` pointer into a
-    // null terminated array, suitable for use as an argv or envp parameter to `execve`.
-    let mut vec_cstr = Vec::with_capacity(slice.len());
-    let mut vec_cptr = Vec::with_capacity(slice.len() + 1);
-    for s in slice {
-        let cstr =
-            CString::new(s.as_ref()).map_err(|_| Error::StrToCString(s.as_ref().to_owned()))?;
-
-        vec_cstr.push(cstr);
-        vec_cptr.push(vec_cstr.last().unwrap().as_ptr());
-    }
-
-    vec_cptr.push(null());
-
-    Ok((vec_cstr, vec_cptr))
-}
-
 #[cfg(test)]
 mod tests {
+    use std::process::exit;
+
     use super::*;
 
-    use std::fs::File;
-
-    use libc::{FD_CLOEXEC, F_GETFD, F_SETFD};
-
     const SHELL: &str = "/bin/sh";
     const EMPTY_STRING_SLICE: &[&str] = &[];
 
-    fn clear_cloexec<A: AsRawFd>(fd_owner: &A) -> StdResult<(), io::Error> {
-        let fd = fd_owner.as_raw_fd();
-        // Safe because fd is read only.
-        let flags = unsafe { libc::fcntl(fd, F_GETFD) };
-        if flags == -1 {
-            return Err(io::Error::last_os_error());
-        }
-
-        let masked_flags = flags & !FD_CLOEXEC;
-        // Safe because this has no side effect(s) on the current process.
-        if masked_flags != flags && unsafe { libc::fcntl(fd, F_SETFD, masked_flags) } == -1 {
-            Err(io::Error::last_os_error())
-        } else {
-            Ok(())
-        }
-    }
-
     #[test]
     fn create_and_free() {
         unsafe {
@@ -1092,7 +889,9 @@
         j.no_new_privs();
         j.parse_seccomp_filters("src/test_filter.policy").unwrap();
         j.use_seccomp_filter();
-        j.run("/bin/true", &[], &EMPTY_STRING_SLICE).unwrap();
+        if unsafe { j.fork(None).unwrap() } == 0 {
+            exit(0);
+        }
     }
 
     #[test]
@@ -1104,28 +903,14 @@
             let j = Minijail::new().unwrap();
             let first = libc::open(FILE_PATH.as_ptr() as *const c_char, libc::O_RDONLY);
             assert!(first >= 0);
-            // This appears unused but its function is to be a file descriptor that is closed
-            // inside run_remap after the fork. If it is not closed, the script will fail.
             let second = libc::open(FILE_PATH.as_ptr() as *const c_char, libc::O_RDONLY);
             assert!(second >= 0);
-
-            let fds: Vec<(RawFd, RawFd)> = vec![(first, 0), (1, 1), (2, 2)];
-            j.run_remap(
-                SHELL,
-                &fds,
-                &[
-                    SHELL,
-                    "-c",
-                    r#"
-if [ `ls -l /proc/self/fd/ | grep '/dev/null' | wc -l` != '1' ]; then
-  ls -l /proc/self/fd/  # Included to make debugging easier.
-  exit 1
-fi
-"#,
-                ],
-            )
-            .unwrap();
-            j.wait().unwrap();
+            let fds: Vec<RawFd> = vec![0, 1, 2, first];
+            if j.fork(Some(&fds)).unwrap() == 0 {
+                assert!(libc::close(second) < 0); // Should fail as second should be closed already.
+                assert_eq!(libc::close(first), 0); // Should succeed as first should be untouched.
+                exit(0);
+            }
         }
     }
 
@@ -1179,29 +964,14 @@
         let j = Minijail::new().unwrap();
         j.run("/bin/does not exist", &[1, 2], &EMPTY_STRING_SLICE)
             .unwrap();
-        // TODO(b/194221986) Fix libminijail so that Error::NoAccess is not sometimes returned.
-        assert!(matches!(
-            j.wait(),
-            Err(Error::NoCommand) | Err(Error::NoAccess)
-        ));
-    }
-
-    #[test]
-    fn runnable_fd_success() {
-        let bin_file = File::open("/bin/true").unwrap();
-        // On Chrome OS targets /bin/true is actually a script, so drop CLOEXEC to prevent ENOENT.
-        clear_cloexec(&bin_file).unwrap();
-
-        let j = Minijail::new().unwrap();
-        j.run_fd(&bin_file, &[1, 2], &EMPTY_STRING_SLICE).unwrap();
-        expect_result!(j.wait(), Ok(()));
+        expect_result!(j.wait(), Err(Error::NoCommand));
     }
 
     #[test]
     fn kill_success() {
         let j = Minijail::new().unwrap();
         j.run(
-            Path::new("/usr/bin/sleep"),
+            Path::new("usr/bin/sleep"),
             &[1, 2],
             &["/usr/bin/sleep", "5"],
         )
@@ -1215,7 +985,9 @@
     fn chroot() {
         let mut j = Minijail::new().unwrap();
         j.enter_chroot(".").unwrap();
-        j.run("/bin/true", &[], &EMPTY_STRING_SLICE).unwrap();
+        if unsafe { j.fork(None).unwrap() } == 0 {
+            exit(0);
+        }
     }
 
     #[test]
@@ -1223,7 +995,9 @@
     fn namespace_vfs() {
         let mut j = Minijail::new().unwrap();
         j.namespace_vfs();
-        j.run("/bin/true", &[], &EMPTY_STRING_SLICE).unwrap();
+        if unsafe { j.fork(None).unwrap() } == 0 {
+            exit(0);
+        }
     }
 
     #[test]
diff --git a/syscall_filter.c b/syscall_filter.c
index de5441c..fcdbaa8 100644
--- a/syscall_filter.c
+++ b/syscall_filter.c
@@ -568,6 +568,49 @@
 	return 0;
 }
 
+/*
+ * This is like getline() but supports line wrapping with \.
+ */
+static ssize_t getmultiline(char **lineptr, size_t *n, FILE *stream)
+{
+	ssize_t ret = getline(lineptr, n, stream);
+	if (ret < 0)
+		return ret;
+
+	char *line = *lineptr;
+	/* Eat the newline to make processing below easier. */
+	if (ret > 0 && line[ret - 1] == '\n')
+		line[--ret] = '\0';
+
+	/* If the line doesn't end in a backslash, we're done. */
+	if (ret <= 0 || line[ret - 1] != '\\')
+		return ret;
+
+	/* This line ends in a backslash. Get the nextline. */
+	line[--ret] = '\0';
+	size_t next_n = 0;
+	char *next_line = NULL;
+	ssize_t next_ret = getmultiline(&next_line, &next_n, stream);
+	if (next_ret == -1) {
+		free(next_line);
+		/* We couldn't fully read the line, so return an error. */
+		return -1;
+	}
+
+	/* Merge the lines. */
+	*n = ret + next_ret + 2;
+	line = realloc(line, *n);
+	if (!line) {
+		free(next_line);
+		return -1;
+	}
+	line[ret] = ' ';
+	memcpy(&line[ret + 1], next_line, next_ret + 1);
+	free(next_line);
+	*lineptr = line;
+	return *n - 1;
+}
+
 int compile_file(const char *filename, FILE *policy_file,
 		 struct filter_block *head, struct filter_block **arg_blocks,
 		 struct bpf_labels *labels,
@@ -589,7 +632,7 @@
 	 * Chain the filter sections together and dump them into
 	 * the final buffer at the end.
 	 */
-	attribute_cleanup_str char *line = NULL;
+	char *line = NULL;
 	size_t len = 0;
 	int ret = 0;
 
@@ -624,16 +667,15 @@
 				    &state,
 				    "failed to parse include statement");
 				ret = -1;
-				goto out;
+				goto free_line;
 			}
 
-			attribute_cleanup_fp FILE *included_file =
-			    fopen(filename, "re");
+			FILE *included_file = fopen(filename, "re");
 			if (included_file == NULL) {
 				compiler_pwarn(&state, "fopen('%s') failed",
 					       filename);
 				ret = -1;
-				goto out;
+				goto free_line;
 			}
 			if (compile_file(filename, included_file, head,
 					 arg_blocks, labels, filteropts,
@@ -641,9 +683,11 @@
 					 include_level + 1) == -1) {
 				compiler_warn(&state, "'@include %s' failed",
 					      filename);
+				fclose(included_file);
 				ret = -1;
-				goto out;
+				goto free_line;
 			}
+			fclose(included_file);
 			continue;
 		}
 
@@ -656,14 +700,14 @@
 			warn("compile_file: malformed policy line, missing "
 			     "':'");
 			ret = -1;
-			goto out;
+			goto free_line;
 		}
 
 		policy_line = strip(policy_line);
 		if (*policy_line == '\0') {
 			compiler_warn(&state, "empty policy line");
 			ret = -1;
-			goto out;
+			goto free_line;
 		}
 
 		syscall_name = strip(syscall_name);
@@ -688,7 +732,7 @@
 				continue;
 			}
 			ret = -1;
-			goto out;
+			goto free_line;
 		}
 
 		if (!insert_and_check_duplicate_syscall(previous_syscalls,
@@ -731,7 +775,7 @@
 				}
 				warn("could not allocate filter block");
 				ret = -1;
-				goto out;
+				goto free_line;
 			}
 
 			if (*arg_blocks) {
@@ -752,7 +796,8 @@
 		ret = -1;
 	}
 
-out:
+free_line:
+	free(line);
 	return ret;
 }
 
diff --git a/syscall_filter_unittest.cc b/syscall_filter_unittest.cc
index 79755f9..74f79da 100644
--- a/syscall_filter_unittest.cc
+++ b/syscall_filter_unittest.cc
@@ -15,11 +15,21 @@
 #include "bpf.h"
 #include "syscall_filter.h"
 #include "syscall_filter_unittest_macros.h"
-#include "test_util.h"
 #include "util.h"
 
 namespace {
 
+// TODO(jorgelo): Android unit tests don't currently support data files.
+// Re-enable by creating a temporary policy file at runtime.
+#if !defined(__ANDROID__)
+
+std::string source_path(std::string file) {
+  std::string srcdir = getenv("SRC") ? : ".";
+  return srcdir + "/" + file;
+}
+
+#endif
+
 // Simple C++ -> C wrappers to simplify test code.
 
 enum ret_trap {
@@ -34,7 +44,7 @@
 };
 
 int test_compile_filter(
-    const std::string& filename,
+    std::string filename,
     FILE* policy_file,
     struct sock_fprog* prog,
     enum block_action action = ACTION_RET_KILL,
@@ -79,7 +89,7 @@
 struct filter_block* test_compile_policy_line(
     struct parser_state* state,
     int nr,
-    const std::string& policy_line,
+    std::string policy_line,
     unsigned int label_id,
     struct bpf_labels* labels,
     enum block_action action = ACTION_RET_KILL) {
@@ -500,7 +510,7 @@
 }
 
 TEST_F(ArgFilterTest, arg0_short_gt_ge_comparisons) {
-  for (const std::string fragment :
+  for (std::string fragment :
        {"arg1 < 0xff", "arg1 <= 0xff", "arg1 > 0xff", "arg1 >= 0xff"}) {
     struct filter_block* block =
         test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
@@ -542,7 +552,7 @@
 
 #if defined(BITS64)
 TEST_F(ArgFilterTest, arg0_long_gt_ge_comparisons) {
-  for (const std::string fragment :
+  for (std::string fragment :
        {"arg1 < 0xbadc0ffee0ddf00d", "arg1 <= 0xbadc0ffee0ddf00d",
         "arg1 > 0xbadc0ffee0ddf00d", "arg1 >= 0xbadc0ffee0ddf00d"}) {
     struct filter_block* block =
@@ -1030,6 +1040,44 @@
 
 namespace {
 
+FILE* write_policy_to_pipe(std::string policy) {
+  int pipefd[2];
+  if (pipe(pipefd) == -1) {
+    pwarn("pipe(pipefd) failed");
+    return nullptr;
+  }
+
+  size_t len = policy.length();
+  size_t i = 0;
+  unsigned int attempts = 0;
+  ssize_t ret;
+  while (i < len) {
+    ret = write(pipefd[1], policy.c_str() + i, len - i);
+    if (ret == -1) {
+      close(pipefd[0]);
+      close(pipefd[1]);
+      return nullptr;
+    }
+
+    /* If we write 0 bytes three times in a row, fail. */
+    if (ret == 0) {
+      if (++attempts >= 3) {
+        close(pipefd[0]);
+        close(pipefd[1]);
+        warn("write() returned 0 three times in a row");
+        return nullptr;
+      }
+      continue;
+    }
+
+    attempts = 0;
+    i += (size_t)ret;
+  }
+
+  close(pipefd[1]);
+  return fdopen(pipefd[0], "r");
+}
+
 class FileTest : public ::testing::Test {
  protected:
   virtual void SetUp() {
@@ -1053,7 +1101,7 @@
   std::string policy =
       "malformed";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
                               &labels_);
@@ -1070,7 +1118,7 @@
       "read:arg0 == 0\n"
       "write:0";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
                               &labels_);
@@ -1086,7 +1134,7 @@
   std::string policy =
       "read:arg0 == 0; ;";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
                               &labels_);
@@ -1105,7 +1153,7 @@
       "rt_sigreturn: 1\n"
       "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
                               &labels_);
@@ -1140,7 +1188,7 @@
 
   const int LABEL_ID = 0;
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
                               &labels_);
@@ -1207,7 +1255,7 @@
 
   const int LABEL_ID = 0;
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
                               &labels_);
@@ -1243,7 +1291,7 @@
       "rt_sigreturn: 1\n"
       "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1280,7 +1328,7 @@
       "rt_sigreturn: 1\n"
       "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual,
@@ -1325,7 +1373,7 @@
       "rt_sigreturn: 1\n"
       "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1345,7 +1393,7 @@
       "rt_sigreturn: 1\n"
       "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1364,7 +1412,7 @@
     "rt_sigreturn: 1\n"
     "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res =
@@ -1403,7 +1451,7 @@
     "rt_sigreturn: 1\n"
     "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual, ACTION_RET_LOG,
@@ -1442,7 +1490,7 @@
     "rt_sigreturn: 1\n"
     "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual, ACTION_RET_LOG,
@@ -1463,7 +1511,7 @@
     "rt_sigreturn: 1\n"
     "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual, ACTION_RET_KILL_PROCESS,
@@ -1502,7 +1550,7 @@
       "rt_sigreturn: 1\n"
       "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1543,7 +1591,7 @@
   struct sock_fprog actual;
   std::string policy = "read :1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1561,7 +1609,7 @@
   struct sock_fprog actual;
   std::string policy = "open:\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1573,7 +1621,7 @@
   struct sock_fprog actual;
   std::string policy = "open:\t    \n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1585,7 +1633,7 @@
   struct sock_fprog actual;
   std::string policy = "notasyscall: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1597,7 +1645,7 @@
   struct sock_fprog actual;
   std::string policy = "open: argnn ==\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1609,7 +1657,7 @@
   struct sock_fprog actual;
   std::string policy = "read: arg0 == 1 |||| arg0 == 2\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1631,7 +1679,7 @@
       "rt_sigreturn: 1\n"
       "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual, ACTION_RET_TRAP,
@@ -1678,7 +1726,7 @@
     "rt_sigreturn: 1\n"
     "exit: 1\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual, ACTION_RET_KILL,
@@ -1721,7 +1769,7 @@
   struct sock_fprog actual;
   std::string frequency = "@frequency ./path/is/ignored.frequency\n";
 
-  FILE* policy_file = write_to_pipe(frequency);
+  FILE* policy_file = write_policy_to_pipe(frequency);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1734,7 +1782,7 @@
   struct sock_fprog actual;
   std::string invalid_token = "@unclude ./test/seccomp.policy\n";
 
-  FILE* policy_file = write_to_pipe(invalid_token);
+  FILE* policy_file = write_policy_to_pipe(invalid_token);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1745,7 +1793,7 @@
   struct sock_fprog actual;
   std::string no_space = "@includetest/seccomp.policy\n";
 
-  FILE* policy_file = write_to_pipe(no_space);
+  FILE* policy_file = write_policy_to_pipe(no_space);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1756,7 +1804,7 @@
   struct sock_fprog actual;
   std::string double_token = "@includeinclude ./test/seccomp.policy\n";
 
-  FILE* policy_file = write_to_pipe(double_token);
+  FILE* policy_file = write_policy_to_pipe(double_token);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1767,7 +1815,7 @@
   struct sock_fprog actual;
   std::string no_file = "@include\n";
 
-  FILE* policy_file = write_to_pipe(no_file);
+  FILE* policy_file = write_policy_to_pipe(no_file);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1778,7 +1826,7 @@
   struct sock_fprog actual;
   std::string space_no_file = "@include \n";
 
-  FILE* policy_file = write_to_pipe(space_no_file);
+  FILE* policy_file = write_policy_to_pipe(space_no_file);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1789,7 +1837,7 @@
   struct sock_fprog actual;
   std::string implicit_relative_path = "@include test/seccomp.policy\n";
 
-  FILE* policy_file = write_to_pipe(implicit_relative_path);
+  FILE* policy_file = write_policy_to_pipe(implicit_relative_path);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1800,7 +1848,7 @@
   struct sock_fprog actual;
   std::string extra_text = "@include /some/file: sneaky comment\n";
 
-  FILE* policy_file = write_to_pipe(extra_text);
+  FILE* policy_file = write_policy_to_pipe(extra_text);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1811,7 +1859,7 @@
   struct sock_fprog actual;
   std::string split_filename = "@include /some/file:colon.policy\n";
 
-  FILE* policy_file = write_to_pipe(split_filename);
+  FILE* policy_file = write_policy_to_pipe(split_filename);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
@@ -1822,7 +1870,7 @@
   struct sock_fprog actual;
   std::string include_policy = "@include ./nonexistent.policy\n";
 
-  FILE* policy_file = write_to_pipe(include_policy);
+  FILE* policy_file = write_policy_to_pipe(include_policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1845,7 +1893,7 @@
       "rt_sigreturn: 1\n"
       "exit: 1\n";
 
-  FILE* file_plain = write_to_pipe(policy_plain);
+  FILE* file_plain = write_policy_to_pipe(policy_plain);
   ASSERT_NE(file_plain, nullptr);
   int res_plain = test_compile_filter("policy", file_plain, &compiled_plain,
                                       ACTION_RET_KILL);
@@ -1854,7 +1902,7 @@
   std::string policy_with_include =
       "@include " + source_path("test/seccomp.policy") + "\n";
 
-  FILE* file_with_include = write_to_pipe(policy_with_include);
+  FILE* file_with_include = write_policy_to_pipe(policy_with_include);
   ASSERT_NE(file_with_include, nullptr);
   int res_with_include = test_compile_filter(
       "policy", file_with_include, &compiled_with_include, ACTION_RET_KILL);
@@ -1901,7 +1949,7 @@
       "exit: 1\n"
       "@include " + source_path("test/seccomp.policy") + "\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1923,7 +1971,7 @@
       "exit: 1\n"
       "@include " + source_path("test/seccomp.policy") + "\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual,
@@ -1940,7 +1988,7 @@
       "@include " + source_path("test/seccomp.policy") + "\n" +
       "@include " + source_path("test/seccomp.policy") + "\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   int res = test_compile_filter("policy", policy_file, &actual);
@@ -1962,7 +2010,7 @@
       "exit: 1\n"
       "@include ./test/invalid_syscall_name.policy\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   /* Ensure the included (invalid) policy file exists. */
@@ -1981,7 +2029,7 @@
   struct sock_fprog actual;
   std::string policy = "@include ./test/nested.policy\n";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
 
   /* Ensure the policy file exists. */
@@ -2003,7 +2051,7 @@
       "read:&&\n"
       "read:&&";
 
-  FILE* policy_file = write_to_pipe(policy);
+  FILE* policy_file = write_policy_to_pipe(policy);
   ASSERT_NE(policy_file, nullptr);
   int res = test_compile_filter("policy", policy_file, &actual);
   fclose(policy_file);
diff --git a/system.c b/system.c
index 711e29e..10e1499 100644
--- a/system.c
+++ b/system.c
@@ -111,8 +111,7 @@
 
 int write_proc_file(pid_t pid, const char *content, const char *basename)
 {
-	attribute_cleanup_fd int fd = -1;
-	int ret;
+	int fd, ret;
 	size_t sz, len;
 	ssize_t written;
 	char filename[32];
@@ -141,6 +140,7 @@
 		warn("failed to write %zu bytes to '%s'", len, filename);
 		return -1;
 	}
+	close(fd);
 	return 0;
 }
 
@@ -167,10 +167,8 @@
 			last_valid_cap--;
 		}
 	} else {
-		static const char cap_file[] = "/proc/sys/kernel/cap_last_cap";
+		const char cap_file[] = "/proc/sys/kernel/cap_last_cap";
 		FILE *fp = fopen(cap_file, "re");
-		if (!fp)
-			pdie("fopen(%s)", cap_file);
 		if (fscanf(fp, "%u", &last_valid_cap) != 1)
 			pdie("fscanf(%s)", cap_file);
 		fclose(fp);
@@ -187,7 +185,7 @@
 int config_net_loopback(void)
 {
 	const char ifname[] = "lo";
-	attribute_cleanup_fd int sock = -1;
+	int sock;
 	struct ifreq ifr;
 
 	/* Make sure people don't try to add really long names. */
@@ -216,6 +214,7 @@
 		return -1;
 	}
 
+	close(sock);
 	return 0;
 }
 
@@ -230,7 +229,6 @@
 	if (fprintf(fp, "%d\n", (int)pid) < 0) {
 		/* fprintf(3) does not set errno on failure. */
 		warn("fprintf(%s) failed", path);
-		fclose(fp);
 		return -1;
 	}
 	if (fclose(fp)) {
@@ -367,13 +365,13 @@
 	if (rc)
 		return rc;
 	if (!domkdir) {
-		attribute_cleanup_fd int fd = open(
-			dest, O_RDWR | O_CREAT | O_CLOEXEC, 0700);
+		int fd = open(dest, O_RDWR | O_CREAT | O_CLOEXEC, 0700);
 		if (fd < 0) {
 			rc = errno;
 			pwarn("open(%s) failed", dest);
 			return -rc;
 		}
+		close(fd);
 	}
 	if (chown(dest, uid, gid)) {
 		rc = errno;
@@ -500,10 +498,11 @@
 		return false;
 	}
 
-	attribute_cleanup_str char *actions_avail = NULL;
+	char *actions_avail = NULL;
 	size_t buf_size = 0;
 	if (getline(&actions_avail, &buf_size, f) < 0) {
 		pwarn("getline() failed");
+		free(actions_avail);
 		return false;
 	}
 
@@ -513,7 +512,9 @@
 	 * seccomp actions which include other actions though, so we're good for
 	 * now. Eventually we might want to split the string by spaces.
 	 */
-	return strstr(actions_avail, wanted) != NULL;
+	bool available = strstr(actions_avail, wanted) != NULL;
+	free(actions_avail);
+	return available;
 }
 
 int seccomp_ret_log_available(void)
diff --git a/test/invalid.conf b/test/invalid.conf
deleted file mode 100644
index d15d289..0000000
--- a/test/invalid.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-% minijail-config-file v0
-# Comments
-bad-key = whatever
diff --git a/test/valid.conf b/test/valid.conf
deleted file mode 100644
index a574e6c..0000000
--- a/test/valid.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-% minijail-config-file v0
-# Comments
-# enable mount namespace
-ns-mount
-# mounts and bind-mounts
-mount = none,/,none
-bind-mount = /,/
-mount-dev
diff --git a/test_util.cc b/test_util.cc
deleted file mode 100644
index cb751ff..0000000
--- a/test_util.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "test_util.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "util.h"
-
-#define MAX_PIPE_CAPACITY (4096)
-
-FILE *write_to_pipe(const std::string& content)
-{
-	int pipefd[2];
-	if (pipe(pipefd) == -1) {
-		die("pipe(pipefd) failed");
-	}
-
-	size_t len = content.length();
-	if (len > MAX_PIPE_CAPACITY)
-		die("write_to_pipe cannot handle >4KB content.");
-	size_t i = 0;
-	unsigned int attempts = 0;
-	ssize_t ret;
-	while (i < len) {
-		ret = write(pipefd[1], content.c_str() + i, len - i);
-		if (ret == -1) {
-			close(pipefd[0]);
-			close(pipefd[1]);
-			return NULL;
-		}
-
-		/* If we write 0 bytes three times in a row, fail. */
-		if (ret == 0) {
-			if (++attempts >= 3) {
-				close(pipefd[0]);
-				close(pipefd[1]);
-				warn("write() returned 0 three times in a row");
-				return NULL;
-			}
-			continue;
-		}
-
-		attempts = 0;
-		i += (size_t)ret;
-	}
-
-	close(pipefd[1]);
-	return fdopen(pipefd[0], "r");
-}
-
-std::string source_path(const std::string& file) {
-	std::string srcdir = getenv("SRC") ? : ".";
-	return srcdir + "/" + file;
-}
diff --git a/test_util.h b/test_util.h
deleted file mode 100644
index e915086..0000000
--- a/test_util.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* test_util.h
- * Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Utility functions in testing.
- */
-
-#ifndef _TEST_UTIL_H_
-#define _TEST_UTIL_H_
-
-#include <stdio.h>
-
-#include <memory>
-#include <string>
-
-#include "config_parser.h"
-
-namespace mj {
-
-namespace internal {
-
-// Functor for |ScopedFILE| (below).
-struct ScopedFILECloser {
-  inline void operator()(FILE *x) const {
-    if (x) {
-      fclose(x);
-    }
-  }
-};
-
-// Functor for |ScopedConfigEntry| (below).
-struct ScopedConfigEntryDeleter {
-  inline void operator()(config_entry *entry) const {
-    if (entry) {
-      free(entry);
-    }
-  }
-};
-
-} // namespace internal
-
-} // namespace mj
-
-using ScopedFILE = std::unique_ptr<FILE, mj::internal::ScopedFILECloser>;
-using ScopedConfigEntry =
-    std::unique_ptr<config_entry, mj::internal::ScopedConfigEntryDeleter>;
-
-/*
- * write_to_pipe: write a string as the file content into a pipe based
- * file handle. This is particularly useful when testing with temporary data
- * files, without dealing with complexities such as relative file path, file
- * permission and etc. However, a pipe has limited capacity so write_to_pipe
- * will hang when a big enough string is written. This is for use in testing
- * only.
- *
- * Returns a FILE* that contains @content.
- */
-
-FILE *write_to_pipe(const std::string& content);
-
-/*
- * source_path: return the path to a test fixture located in the current
- * source tree. This uses the `SRC` environment variable as the root of the
- * tree, falling back to the current directory.
- */
-std::string source_path(const std::string& file);
-
-#endif /* _TEST_UTIL_H_ */
diff --git a/tools/compile_seccomp_policy.py b/tools/compile_seccomp_policy.py
index 2219ae5..f2b714b 100755
--- a/tools/compile_seccomp_policy.py
+++ b/tools/compile_seccomp_policy.py
@@ -40,25 +40,6 @@
 CONSTANTS_ERR_MSG = """Could not find 'constants.json' file.
 See 'generate_constants_json.py -h'."""
 
-HEADER_TEMPLATE = """/* DO NOT EDIT GENERATED FILE */
-#ifndef MJ_SECCOMP_%(upper_name)s_H
-#define MJ_SECCOMP_%(upper_name)s_H
-#include <stdint.h>
-
-static const unsigned char %(name)s_binary_seccomp_policy[] __attribute__((__aligned__(4))) = {
-    %(program)s
-};
-
-static const struct {
-    uint16_t cnt;
-    const void *bpf;
-} %(name)s_seccomp_bpf_program = {
-    .cnt = sizeof(%(name)s_binary_seccomp_policy) / 8,
-    .bpf = %(name)s_binary_seccomp_policy,
-};
-
-#endif
-"""
 
 def parse_args(argv):
     """Return the parsed CLI arguments for this tool."""
@@ -70,10 +51,6 @@
     arg_parser.add_argument('--include-depth-limit', default=10)
     arg_parser.add_argument('--arch-json', default='constants.json')
     arg_parser.add_argument(
-        '--denylist',
-        action='store_true',
-        help='Compile as a denylist policy rather than the default allowlist.')
-    arg_parser.add_argument(
         '--default-action',
         type=str,
         help=('Use the specified default action, overriding any @default '
@@ -86,22 +63,12 @@
         action='store_true',
         help=('Use SECCOMP_RET_KILL_PROCESS instead of '
               'SECCOMP_RET_KILL_THREAD (requires Linux v4.14+).'))
-    arg_parser.add_argument(
-        '--use-ret-log',
-        action='store_true',
-        help=('Change all seccomp failures to return SECCOMP_RET_LOG instead '
-              'of killing (requires SECCOMP_RET_LOG kernel support).'))
-    arg_parser.add_argument(
-        '--output-header-file',
-        action='store_true',
-        help=('Output the compiled bpf to a constant variable in a C header '
-              'file instead of a binary file (output should not have a .h '
-              'extension, one will be added).'))
     arg_parser.add_argument('policy',
                             help='The seccomp policy.',
                             type=argparse.FileType('r'))
     arg_parser.add_argument('output',
-                            help='The BPF program.')
+                            help='The BPF program.',
+                            type=argparse.FileType('wb'))
     return arg_parser.parse_args(argv), arg_parser
 
 
@@ -117,21 +84,7 @@
 
     parsed_arch = arch.Arch.load_from_json(opts.arch_json)
     policy_compiler = compiler.PolicyCompiler(parsed_arch)
-    # Set ret_log to true if the MINIJAIL_DEFAULT_RET_LOG environment variable
-    # is present.
-    if 'MINIJAIL_DEFAULT_RET_LOG' in os.environ:
-        print("""
-            \n**********************
-Warning: MINJAIL_DEFAULT_RET_LOG is on, policy will not have any effect
-**********************\n
-""")
-        opts.use_ret_log = True
-    if opts.use_ret_log:
-        kill_action = bpf.Log()
-    elif opts.denylist:
-        # Default action for a denylist policy is return EPERM
-        kill_action = bpf.ReturnErrno(parsed_arch.constants['EPERM'])
-    elif opts.use_kill_process:
+    if opts.use_kill_process:
         kill_action = bpf.KillProcess()
     else:
         kill_action = bpf.KillThread()
@@ -141,29 +94,14 @@
         override_default_action = parser.PolicyParser(
             parsed_arch, kill_action=bpf.KillProcess()).parse_action(
                 next(parser_state.tokenize([opts.default_action])))
-
-    compiled_policy = policy_compiler.compile_file(
-        opts.policy.name,
-        optimization_strategy=opts.optimization_strategy,
-        kill_action=kill_action,
-        include_depth_limit=opts.include_depth_limit,
-        override_default_action=override_default_action,
-        denylist=opts.denylist,
-        ret_log=opts.use_ret_log)
-    # Outputs the bpf binary to a c header file instead of a binary file.
-    if opts.output_header_file:
-        output_file_base = opts.output
-        with open(output_file_base + '.h', 'w') as output_file:
-            program = ', '.join('%i' % x for x in compiled_policy.opcodes)
-            output_file.write(HEADER_TEMPLATE % {
-                'upper_name': output_file_base.upper(),
-                'name': output_file_base,
-                'program': program,
-            })
-
-    else:
-        with open(opts.output, 'wb') as outf:
-            outf.write(compiled_policy.opcodes)
+    with opts.output as outf:
+        outf.write(
+            policy_compiler.compile_file(
+                opts.policy.name,
+                optimization_strategy=opts.optimization_strategy,
+                kill_action=kill_action,
+                include_depth_limit=opts.include_depth_limit,
+                override_default_action=override_default_action).opcodes)
     return 0
 
 
diff --git a/tools/compiler.py b/tools/compiler.py
index f239740..161eadf 100644
--- a/tools/compiler.py
+++ b/tools/compiler.py
@@ -270,32 +270,24 @@
                      optimization_strategy,
                      kill_action,
                      include_depth_limit=10,
-                     override_default_action=None,
-                     denylist=False,
-                     ret_log=False):
+                     override_default_action=None):
         """Return a compiled BPF program from the provided policy file."""
         policy_parser = parser.PolicyParser(
             self._arch,
             kill_action=kill_action,
             include_depth_limit=include_depth_limit,
-            override_default_action=override_default_action,
-            denylist=denylist,
-            ret_log=ret_log)
+            override_default_action=override_default_action)
         parsed_policy = policy_parser.parse_file(policy_filename)
         entries = [
             self.compile_filter_statement(
-                filter_statement, kill_action=kill_action, denylist=denylist)
+                filter_statement, kill_action=kill_action)
             for filter_statement in parsed_policy.filter_statements
         ]
 
         visitor = bpf.FlatteningVisitor(
             arch=self._arch, kill_action=kill_action)
-        if denylist:
-            accept_action = kill_action
-            reject_action = bpf.Allow()
-        else:
-            accept_action = bpf.Allow()
-            reject_action = parsed_policy.default_action
+        accept_action = bpf.Allow()
+        reject_action = parsed_policy.default_action
         if entries:
             if optimization_strategy == OptimizationStrategy.BST:
                 next_action = _compile_entries_bst(entries, accept_action,
@@ -312,11 +304,7 @@
             bpf.ValidateArch(reject_action).accept(visitor)
         return visitor.result
 
-    def compile_filter_statement(self,
-                                 filter_statement,
-                                 *,
-                                 kill_action,
-                                 denylist=False):
+    def compile_filter_statement(self, filter_statement, *, kill_action):
         """Compile one parser.FilterStatement into BPF."""
         policy_entry = SyscallPolicyEntry(filter_statement.syscall.name,
                                           filter_statement.syscall.number,
@@ -326,7 +314,7 @@
         # false action taken here is the one that applies if the whole
         # expression fails to match.
         false_action = filter_statement.filters[-1].action
-        if not denylist and false_action == bpf.Allow():
+        if false_action == bpf.Allow():
             return policy_entry
         # We then traverse the list of filters backwards since we want
         # the root of the DAG to be the very first boolean operation in
diff --git a/tools/parser.py b/tools/parser.py
index 87e1493..0db0f62 100644
--- a/tools/parser.py
+++ b/tools/parser.py
@@ -31,12 +31,6 @@
     from minijail import bpf
 
 
-# Representations of numbers with different radix (base) in C.
-HEX_REGEX = r'-?0[xX][0-9a-fA-F]+'
-OCTAL_REGEX = r'-?0[0-7]+'
-DECIMAL_REGEX = r'-?[0-9]+'
-
-
 Token = collections.namedtuple(
     'Token', ['type', 'value', 'filename', 'line', 'line_number', 'column'])
 
@@ -48,9 +42,8 @@
     ('DEFAULT', r'@default\b'),
     ('INCLUDE', r'@include\b'),
     ('FREQUENCY', r'@frequency\b'),
-    ('DENYLIST', r'@denylist$'),
     ('PATH', r'(?:\.)?/\S+'),
-    ('NUMERIC_CONSTANT', f'{HEX_REGEX}|{OCTAL_REGEX}|{DECIMAL_REGEX}'),
+    ('NUMERIC_CONSTANT', r'-?0[xX][0-9a-fA-F]+|-?0[Oo][0-7]+|-?[0-9]+'),
     ('COLON', r':'),
     ('SEMICOLON', r';'),
     ('COMMA', r','),
@@ -226,21 +219,14 @@
                  *,
                  kill_action,
                  include_depth_limit=10,
-                 override_default_action=None,
-                 denylist=False,
-                 ret_log=False):
+                 override_default_action=None):
         self._parser_states = [ParserState("<memory>")]
         self._kill_action = kill_action
         self._include_depth_limit = include_depth_limit
-        if denylist:
-            self._default_action = bpf.Allow()
-        else:
-            self._default_action = self._kill_action
+        self._default_action = self._kill_action
         self._override_default_action = override_default_action
         self._frequency_mapping = collections.defaultdict(int)
         self._arch = arch
-        self._denylist = denylist
-        self._ret_log = ret_log
 
     @property
     def _parser_state(self):
@@ -255,21 +241,8 @@
                 self._parser_state.error('invalid constant', token=token)
             single_constant = self._arch.constants[token.value]
         elif token.type == 'NUMERIC_CONSTANT':
-            # As `int(_, 0)` in Python != `strtol(_, _, 0)` in C, to make sure
-            # the number parsing behaves exactly in C, instead of using `int()`
-            # directly, we list out all the possible formats for octal, decimal
-            # and hex numbers, and determine the corresponding base by regex.
             try:
-                if re.match(HEX_REGEX, token.value):
-                    base = 16
-                elif re.match(OCTAL_REGEX, token.value):
-                    base = 8
-                elif re.match(DECIMAL_REGEX, token.value):
-                    base = 10
-                else:
-                    # This should never happen.
-                    raise ValueError
-                single_constant = int(token.value, base=base)
+                single_constant = int(token.value, base=0)
             except ValueError:
                 self._parser_state.error('invalid constant', token=token)
         else:
@@ -317,7 +290,7 @@
 
         Constants can be:
 
-        - A number that can be parsed with strtol() in C.
+        - A number that can be parsed with int(..., base=0)
         - A named constant expression.
         - A parenthesized, valid constant expression.
         - A valid constant expression prefixed with the unary bitwise
@@ -433,11 +406,6 @@
         if not tokens:
             self._parser_state.error('missing action')
         action_token = tokens.pop(0)
-        # denylist policies must specify a return for every line.
-        if self._denylist:
-            if action_token.type != 'RETURN':
-                self._parser_state.error('invalid denylist policy')
-
         if action_token.type == 'ACTION':
             if action_token.value == 'allow':
                 return bpf.Allow()
@@ -462,22 +430,17 @@
         elif action_token.type == 'RETURN':
             if not tokens:
                 self._parser_state.error('missing return value')
-            if self._ret_log:
-                tokens.pop(0)
-                return bpf.Log()
-            else:
-                return bpf.ReturnErrno(self._parse_single_constant(tokens.pop(0)))
+            return bpf.ReturnErrno(self._parse_single_constant(tokens.pop(0)))
         return self._parser_state.error('invalid action', token=action_token)
 
     # single-filter = action
     #               | argument-expression , [ ';' , action ]
-    #               | '!','(', argument-expression, [ ';', action ], ')'
     #               ;
     def _parse_single_filter(self, tokens):
         if not tokens:
             self._parser_state.error('missing filter')
         if tokens[0].type == 'ARGUMENT':
-	    # Only argument expressions can start with an ARGUMENT token.
+            # Only argument expressions can start with an ARGUMENT token.
             argument_expression = self.parse_argument_expression(tokens)
             if tokens and tokens[0].type == 'SEMICOLON':
                 tokens.pop(0)
@@ -734,7 +697,6 @@
         self._parser_states.append(ParserState(filename))
         try:
             statements = []
-            denylist_header = False
             with open(filename) as policy_file:
                 for tokens in self._parser_state.tokenize(policy_file):
                     if tokens[0].type == 'INCLUDE':
@@ -748,14 +710,6 @@
                     elif tokens[0].type == 'DEFAULT':
                         self._default_action = self._parse_default_statement(
                             tokens)
-                    elif tokens[0].type == 'DENYLIST':
-                        tokens.pop()
-                        if not self._denylist:
-                            self._parser_state.error('policy is denylist, but '
-                                                     'flag --denylist not '
-                                                     'passed in.')
-                        else:
-                            denylist_header = True
                     else:
                         statement = self.parse_filter_statement(tokens)
                         if statement is None:
@@ -767,9 +721,6 @@
                     if tokens:
                         self._parser_state.error(
                             'extra tokens', token=tokens[0])
-            if self._denylist and not denylist_header:
-                self._parser_state.error('policy must contain @denylist flag to'
-                                         ' be compiled with --denylist flag.')
             return statements
         finally:
             self._parser_states.pop()
diff --git a/tools/parser_unittest.py b/tools/parser_unittest.py
index 9e7d6d8..1570e51 100755
--- a/tools/parser_unittest.py
+++ b/tools/parser_unittest.py
@@ -60,7 +60,7 @@
         ])
         self.assertEqual(
             [(token.type, token.value) for token in TokenizerTests._tokenize(
-                'read: arg0 in ~0xffff || arg0 & (1|2) && arg0 == 0755; '
+                'read: arg0 in ~0xffff || arg0 & (1|2) && arg0 == 0o755; '
                 'return ENOSYS # ignored')], [
                     ('IDENTIFIER', 'read'),
                     ('COLON', ':'),
@@ -79,7 +79,7 @@
                     ('AND', '&&'),
                     ('ARGUMENT', 'arg0'),
                     ('OP', '=='),
-                    ('NUMERIC_CONSTANT', '0755'),
+                    ('NUMERIC_CONSTANT', '0o755'),
                     ('SEMICOLON', ';'),
                     ('RETURN', 'return'),
                     ('IDENTIFIER', 'ENOSYS'),
@@ -276,27 +276,6 @@
                      parser.Atom(1, '==', 2)],
                 ])
 
-    def test_parse_number_argument_expression(self):
-        """Accept valid argument expressions with any octal/decimal/hex number."""
-        # 4607 == 010777 == 0x11ff
-        self.assertEqual(
-            self.parser.parse_argument_expression(
-                self._tokenize('arg0 in 4607')), [
-                    [parser.Atom(0, 'in', 4607)],
-            ])
-
-        self.assertEqual(
-            self.parser.parse_argument_expression(
-                self._tokenize('arg0 in 010777')), [
-                    [parser.Atom(0, 'in', 4607)],
-            ])
-
-        self.assertEqual(
-            self.parser.parse_argument_expression(
-                self._tokenize('arg0 in 0x11ff')), [
-                    [parser.Atom(0, 'in', 4607)],
-            ])
-
     def test_parse_empty_argument_expression(self):
         """Reject empty argument expressions."""
         with self.assertRaisesRegex(parser.ParseException,
@@ -416,29 +395,6 @@
             self.parser.parse_filter(self._tokenize('{ allow'))
 
 
-class ParseFilterDenylistTests(unittest.TestCase):
-    """Tests for PolicyParser.parse_filter with a denylist policy."""
-
-    def setUp(self):
-        self.arch = ARCH_64
-        self.kill_action = bpf.KillProcess()
-        self.parser = parser.PolicyParser(
-            self.arch, kill_action=self.kill_action, denylist=True)
-
-    def _tokenize(self, line):
-        # pylint: disable=protected-access
-        return list(self.parser._parser_state.tokenize([line]))[0]
-
-    def test_parse_filter(self):
-        """Accept only filters that return an errno."""
-        self.assertEqual(
-            self.parser.parse_filter(self._tokenize('arg0 == 0; return ENOSYS')),
-            [
-                parser.Filter([[parser.Atom(0, '==', 0)]],
-                bpf.ReturnErrno(self.arch.constants['ENOSYS'])),
-            ])
-
-
 class ParseFilterStatementTests(unittest.TestCase):
     """Tests for PolicyParser.parse_filter_statement."""
 
@@ -912,112 +868,6 @@
                  r'applied')):
             self.parser.parse_file(path)
 
-    def test_parse_allowlist_denylist_header(self):
-        """Reject trying to compile denylist policy file as allowlist."""
-        with self.assertRaisesRegex(parser.ParseException,
-                                    r'policy is denylist, but flag --denylist '
-                                    'not passed in'):
-            path = self._write_file(
-                'test.policy', """
-                @denylist
-            """)
-            self.parser.parse_file(path)
-
-
-class ParseFileDenylistTests(unittest.TestCase):
-    """Tests for PolicyParser.parse_file."""
-
-    def setUp(self):
-        self.arch = ARCH_64
-        self.kill_action = bpf.KillProcess()
-        self.parser = parser.PolicyParser(
-            self.arch, kill_action=self.kill_action, denylist=True)
-        self.tempdir = tempfile.mkdtemp()
-
-    def tearDown(self):
-        shutil.rmtree(self.tempdir)
-
-    def _write_file(self, filename, contents):
-        """Helper to write out a file for testing."""
-        path = os.path.join(self.tempdir, filename)
-        with open(path, 'w') as outf:
-            outf.write(contents)
-        return path
-
-    def test_parse_simple(self):
-        """Allow simple denylist policy files."""
-        path = self._write_file(
-            'test.policy', """
-            # Comment.
-            @denylist
-            read: return ENOSYS
-            write: return ENOSYS
-        """)
-
-        self.assertEqual(
-            self.parser.parse_file(path),
-            parser.ParsedPolicy(
-                default_action=bpf.Allow(),
-                filter_statements=[
-                    parser.FilterStatement(
-                        syscall=parser.Syscall('read', 0),
-                        frequency=1,
-                        filters=[
-                            parser.Filter(None, bpf.ReturnErrno(
-                                    self.arch.constants['ENOSYS'])),
-                        ]),
-                    parser.FilterStatement(
-                        syscall=parser.Syscall('write', 1),
-                        frequency=1,
-                        filters=[
-                            parser.Filter(None, bpf.ReturnErrno(
-                                    self.arch.constants['ENOSYS'])),
-                        ]),
-                ]))
-
-    def test_parse_simple_with_arg(self):
-        """Allow simple denylist policy files."""
-        path = self._write_file(
-            'test.policy', """
-            # Comment.
-            @denylist
-            read: return ENOSYS
-            write: arg0 == 0 ; return ENOSYS
-        """)
-
-        self.assertEqual(
-            self.parser.parse_file(path),
-            parser.ParsedPolicy(
-                default_action=bpf.Allow(),
-                filter_statements=[
-                    parser.FilterStatement(
-                        syscall=parser.Syscall('read', 0),
-                        frequency=1,
-                        filters=[
-                            parser.Filter(None, bpf.ReturnErrno(
-                                    self.arch.constants['ENOSYS'])),
-                        ]),
-                    parser.FilterStatement(
-                        syscall=parser.Syscall('write', 1),
-                        frequency=1,
-                        filters=[
-                            parser.Filter([[parser.Atom(0, '==', 0)]],
-                                bpf.ReturnErrno(self.arch.constants['ENOSYS'])),
-                            parser.Filter(None, bpf.Allow()),
-                        ]),
-                ]))
-
-
-    def test_parse_denylist_no_header(self):
-        """Reject trying to compile denylist policy file as allowlist."""
-        with self.assertRaisesRegex(parser.ParseException,
-                                    r'policy must contain @denylist flag to be '
-                                    'compiled with --denylist flag'):
-            path = self._write_file(
-                'test.policy', """
-                read: return ENOSYS
-            """)
-            self.parser.parse_file(path)
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tools/seccomp_policy_lint.py b/tools/seccomp_policy_lint.py
deleted file mode 100755
index f7621b0..0000000
--- a/tools/seccomp_policy_lint.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""A linter for the Minijail seccomp policy file."""
-
-import argparse
-import re
-import sys
-
-from typing import List, NamedTuple
-
-# The syscalls we have determined are more dangerous and need justification
-# for inclusion in a policy.
-DANGEROUS_SYSCALLS = (
-    'clone',
-    'mount',
-    'setns',
-    'kill',
-    'execve',
-    'execveat',
-    'bpf',
-    'socket',
-    'ptrace',
-    'swapon',
-    'swapoff',
-    # TODO(b/193169195): Add argument granularity for the below syscalls.
-    'prctl',
-    'ioctl',
-#   'mmap',
-#   'mprotect',
-#   'mmap2',
-)
-
-class CheckPolicyReturn(NamedTuple):
-    """Represents a return value from check_seccomp_policy
-
-    Contains a message to print to the user and a list of errors that were
-    found in the file.
-    """
-    message: str
-    errors: List[str]
-
-def parse_args(argv):
-    """Return the parsed CLI arguments for this tool."""
-    parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument(
-        '--denylist',
-        action='store_true',
-        help='Check as a denylist policy rather than the default allowlist.')
-    parser.add_argument(
-        '--dangerous-syscalls',
-        action='store',
-        default=','.join(DANGEROUS_SYSCALLS),
-        help='Comma-separated list of dangerous sycalls (overrides default).'
-    )
-    parser.add_argument('policy',
-                            help='The seccomp policy.',
-                            type=argparse.FileType('r', encoding='utf-8'))
-    return parser.parse_args(argv), parser
-
-def check_seccomp_policy(check_file, dangerous_syscalls):
-    """Fail if the seccomp policy file has dangerous, undocumented syscalls.
-
-    Takes in a file object and a set of dangerous syscalls as arguments.
-    """
-
-    found_syscalls = set()
-    errors = []
-    msg = ''
-    contains_dangerous_syscall = False
-    prev_line_comment = False
-
-    for line_num, line in enumerate(check_file):
-        if re.match(r'^\s*#', line):
-            prev_line_comment = True
-        elif re.match(r'^\s*$', line):
-            # Empty lines shouldn't reset prev_line_comment.
-            continue
-        else:
-            match = re.match(fr'^\s*(\w*)\s*:', line)
-            if match:
-                syscall = match.group(1)
-                if syscall in found_syscalls:
-                    errors.append(f'{check_file.name}, line {line_num}: repeat '
-                                  f'syscall: {syscall}')
-                else:
-                    found_syscalls.add(syscall)
-                    for dangerous in dangerous_syscalls:
-                        if dangerous == syscall:
-                            # Dangerous syscalls must be preceded with a
-                            # comment.
-                            contains_dangerous_syscall = True
-                            if not prev_line_comment:
-                                errors.append(f'{check_file.name}, line '
-                                              f'{line_num}: {syscall} syscall '
-                                              'is a dangerous syscall so '
-                                              'requires a comment on the '
-                                              'preceding line')
-                prev_line_comment = False
-            else:
-                # This line is probably a continuation from the previous line.
-                # TODO(b/203216289): Support line breaks.
-                pass
-
-    if contains_dangerous_syscall:
-        msg = (f'seccomp: {check_file.name} contains dangerous syscalls, so'
-               ' requires review from chromeos-security@')
-    else:
-        msg = (f'seccomp: {check_file.name} does not contain any dangerous'
-               ' syscalls, so does not require review from'
-               ' chromeos-security@')
-
-    if errors:
-        return CheckPolicyReturn(msg, errors)
-
-    return CheckPolicyReturn(msg, errors)
-
-def main(argv=None):
-    """Main entrypoint."""
-
-    if argv is None:
-        argv = sys.argv[1:]
-
-    opts, _arg_parser = parse_args(argv)
-
-    check = check_seccomp_policy(opts.policy,
-                                 set(opts.dangerous_syscalls.split(',')))
-
-    formatted_items = ''
-    if check.errors:
-        item_prefix = '\n    * '
-        formatted_items = item_prefix + item_prefix.join(check.errors)
-
-    print('* ' + check.message + formatted_items)
-
-    return 1 if check.errors else 0
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv[1:]))
diff --git a/tools/seccomp_policy_lint_unittest.py b/tools/seccomp_policy_lint_unittest.py
deleted file mode 100644
index 192739f..0000000
--- a/tools/seccomp_policy_lint_unittest.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Unittests for the seccomp policy linter module."""
-
-from pathlib import Path
-import tempfile
-import unittest
-
-import seccomp_policy_lint
-
-class CheckSeccompPolicyTests(unittest.TestCase):
-    """Tests for check_seccomp_policy."""
-
-    def setUp(self):
-        self.tempdir = Path(tempfile.mkdtemp())
-
-    def _write_file(self, filename, contents):
-        """Helper to write out a file for testing."""
-        path = self.tempdir / filename
-        path.write_text(contents)
-        return path
-
-    def test_check_simple(self):
-        """Allow simple policy files."""
-        path = self._write_file(
-            'test.policy', """
-            # Comment.\n
-            read: 1\n
-            write: 1\n
-        """)
-
-        exp_out = seccomp_policy_lint.CheckPolicyReturn(
-                    f'seccomp: {path.resolve()} does not contain any dangerous'
-                    ' syscalls, so does not require review from'
-                    ' chromeos-security@',
-                    [])
-
-        with path.open('r', encoding='utf-8') as check_file:
-            self.assertEqual(seccomp_policy_lint.check_seccomp_policy(
-                    check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS),
-                    exp_out)
-
-    def test_check_dangerous_comment(self):
-        """Dangerous syscalls must have a comment and need to be reviewed."""
-        path = self._write_file(
-            'test.policy', """
-            # Comment.\n\n\n
-            clone: 1\n
-            write: 1\n
-        """)
-
-        exp_out = seccomp_policy_lint.CheckPolicyReturn(
-                    f'seccomp: {path.resolve()} contains dangerous syscalls,'
-                    ' so requires review from chromeos-security@',
-                    [])
-
-        with path.open('r', encoding='utf-8') as check_file:
-            self.assertEqual(seccomp_policy_lint.check_seccomp_policy(
-                    check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS),
-                    exp_out)
-
-    def test_check_dangerous_no_comment(self):
-        """Dangerous syscalls without a comment should cause an error."""
-        path = self._write_file(
-            'test.policy', """
-            # Comment.\n
-            mount: 1\n
-            clone: 1\n
-        """)
-
-        exp_out = seccomp_policy_lint.CheckPolicyReturn(
-                    f'seccomp: {path.resolve()} contains dangerous syscalls,'
-                    ' so requires review from chromeos-security@',
-                   [(f'{path.resolve()}, line 5: clone syscall is a dangerous '
-                   'syscall so requires a comment on the preceding line')])
-
-        with path.open('r', encoding='utf-8') as check_file:
-            self.assertEqual(seccomp_policy_lint.check_seccomp_policy(
-                    check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS),
-                    exp_out)
-
-    def test_check_duplicate_syscall(self):
-        """Policy files cannot have duplicate syscalls.."""
-        path = self._write_file(
-            'test.policy', """
-            # Comment.\n
-            clone: 1\n
-            clone: arg0 == 3
-        """)
-
-        exp_out = seccomp_policy_lint.CheckPolicyReturn(
-                    f'seccomp: {path.resolve()} contains dangerous syscalls,'
-                    ' so requires review from chromeos-security@',
-                   [(f'{path.resolve()}, line 5: repeat syscall: clone')])
-
-        with path.open('r', encoding='utf-8') as check_file:
-            self.assertEqual(seccomp_policy_lint.check_seccomp_policy(
-                    check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS),
-                    exp_out)
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/util.c b/util.c
index f715b19..0926866 100644
--- a/util.c
+++ b/util.c
@@ -35,37 +35,34 @@
  */
 #if defined(__x86_64__)
 #if defined(__ANDROID__)
-const char *const log_syscalls[] = {"socket", "connect", "fcntl", "writev"};
+const char *log_syscalls[] = {"socket", "connect", "fcntl", "writev"};
 #else
-const char *const log_syscalls[] = {"socket", "connect", "sendto", "writev"};
+const char *log_syscalls[] = {"socket", "connect", "sendto", "writev"};
 #endif
 #elif defined(__i386__)
 #if defined(__ANDROID__)
-const char *const log_syscalls[] = {"socketcall", "writev", "fcntl64",
-				    "clock_gettime"};
+const char *log_syscalls[] = {"socketcall", "writev", "fcntl64",
+			      "clock_gettime"};
 #else
-const char *const log_syscalls[] = {"socketcall", "time", "writev"};
+const char *log_syscalls[] = {"socketcall", "time", "writev"};
 #endif
 #elif defined(__arm__)
 #if defined(__ANDROID__)
-const char *const log_syscalls[] = {"clock_gettime", "connect", "fcntl64",
-				    "socket", "writev"};
+const char *log_syscalls[] = {"clock_gettime", "connect", "fcntl64", "socket",
+			      "writev"};
 #else
-const char *const log_syscalls[] = {"socket", "connect", "gettimeofday", "send",
-				    "writev"};
+const char *log_syscalls[] = {"socket", "connect", "gettimeofday", "send",
+			      "writev"};
 #endif
 #elif defined(__aarch64__)
 #if defined(__ANDROID__)
-const char *const log_syscalls[] = {"connect", "fcntl", "sendto", "socket",
-				    "writev"};
+const char *log_syscalls[] = {"connect", "fcntl", "sendto", "socket", "writev"};
 #else
-const char *const log_syscalls[] = {"socket", "connect", "send", "writev"};
+const char *log_syscalls[] = {"socket", "connect", "send", "writev"};
 #endif
 #elif defined(__powerpc__) || defined(__ia64__) || defined(__hppa__) ||        \
-    defined(__sparc__) || defined(__mips__)
-const char *const log_syscalls[] = {"socket", "connect", "send"};
-#elif defined(__riscv)
-const char *const log_syscalls[] = {"socket", "connect", "sendto"};
+      defined(__sparc__) || defined(__mips__)
+const char *log_syscalls[] = {"socket", "connect", "send"};
 #else
 #error "Unsupported platform"
 #endif
@@ -443,10 +440,16 @@
 
 char *path_join(const char *external_path, const char *internal_path)
 {
-	char *path = NULL;
-	return asprintf(&path, "%s/%s", external_path, internal_path) < 0
-		   ? NULL
-		   : path;
+	char *path;
+	size_t pathlen;
+
+	/* One extra char for '/' and one for '\0', hence + 2. */
+	pathlen = strlen(external_path) + strlen(internal_path) + 2;
+	path = malloc(pathlen);
+	if (path)
+		snprintf(path, pathlen, "%s/%s", external_path, internal_path);
+
+	return path;
 }
 
 void *consumebytes(size_t length, char **buf, size_t *buflength)
@@ -511,46 +514,24 @@
 	return copy;
 }
 
-/*
- * Utility function used by minijail_setenv, minijail_unsetenv and
- * minijail_getenv, returns true if |name| is found, false if not.
- * If found, |*i| is |name|'s index. If not, |*i| is the length of |envp|.
- */
-static bool getenv_index(char **envp, const char *name, int *i) {
-	if (!envp || !name || !i)
-		return false;
-
-	size_t name_len = strlen(name);
-	for (*i = 0; envp[*i]; ++(*i)) {
-		/*
-		 * If we find a match the size of |name|, we must check
-		 * that the next character is a '=', indicating that
-		 * the full varname of envp[i] is exactly |name| and
-		 * not just happening to start with |name|.
-		 */
-		if (!strncmp(envp[*i], name, name_len) &&
-		    (envp[*i][name_len] == '=')) {
-			return true;
-		}
-	}
-	/* No match found, |*i| contains the number of elements in |envp|. */
-	return false;
-}
-
 int minijail_setenv(char ***env, const char *name, const char *value,
 		    int overwrite)
 {
 	if (!env || !*env || !name || !*name || !value)
 		return EINVAL;
 
-	char **dest = NULL;
-	int i;
+	size_t name_len = strlen(name);
 
-	/* Look in env to check if this var name already exists. */
-	if (getenv_index(*env, name, &i)) {
-		if (!overwrite)
-			return 0;
-		dest = &(*env)[i];
+	char **dest = NULL;
+	size_t env_len = 0;
+	for (char **entry = *env; *entry; ++entry, ++env_len) {
+		if (!dest && strncmp(name, *entry, name_len) == 0 &&
+		    (*entry)[name_len] == '=') {
+			if (!overwrite)
+				return 0;
+
+			dest = entry;
+		}
 	}
 
 	char *new_entry = NULL;
@@ -563,87 +544,15 @@
 		return 0;
 	}
 
-	/* getenv_index has set |i| to the length of |env|. */
-	++i;
-	char **new_env = realloc(*env, (i + 1) * sizeof(char *));
+	env_len++;
+	char **new_env = realloc(*env, (env_len + 1) * sizeof(char *));
 	if (!new_env) {
 		free(new_entry);
 		return ENOMEM;
 	}
 
-	new_env[i - 1] = new_entry;
-	new_env[i] = NULL;
+	new_env[env_len - 1] = new_entry;
+	new_env[env_len] = NULL;
 	*env = new_env;
 	return 0;
 }
-
-/*
- * This is like getline() but supports line wrapping with \.
- */
-ssize_t getmultiline(char **lineptr, size_t *n, FILE *stream)
-{
-	ssize_t ret = getline(lineptr, n, stream);
-	if (ret < 0)
-		return ret;
-
-	char *line = *lineptr;
-	/* Eat the newline to make processing below easier. */
-	if (ret > 0 && line[ret - 1] == '\n')
-		line[--ret] = '\0';
-
-	/* If the line doesn't end in a backslash, we're done. */
-	if (ret <= 0 || line[ret - 1] != '\\')
-		return ret;
-
-	/* This line ends in a backslash. Get the nextline. */
-	line[--ret] = '\0';
-	size_t next_n = 0;
-	attribute_cleanup_str char *next_line = NULL;
-	ssize_t next_ret = getmultiline(&next_line, &next_n, stream);
-	if (next_ret == -1) {
-		/* We couldn't fully read the line, so return an error. */
-		return -1;
-	}
-
-	/* Merge the lines. */
-	*n = ret + next_ret + 2;
-	line = realloc(line, *n);
-	if (!line)
-		return -1;
-	line[ret] = ' ';
-	memcpy(&line[ret + 1], next_line, next_ret + 1);
-	*lineptr = line;
-	return *n - 1;
-}
-
-char *minijail_getenv(char **envp, const char *name) {
-	if (!envp || !name)
-		return NULL;
-
-	int i;
-	if (!getenv_index(envp, name, &i))
-		return NULL;
-
-	/* Return a ptr to the value after the '='. */
-	return envp[i] + strlen(name) + 1;
-}
-
-bool minijail_unsetenv(char **envp, const char *name)
-{
-	if (!envp || !name)
-		return false;
-
-	int i;
-	if (!getenv_index(envp, name, &i))
-		return false;
-
-	/* We found a match, replace it by the last entry of the array. */
-	int last;
-	for (last = i; envp[last]; ++last)
-		continue;
-	--last;
-	envp[i] = envp[last];
-	envp[last] = NULL;
-
-	return true;
-}
diff --git a/util.h b/util.h
index 5ed9f94..359ce95 100644
--- a/util.h
+++ b/util.h
@@ -55,72 +55,6 @@
 #define attribute_printf(format_idx, check_idx) \
 	__attribute__((__format__(__printf__, format_idx, check_idx)))
 
-#ifndef __cplusplus
-/* If writing C++, use std::unique_ptr with a destructor instead. */
-
-/*
- * Mark a local variable for automatic cleanup when exiting its scope.
- * See attribute_cleanup_fp as an example below.
- * Make sure any variable using this is always initialized to something.
- * @func The function to call on (a pointer to) the variable.
- */
-#define attribute_cleanup(func) \
-	__attribute__((__cleanup__(func)))
-
-/*
- * Automatically close a FILE* when exiting its scope.
- * Make sure the pointer is always initialized.
- * Some examples:
- *   attribute_cleanup_fp FILE *fp = fopen(...);
- *   attribute_cleanup_fp FILE *fp = NULL;
- *   ...
- *   fp = fopen(...);
- *
- * NB: This will automatically close the underlying fd, so do not use this
- * with fdopen calls if the fd should be left open.
- */
-#define attribute_cleanup_fp attribute_cleanup(_cleanup_fp)
-static inline void _cleanup_fp(FILE **fp)
-{
-	if (*fp)
-		fclose(*fp);
-}
-
-/*
- * Automatically close a fd when exiting its scope.
- * Make sure the fd is always initialized.
- * Some examples:
- *   attribute_cleanup_fd int fd = open(...);
- *   attribute_cleanup_fd int fd = -1;
- *   ...
- *   fd = open(...);
- *
- * NB: Be careful when using this with attribute_cleanup_fp and fdopen.
- */
-#define attribute_cleanup_fd attribute_cleanup(_cleanup_fd)
-static inline void _cleanup_fd(int *fd)
-{
-	if (*fd >= 0)
-		close(*fd);
-}
-
-/*
- * Automatically free a heap allocation when exiting its scope.
- * Make sure the pointer is always initialized.
- * Some examples:
- *   attribute_cleanup_str char *s = strdup(...);
- *   attribute_cleanup_str char *s = NULL;
- *   ...
- *   s = strdup(...);
- */
-#define attribute_cleanup_str attribute_cleanup(_cleanup_str)
-static inline void _cleanup_str(char **ptr)
-{
-	free(*ptr);
-}
-
-#endif /* __cplusplus */
-
 /* clang-format off */
 #define die(_msg, ...) \
 	do_fatal_log(LOG_ERR, "libminijail[%d]: " _msg, getpid(), ## __VA_ARGS__)
@@ -140,7 +74,7 @@
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 /* clang-format on */
 
-extern const char *const log_syscalls[];
+extern const char *log_syscalls[];
 extern const size_t log_syscalls_len;
 
 enum logging_system_t {
@@ -202,8 +136,7 @@
 	return compiled_with_asan() || &__asan_init != 0 || &__hwasan_init != 0;
 }
 
-static inline bool debug_logging_allowed(void)
-{
+static inline bool debug_logging_allowed(void) {
 #if defined(ALLOW_DEBUG_LOGGING)
 	return true;
 #else
@@ -211,15 +144,6 @@
 #endif
 }
 
-static inline bool seccomp_default_ret_log(void)
-{
-#if defined(SECCOMP_DEFAULT_RET_LOG)
-	return true;
-#else
-	return false;
-#endif
-}
-
 static inline size_t get_num_syscalls(void)
 {
 	return syscall_table_size;
@@ -274,7 +198,7 @@
  * @fd           The file descriptor to log into. Ignored unless
  *               @logger = LOG_TO_FD.
  * @min_priority The minimum priority to display. Corresponds to syslog's
- *               priority parameter. Ignored unless @logger = LOG_TO_FD.
+                 priority parameter. Ignored unless @logger = LOG_TO_FD.
  */
 void init_logging(enum logging_system_t logger, int fd, int min_priority);
 
@@ -318,45 +242,6 @@
 int minijail_setenv(char ***env, const char *name, const char *value,
 		    int overwrite);
 
-/*
- * getmultiline: This is like getline() but supports line wrapping with \.
- *
- * @lineptr    Address of a buffer that a mutli-line is stored.
- * @n          Number of bytes stored in *lineptr.
- * @stream     Input stream to read from.
- *
- * Returns number of bytes read or -1 on failure to read (including EOF).
- */
-ssize_t getmultiline(char **lineptr, size_t *n, FILE *stream);
-
-/*
- * minjail_getenv: Get an environment variable from @envp. Semantics match the
- * standard getenv() function, but this operates on @envp, not the global
- * environment (usually referred to as `extern char **environ`).
- *
- * @env       Address of the environment to read from.
- * @name      Name of the key to get.
- *
- * Returns a pointer to the corresponding environment value. The caller must
- * take care not to modify the pointed value, as this points directly to memory
- * pointed to by @envp.
- * If the environment variable name is not found, returns NULL.
- */
-char *minijail_getenv(char **env, const char *name);
-
-/*
- * minjail_unsetenv: Clear the environment variable @name from the @envp array
- * of pointers to strings that have the KEY=VALUE format. If the operation is
- * successful, the array will contain one item less than before the call.
- * Only the first occurence is removed.
- *
- * @envp      Address of the environment to clear the variable from.
- * @name      Name of the variable to clear.
- *
- * Returns false and modifies *@envp on success, returns true otherwise.
- */
-bool minijail_unsetenv(char **envp, const char *name);
-
 #ifdef __cplusplus
 }; /* extern "C" */
 #endif
diff --git a/util_unittest.cc b/util_unittest.cc
index b9e6dfc..35a99e5 100644
--- a/util_unittest.cc
+++ b/util_unittest.cc
@@ -14,7 +14,6 @@
 #include <gtest/gtest.h>
 
 #include "bpf.h"
-#include "test_util.h"
 #include "util.h"
 
 namespace {
@@ -158,42 +157,6 @@
   EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
             dump_env(env));
 
-  EXPECT_EQ(nullptr, minijail_getenv(nullptr, "dup"));
-  EXPECT_EQ(nullptr, minijail_getenv(nullptr, nullptr));
-  EXPECT_EQ(nullptr, minijail_getenv(env, nullptr));
-  EXPECT_EQ(nullptr, minijail_getenv(env, "dup="));
-  EXPECT_EQ(nullptr, minijail_getenv(env, "du"));
-  EXPECT_EQ(std::string("8"), minijail_getenv(env, "new2"));
-  EXPECT_EQ(std::string("3"), minijail_getenv(env, "val1"));
-  EXPECT_EQ(std::string("5"), minijail_getenv(env, "dup"));
-
-  EXPECT_EQ(false, minijail_unsetenv(env, "nonexisting"));
-  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
-            dump_env(env));
-  EXPECT_EQ(false, minijail_unsetenv(env, ""));
-  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
-            dump_env(env));
-  EXPECT_EQ(false, minijail_unsetenv(env, nullptr));
-  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
-            dump_env(env));
-  EXPECT_EQ(false, minijail_unsetenv(nullptr, nullptr));
-  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
-            dump_env(env));
-  EXPECT_EQ(false, minijail_unsetenv(nullptr, "nonexisting"));
-  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
-            dump_env(env));
-  EXPECT_EQ(false, minijail_unsetenv(env, "val1="));
-  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
-            dump_env(env));
-  EXPECT_EQ(true, minijail_unsetenv(env, "val1"));
-  EXPECT_EQ("new2=8\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\n", dump_env(env));
-  EXPECT_EQ(true, minijail_unsetenv(env, "empty"));
-  EXPECT_EQ("new2=8\nval2=4\ndup=5\ndup=2\nnew1=7\n", dump_env(env));
-  EXPECT_EQ(true, minijail_unsetenv(env, "new2"));
-  EXPECT_EQ("new1=7\nval2=4\ndup=5\ndup=2\n", dump_env(env));
-  EXPECT_EQ(true, minijail_unsetenv(env, "new1"));
-  EXPECT_EQ("dup=2\nval2=4\ndup=5\n", dump_env(env));
-
   minijail_free_env(env);
 }
 
@@ -395,36 +358,3 @@
   ASSERT_EQ(-EINVAL, parse_size(&size, "-1G"));
   ASSERT_EQ(-EINVAL, parse_size(&size, "; /bin/rm -- "));
 }
-
-TEST(path_join, basic) {
-  char *path = path_join("a", "b");
-  ASSERT_EQ(std::string("a/b"), path);
-  free(path);
-}
-
-TEST(getmultiline, basic) {
-  std::string config =
-           "\n"
-           "mount = none\n"
-           "mount =\\\n"
-           "none\n"
-           "binding = none,/tmp\n"
-           "binding = none,\\\n"
-           "/tmp";
-  FILE *config_file = write_to_pipe(config);
-  ASSERT_NE(config_file, nullptr);
-
-  char *line = NULL;
-  size_t len = 0;
-  ASSERT_EQ(0, getmultiline(&line, &len, config_file));
-  EXPECT_EQ(std::string(line), "");
-  ASSERT_EQ(12, getmultiline(&line, &len, config_file));
-  EXPECT_EQ(std::string(line), "mount = none");
-  ASSERT_EQ(12, getmultiline(&line, &len, config_file));
-  EXPECT_EQ(std::string(line), "mount = none");
-  ASSERT_EQ(19, getmultiline(&line, &len, config_file));
-  EXPECT_EQ(std::string(line), "binding = none,/tmp");
-  ASSERT_EQ(20, getmultiline(&line, &len, config_file));
-  EXPECT_EQ(std::string(line), "binding = none, /tmp");
-  free(line);
-}