selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] libsepol/cil: move the fuzz target and build script to the selinux repository
@ 2021-07-13  0:04 Evgeny Vereshchagin
  2021-07-13 19:51 ` Nicolas Iooss
  0 siblings, 1 reply; 5+ messages in thread
From: Evgeny Vereshchagin @ 2021-07-13  0:04 UTC (permalink / raw)
  To: selinux

It should make it easier to reproduce bugs found by OSS-Fuzz locally
without docker. The fuzz target can be built and run with the corpus
OSS-Fuzz has accumulated so far by running the following commands:
```
./scripts/oss-fuzz.sh
wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
unzip -d CORPUS public.zip
./out/secilc-fuzzer CORPUS/
```

It was tested in https://github.com/google/oss-fuzz/pull/6026
by pointing OSS-Fuzz to the branch containing the patch and
running all the tests with all the sanitizers and fuzzing engines
there: https://github.com/google/oss-fuzz/actions/runs/1024673143

Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>
---
 libsepol/fuzz/secilc-fuzzer.c | 69 +++++++++++++++++++++++++++++++++++
 scripts/oss-fuzz.sh           | 28 ++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 libsepol/fuzz/secilc-fuzzer.c
 create mode 100755 scripts/oss-fuzz.sh

diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c
new file mode 100644
index 00000000..255b3241
--- /dev/null
+++ b/libsepol/fuzz/secilc-fuzzer.c
@@ -0,0 +1,69 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/stat.h>
+
+#include <sepol/cil/cil.h>
+#include <sepol/policydb.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+	enum cil_log_level log_level = CIL_ERR;
+	struct sepol_policy_file *pf = NULL;
+	FILE *dev_null = NULL;
+	int target = SEPOL_TARGET_SELINUX;
+	int disable_dontaudit = 0;
+	int multiple_decls = 0;
+	int disable_neverallow = 0;
+	int preserve_tunables = 0;
+	int policyvers = POLICYDB_VERSION_MAX;
+	int mls = -1;
+	int attrs_expand_generated = 0;
+	struct cil_db *db = NULL;
+	sepol_policydb_t *pdb = NULL;
+
+	cil_set_log_level(log_level);
+
+	cil_db_init(&db);
+	cil_set_disable_dontaudit(db, disable_dontaudit);
+	cil_set_multiple_decls(db, multiple_decls);
+	cil_set_disable_neverallow(db, disable_neverallow);
+	cil_set_preserve_tunables(db, preserve_tunables);
+	cil_set_mls(db, mls);
+	cil_set_target_platform(db, target);
+	cil_set_policy_version(db, policyvers);
+	cil_set_attrs_expand_generated(db, attrs_expand_generated);
+
+	if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK)
+		goto exit;
+
+	if (cil_compile(db) != SEPOL_OK)
+		goto exit;
+
+	if (cil_build_policydb(db, &pdb) != SEPOL_OK)
+		goto exit;
+
+	if (sepol_policydb_optimize(pdb) != SEPOL_OK)
+		goto exit;
+
+	dev_null = fopen("/dev/null", "w");
+	if (dev_null == NULL)
+		goto exit;
+
+	if (sepol_policy_file_create(&pf) != 0)
+		goto exit;
+
+	sepol_policy_file_set_fp(pf, dev_null);
+
+	if (sepol_policydb_write(pdb, pf) != 0)
+		goto exit;
+exit:
+	if (dev_null != NULL)
+		fclose(dev_null);
+
+	cil_db_destroy(&db);
+	sepol_policydb_free(pdb);
+	sepol_policy_file_free(pf);
+	return 0;
+}
diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh
new file mode 100755
index 00000000..9e720a5c
--- /dev/null
+++ b/scripts/oss-fuzz.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+set -eux
+
+export DESTDIR=$(pwd)/DESTDIR
+
+SANITIZER=${SANITIZER:-address}
+flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link"
+
+export CC=${CC:-clang}
+export CFLAGS=${CFLAGS:-$flags}
+
+export CXX=${CXX:-clang++}
+export CXXFLAGS=${CXXFLAGS:-$flags}
+
+export LDFLAGS="${LDFLAGS:-} $CFLAGS"
+
+export OUT=${OUT:-$(pwd)/out}
+mkdir -p $OUT
+
+export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer}
+
+find -name Makefile | xargs sed -i 's/,-z,defs//'
+make V=1 -j$(nproc) install
+
+$CC $CFLAGS -I$DESTDIR/usr/include -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -c -o secilc-fuzzer.o libsepol/fuzz/secilc-fuzzer.c
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o $DESTDIR/usr/lib/libsepol.a -o $OUT/secilc-fuzzer
+zip -r $OUT/secilc-fuzzer_seed_corpus.zip secilc/test
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] libsepol/cil: move the fuzz target and build script to the selinux repository
  2021-07-13  0:04 [PATCH] libsepol/cil: move the fuzz target and build script to the selinux repository Evgeny Vereshchagin
@ 2021-07-13 19:51 ` Nicolas Iooss
  2021-07-15  6:11   ` [PATCH v2] " Evgeny Vereshchagin
  0 siblings, 1 reply; 5+ messages in thread
From: Nicolas Iooss @ 2021-07-13 19:51 UTC (permalink / raw)
  To: Evgeny Vereshchagin; +Cc: SElinux list

On Tue, Jul 13, 2021 at 2:05 AM Evgeny Vereshchagin <evvers@ya.ru> wrote:
>
> It should make it easier to reproduce bugs found by OSS-Fuzz locally
> without docker. The fuzz target can be built and run with the corpus
> OSS-Fuzz has accumulated so far by running the following commands:
> ```
> ./scripts/oss-fuzz.sh
> wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
> unzip -d CORPUS public.zip
> ./out/secilc-fuzzer CORPUS/
> ```

Hello,
Thanks for this patch! I have a couple of comments to improve it.

First, the instructions you gave (with wget + unzip) are useful and in
my humble opinion, they could be documented for example in a comment
at the beginning of scripts/oss-fuzz.sh ("# Usage: ...").

Second, shellcheck (https://www.shellcheck.net/)  reports many
warnings, such as missing quotes:

In scripts/oss-fuzz.sh line 19:
mkdir -p $OUT
         ^--^ SC2086: Double quote to prevent globbing and word splitting.

Even though naming directories with spaces breaks many tools, it is
good practice to avoid introducing more breakage, which is why quoting
paths is required. Could you please take a look at shellcheck output
and fix the issues it identifies?

More comments below...

> It was tested in https://github.com/google/oss-fuzz/pull/6026
> by pointing OSS-Fuzz to the branch containing the patch and
> running all the tests with all the sanitizers and fuzzing engines
> there: https://github.com/google/oss-fuzz/actions/runs/1024673143
>
> Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>
> ---
>  libsepol/fuzz/secilc-fuzzer.c | 69 +++++++++++++++++++++++++++++++++++
>  scripts/oss-fuzz.sh           | 28 ++++++++++++++
>  2 files changed, 97 insertions(+)
>  create mode 100644 libsepol/fuzz/secilc-fuzzer.c
>  create mode 100755 scripts/oss-fuzz.sh
>
> diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c
> new file mode 100644
> index 00000000..255b3241
> --- /dev/null
> +++ b/libsepol/fuzz/secilc-fuzzer.c
> @@ -0,0 +1,69 @@
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <getopt.h>
> +#include <sys/stat.h>
> +
> +#include <sepol/cil/cil.h>
> +#include <sepol/policydb.h>
> +
> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
> +       enum cil_log_level log_level = CIL_ERR;
> +       struct sepol_policy_file *pf = NULL;
> +       FILE *dev_null = NULL;
> +       int target = SEPOL_TARGET_SELINUX;
> +       int disable_dontaudit = 0;
> +       int multiple_decls = 0;
> +       int disable_neverallow = 0;
> +       int preserve_tunables = 0;
> +       int policyvers = POLICYDB_VERSION_MAX;
> +       int mls = -1;
> +       int attrs_expand_generated = 0;
> +       struct cil_db *db = NULL;
> +       sepol_policydb_t *pdb = NULL;
> +
> +       cil_set_log_level(log_level);
> +
> +       cil_db_init(&db);
> +       cil_set_disable_dontaudit(db, disable_dontaudit);
> +       cil_set_multiple_decls(db, multiple_decls);
> +       cil_set_disable_neverallow(db, disable_neverallow);
> +       cil_set_preserve_tunables(db, preserve_tunables);
> +       cil_set_mls(db, mls);
> +       cil_set_target_platform(db, target);
> +       cil_set_policy_version(db, policyvers);
> +       cil_set_attrs_expand_generated(db, attrs_expand_generated);
> +
> +       if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK)
> +               goto exit;
> +
> +       if (cil_compile(db) != SEPOL_OK)
> +               goto exit;
> +
> +       if (cil_build_policydb(db, &pdb) != SEPOL_OK)
> +               goto exit;
> +
> +       if (sepol_policydb_optimize(pdb) != SEPOL_OK)
> +               goto exit;
> +
> +       dev_null = fopen("/dev/null", "w");
> +       if (dev_null == NULL)
> +               goto exit;
> +
> +       if (sepol_policy_file_create(&pf) != 0)
> +               goto exit;
> +
> +       sepol_policy_file_set_fp(pf, dev_null);
> +
> +       if (sepol_policydb_write(pdb, pf) != 0)
> +               goto exit;
> +exit:
> +       if (dev_null != NULL)
> +               fclose(dev_null);
> +
> +       cil_db_destroy(&db);
> +       sepol_policydb_free(pdb);
> +       sepol_policy_file_free(pf);
> +       return 0;
> +}
> diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh
> new file mode 100755
> index 00000000..9e720a5c
> --- /dev/null
> +++ b/scripts/oss-fuzz.sh
> @@ -0,0 +1,28 @@
> +#!/bin/bash
> +
> +set -eux
> +
> +export DESTDIR=$(pwd)/DESTDIR

It is strange that $OUT is configurable but not $DESTDIR. Please add a
way to specify DESTDIR too.

> +
> +SANITIZER=${SANITIZER:-address}
> +flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link"
> +
> +export CC=${CC:-clang}
> +export CFLAGS=${CFLAGS:-$flags}
> +
> +export CXX=${CXX:-clang++}
> +export CXXFLAGS=${CXXFLAGS:-$flags}
> +
> +export LDFLAGS="${LDFLAGS:-} $CFLAGS"

Why do you need to include CFLAGS in LDFLAGS?

> +
> +export OUT=${OUT:-$(pwd)/out}
> +mkdir -p $OUT
> +
> +export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer}
> +
> +find -name Makefile | xargs sed -i 's/,-z,defs//'

This is horrible for two reasons: it touches libsemanage/src/Makefile
even though the fuzzer only needs libsepol, and it modifies in-place
files which are versionned (with git).
I understand the issue you are trying to fix here is that building
with sanitizers leads to undefined symbols, but there are other
options:

* The most straightforward one is to prevent make from setting the
variable which adds "-z,defs", by building with "make ...
LD_SONAME_FLAGS="
* Another one consists in introducing a new Makefile variable, for
example named "ALLOW_UNDEFINED_SYMBOLS" and to modify the Makefiles to
only add -z,defs when this option is not defined.

> +make V=1 -j$(nproc) install

You do not need to build every sub-project. You can restrict the build
to libsepol with "make -C libsepol ...".

Moreover if the script is being launched from scripts/ ("cd scripts &&
./oss-fuzz.sh") this does not work. If you intend to be run from the
root directory, please insert a command which changes to the root
directory somewhere, like:

cd "$(dirname -- "$0")/.."

Or (if you do not want to chdir) please use a reference to this base
directory when you are using make and when you are compiling files.

Moreover if libsepol was already built, "make" will not rebuild it
even if the compiling option changed. Adding "make -C libsepol clean"
before invoking make could be useful.

> +
> +$CC $CFLAGS -I$DESTDIR/usr/include -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -c -o secilc-fuzzer.o libsepol/fuzz/secilc-fuzzer.c
> +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o $DESTDIR/usr/lib/libsepol.a -o $OUT/secilc-fuzzer

Why are you using a C++ compiler to link the files? To my knowledge,
the fuzzing/sanitizing options available to clang++ linker are the
same as with clang. It would make the script easier to use if only one
compiler was used, but you have a reason to prefer using clang++,
please add a comment (in the script) about this.

> +zip -r $OUT/secilc-fuzzer_seed_corpus.zip secilc/test
> --
> 2.31.1
>

So I believe there are few things to improve in your patch. If you
have questions or if you disagree with some of my comments, feel free
to discuss. (And if other SELinux maintainers/members want to comment,
feel free to do so too ;) ).

Thanks,
Nicolas


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2] libsepol/cil: move the fuzz target and build script to the selinux repository
  2021-07-13 19:51 ` Nicolas Iooss
@ 2021-07-15  6:11   ` Evgeny Vereshchagin
  2021-08-16  9:16     ` Nicolas Iooss
  0 siblings, 1 reply; 5+ messages in thread
From: Evgeny Vereshchagin @ 2021-07-15  6:11 UTC (permalink / raw)
  To: selinux; +Cc: nicolas.iooss

It should make it easier to reproduce bugs found by OSS-Fuzz locally
without docker. The fuzz target can be built and run with the corpus
OSS-Fuzz has accumulated so far by running the following commands:
```
./scripts/oss-fuzz.sh
wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
unzip -d CORPUS public.zip
./out/secilc-fuzzer CORPUS/
```

It was tested in https://github.com/google/oss-fuzz/pull/6026
by pointing OSS-Fuzz to the branch containing the patch and
running all the tests with all the sanitizers and fuzzing engines
there: https://github.com/google/oss-fuzz/actions/runs/1024673143

[v2]
[1] oss-fuzz: make shellcheck happy

[2] oss-fuzz: build libsepol only

The fuzz target covers libsepol so it's unnecessary to build everything
else. Apart from that, the "LDFLAGS" kludge was removed since libsepol
is compatible with the sanitizers flags passed via CFLAGS only. It
should be brought back one way or another eventually though to fix
build failures like
```
clang -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L../src  sefcontext_compile.o ../src/regex.o  -lselinux  -lpcre  ../src/libselinux.a -lsepol -o sefcontext_compile
/usr/bin/ld: sefcontext_compile.o: in function `usage':
/home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:271: undefined reference to `__asan_report_load8'
/usr/bin/ld: /home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:292: undefined reference to `__asan_handle_no_return'
/usr/bin/ld: sefcontext_compile.o: in function `asan.module_ctor':
```

[3] oss-fuzz: make it possible to run the script more than once
by removing various build artifacts

[4] oss-fuzz: make it possible to run the script from any directory

[5] oss-fuzz: be a little bit more specific about what the script does

[6] oss-fuzz: stop overwriting all the Makefiles

Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>
---
 libsepol/fuzz/secilc-fuzzer.c | 69 +++++++++++++++++++++++++++++++++++
 scripts/oss-fuzz.sh           | 59 ++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+)
 create mode 100644 libsepol/fuzz/secilc-fuzzer.c
 create mode 100755 scripts/oss-fuzz.sh

diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c
new file mode 100644
index 00000000..255b3241
--- /dev/null
+++ b/libsepol/fuzz/secilc-fuzzer.c
@@ -0,0 +1,69 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/stat.h>
+
+#include <sepol/cil/cil.h>
+#include <sepol/policydb.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+	enum cil_log_level log_level = CIL_ERR;
+	struct sepol_policy_file *pf = NULL;
+	FILE *dev_null = NULL;
+	int target = SEPOL_TARGET_SELINUX;
+	int disable_dontaudit = 0;
+	int multiple_decls = 0;
+	int disable_neverallow = 0;
+	int preserve_tunables = 0;
+	int policyvers = POLICYDB_VERSION_MAX;
+	int mls = -1;
+	int attrs_expand_generated = 0;
+	struct cil_db *db = NULL;
+	sepol_policydb_t *pdb = NULL;
+
+	cil_set_log_level(log_level);
+
+	cil_db_init(&db);
+	cil_set_disable_dontaudit(db, disable_dontaudit);
+	cil_set_multiple_decls(db, multiple_decls);
+	cil_set_disable_neverallow(db, disable_neverallow);
+	cil_set_preserve_tunables(db, preserve_tunables);
+	cil_set_mls(db, mls);
+	cil_set_target_platform(db, target);
+	cil_set_policy_version(db, policyvers);
+	cil_set_attrs_expand_generated(db, attrs_expand_generated);
+
+	if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK)
+		goto exit;
+
+	if (cil_compile(db) != SEPOL_OK)
+		goto exit;
+
+	if (cil_build_policydb(db, &pdb) != SEPOL_OK)
+		goto exit;
+
+	if (sepol_policydb_optimize(pdb) != SEPOL_OK)
+		goto exit;
+
+	dev_null = fopen("/dev/null", "w");
+	if (dev_null == NULL)
+		goto exit;
+
+	if (sepol_policy_file_create(&pf) != 0)
+		goto exit;
+
+	sepol_policy_file_set_fp(pf, dev_null);
+
+	if (sepol_policydb_write(pdb, pf) != 0)
+		goto exit;
+exit:
+	if (dev_null != NULL)
+		fclose(dev_null);
+
+	cil_db_destroy(&db);
+	sepol_policydb_free(pdb);
+	sepol_policy_file_free(pf);
+	return 0;
+}
diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh
new file mode 100755
index 00000000..16cc3c0a
--- /dev/null
+++ b/scripts/oss-fuzz.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+# The script is used to build the fuzz targets run on ClusterFuzz. It has to be
+# compatible with the "build.sh" script described at
+# https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh
+# More precisely, it should use environment variables like OUT, LIB_FUZZING_ENGINE
+# and so on (https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh-script-environment),
+# and the fuzz targets have to be linked with $CXX even though the project is written
+# in C: https://google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements
+
+# To make it easier to build the fuzz targets locally, the script can also work in "local"
+# mode. To run secilc-fuzzer against a test case (named, say, CRASH) triggering an issue
+# the following commands should be run
+#
+# $ ./scripts/oss-fuzz.sh
+# $ ./out/secilc-fuzzer CRASH
+
+# To run the fuzzer against the corpus OSS-Fuzz has accumulated so far it should be
+# downloaded, unpacked and passed to the fuzzer:
+#
+# $ wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
+# $ unzip -d CORPUS public.zip
+# $ ./out/secilc-fuzzer CORPUS/
+
+set -eux
+
+cd "$(dirname -- "$0")/.."
+
+export DESTDIR=${DESTDIR:-$(pwd)/DESTDIR}
+
+SANITIZER=${SANITIZER:-address}
+flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link"
+
+export CC=${CC:-clang}
+export CFLAGS=${CFLAGS:-$flags}
+
+export CXX=${CXX:-clang++}
+export CXXFLAGS=${CXXFLAGS:-$flags}
+
+export OUT=${OUT:-$(pwd)/out}
+mkdir -p "$OUT"
+
+export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer}
+
+rm -rf "$DESTDIR"
+make -C libsepol clean
+# LIBSO and LIBMAP shouldn't be expanded here because their values are unknown until Makefile
+# has been read by make
+# shellcheck disable=SC2016
+make -C libsepol V=1 LD_SONAME_FLAGS='-soname,$(LIBSO),--version-script=$(LIBMAP)' -j"$(nproc)" install
+
+# CFLAGS, CXXFLAGS and LIB_FUZZING_ENGINE have to be split to be accepted by
+# the compiler/linker so they shouldn't be quoted
+# shellcheck disable=SC2086
+$CC $CFLAGS -I"$DESTDIR/usr/include" -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -c -o secilc-fuzzer.o libsepol/fuzz/secilc-fuzzer.c
+# shellcheck disable=SC2086
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o "$DESTDIR/usr/lib/libsepol.a" -o "$OUT/secilc-fuzzer"
+
+zip -r "$OUT/secilc-fuzzer_seed_corpus.zip" secilc/test
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] libsepol/cil: move the fuzz target and build script to the selinux repository
  2021-07-15  6:11   ` [PATCH v2] " Evgeny Vereshchagin
@ 2021-08-16  9:16     ` Nicolas Iooss
  2021-08-17 18:42       ` James Carter
  0 siblings, 1 reply; 5+ messages in thread
From: Nicolas Iooss @ 2021-08-16  9:16 UTC (permalink / raw)
  To: Evgeny Vereshchagin; +Cc: SElinux list

On Thu, Jul 15, 2021 at 8:11 AM Evgeny Vereshchagin <evvers@ya.ru> wrote:
>
> It should make it easier to reproduce bugs found by OSS-Fuzz locally
> without docker. The fuzz target can be built and run with the corpus
> OSS-Fuzz has accumulated so far by running the following commands:
> ```
> ./scripts/oss-fuzz.sh
> wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
> unzip -d CORPUS public.zip
> ./out/secilc-fuzzer CORPUS/
> ```
>
> It was tested in https://github.com/google/oss-fuzz/pull/6026
> by pointing OSS-Fuzz to the branch containing the patch and
> running all the tests with all the sanitizers and fuzzing engines
> there: https://github.com/google/oss-fuzz/actions/runs/1024673143
>
> [v2]
> [1] oss-fuzz: make shellcheck happy
>
> [2] oss-fuzz: build libsepol only
>
> The fuzz target covers libsepol so it's unnecessary to build everything
> else. Apart from that, the "LDFLAGS" kludge was removed since libsepol
> is compatible with the sanitizers flags passed via CFLAGS only. It
> should be brought back one way or another eventually though to fix
> build failures like
> ```
> clang -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L../src  sefcontext_compile.o ../src/regex.o  -lselinux  -lpcre  ../src/libselinux.a -lsepol -o sefcontext_compile
> /usr/bin/ld: sefcontext_compile.o: in function `usage':
> /home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:271: undefined reference to `__asan_report_load8'
> /usr/bin/ld: /home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:292: undefined reference to `__asan_handle_no_return'
> /usr/bin/ld: sefcontext_compile.o: in function `asan.module_ctor':
> ```
>
> [3] oss-fuzz: make it possible to run the script more than once
> by removing various build artifacts
>
> [4] oss-fuzz: make it possible to run the script from any directory
>
> [5] oss-fuzz: be a little bit more specific about what the script does
>
> [6] oss-fuzz: stop overwriting all the Makefiles
>
> Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>

Sorry for the delay. I have now been able to review and test your
script and it seems to work perfectly. Thanks!

Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>

Thanks,
Nicolas

> ---
>  libsepol/fuzz/secilc-fuzzer.c | 69 +++++++++++++++++++++++++++++++++++
>  scripts/oss-fuzz.sh           | 59 ++++++++++++++++++++++++++++++
>  2 files changed, 128 insertions(+)
>  create mode 100644 libsepol/fuzz/secilc-fuzzer.c
>  create mode 100755 scripts/oss-fuzz.sh
>
> diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c
> new file mode 100644
> index 00000000..255b3241
> --- /dev/null
> +++ b/libsepol/fuzz/secilc-fuzzer.c
> @@ -0,0 +1,69 @@
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <getopt.h>
> +#include <sys/stat.h>
> +
> +#include <sepol/cil/cil.h>
> +#include <sepol/policydb.h>
> +
> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
> +       enum cil_log_level log_level = CIL_ERR;
> +       struct sepol_policy_file *pf = NULL;
> +       FILE *dev_null = NULL;
> +       int target = SEPOL_TARGET_SELINUX;
> +       int disable_dontaudit = 0;
> +       int multiple_decls = 0;
> +       int disable_neverallow = 0;
> +       int preserve_tunables = 0;
> +       int policyvers = POLICYDB_VERSION_MAX;
> +       int mls = -1;
> +       int attrs_expand_generated = 0;
> +       struct cil_db *db = NULL;
> +       sepol_policydb_t *pdb = NULL;
> +
> +       cil_set_log_level(log_level);
> +
> +       cil_db_init(&db);
> +       cil_set_disable_dontaudit(db, disable_dontaudit);
> +       cil_set_multiple_decls(db, multiple_decls);
> +       cil_set_disable_neverallow(db, disable_neverallow);
> +       cil_set_preserve_tunables(db, preserve_tunables);
> +       cil_set_mls(db, mls);
> +       cil_set_target_platform(db, target);
> +       cil_set_policy_version(db, policyvers);
> +       cil_set_attrs_expand_generated(db, attrs_expand_generated);
> +
> +       if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK)
> +               goto exit;
> +
> +       if (cil_compile(db) != SEPOL_OK)
> +               goto exit;
> +
> +       if (cil_build_policydb(db, &pdb) != SEPOL_OK)
> +               goto exit;
> +
> +       if (sepol_policydb_optimize(pdb) != SEPOL_OK)
> +               goto exit;
> +
> +       dev_null = fopen("/dev/null", "w");
> +       if (dev_null == NULL)
> +               goto exit;
> +
> +       if (sepol_policy_file_create(&pf) != 0)
> +               goto exit;
> +
> +       sepol_policy_file_set_fp(pf, dev_null);
> +
> +       if (sepol_policydb_write(pdb, pf) != 0)
> +               goto exit;
> +exit:
> +       if (dev_null != NULL)
> +               fclose(dev_null);
> +
> +       cil_db_destroy(&db);
> +       sepol_policydb_free(pdb);
> +       sepol_policy_file_free(pf);
> +       return 0;
> +}
> diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh
> new file mode 100755
> index 00000000..16cc3c0a
> --- /dev/null
> +++ b/scripts/oss-fuzz.sh
> @@ -0,0 +1,59 @@
> +#!/bin/bash
> +
> +# The script is used to build the fuzz targets run on ClusterFuzz. It has to be
> +# compatible with the "build.sh" script described at
> +# https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh
> +# More precisely, it should use environment variables like OUT, LIB_FUZZING_ENGINE
> +# and so on (https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh-script-environment),
> +# and the fuzz targets have to be linked with $CXX even though the project is written
> +# in C: https://google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements
> +
> +# To make it easier to build the fuzz targets locally, the script can also work in "local"
> +# mode. To run secilc-fuzzer against a test case (named, say, CRASH) triggering an issue
> +# the following commands should be run
> +#
> +# $ ./scripts/oss-fuzz.sh
> +# $ ./out/secilc-fuzzer CRASH
> +
> +# To run the fuzzer against the corpus OSS-Fuzz has accumulated so far it should be
> +# downloaded, unpacked and passed to the fuzzer:
> +#
> +# $ wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
> +# $ unzip -d CORPUS public.zip
> +# $ ./out/secilc-fuzzer CORPUS/
> +
> +set -eux
> +
> +cd "$(dirname -- "$0")/.."
> +
> +export DESTDIR=${DESTDIR:-$(pwd)/DESTDIR}
> +
> +SANITIZER=${SANITIZER:-address}
> +flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link"
> +
> +export CC=${CC:-clang}
> +export CFLAGS=${CFLAGS:-$flags}
> +
> +export CXX=${CXX:-clang++}
> +export CXXFLAGS=${CXXFLAGS:-$flags}
> +
> +export OUT=${OUT:-$(pwd)/out}
> +mkdir -p "$OUT"
> +
> +export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer}
> +
> +rm -rf "$DESTDIR"
> +make -C libsepol clean
> +# LIBSO and LIBMAP shouldn't be expanded here because their values are unknown until Makefile
> +# has been read by make
> +# shellcheck disable=SC2016
> +make -C libsepol V=1 LD_SONAME_FLAGS='-soname,$(LIBSO),--version-script=$(LIBMAP)' -j"$(nproc)" install
> +
> +# CFLAGS, CXXFLAGS and LIB_FUZZING_ENGINE have to be split to be accepted by
> +# the compiler/linker so they shouldn't be quoted
> +# shellcheck disable=SC2086
> +$CC $CFLAGS -I"$DESTDIR/usr/include" -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -c -o secilc-fuzzer.o libsepol/fuzz/secilc-fuzzer.c
> +# shellcheck disable=SC2086
> +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o "$DESTDIR/usr/lib/libsepol.a" -o "$OUT/secilc-fuzzer"
> +
> +zip -r "$OUT/secilc-fuzzer_seed_corpus.zip" secilc/test
> --
> 2.31.1
>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] libsepol/cil: move the fuzz target and build script to the selinux repository
  2021-08-16  9:16     ` Nicolas Iooss
@ 2021-08-17 18:42       ` James Carter
  0 siblings, 0 replies; 5+ messages in thread
From: James Carter @ 2021-08-17 18:42 UTC (permalink / raw)
  To: Nicolas Iooss; +Cc: Evgeny Vereshchagin, SElinux list

On Mon, Aug 16, 2021 at 5:16 AM Nicolas Iooss <nicolas.iooss@m4x.org> wrote:
>
> On Thu, Jul 15, 2021 at 8:11 AM Evgeny Vereshchagin <evvers@ya.ru> wrote:
> >
> > It should make it easier to reproduce bugs found by OSS-Fuzz locally
> > without docker. The fuzz target can be built and run with the corpus
> > OSS-Fuzz has accumulated so far by running the following commands:
> > ```
> > ./scripts/oss-fuzz.sh
> > wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
> > unzip -d CORPUS public.zip
> > ./out/secilc-fuzzer CORPUS/
> > ```
> >
> > It was tested in https://github.com/google/oss-fuzz/pull/6026
> > by pointing OSS-Fuzz to the branch containing the patch and
> > running all the tests with all the sanitizers and fuzzing engines
> > there: https://github.com/google/oss-fuzz/actions/runs/1024673143
> >
> > [v2]
> > [1] oss-fuzz: make shellcheck happy
> >
> > [2] oss-fuzz: build libsepol only
> >
> > The fuzz target covers libsepol so it's unnecessary to build everything
> > else. Apart from that, the "LDFLAGS" kludge was removed since libsepol
> > is compatible with the sanitizers flags passed via CFLAGS only. It
> > should be brought back one way or another eventually though to fix
> > build failures like
> > ```
> > clang -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L../src  sefcontext_compile.o ../src/regex.o  -lselinux  -lpcre  ../src/libselinux.a -lsepol -o sefcontext_compile
> > /usr/bin/ld: sefcontext_compile.o: in function `usage':
> > /home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:271: undefined reference to `__asan_report_load8'
> > /usr/bin/ld: /home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:292: undefined reference to `__asan_handle_no_return'
> > /usr/bin/ld: sefcontext_compile.o: in function `asan.module_ctor':
> > ```
> >
> > [3] oss-fuzz: make it possible to run the script more than once
> > by removing various build artifacts
> >
> > [4] oss-fuzz: make it possible to run the script from any directory
> >
> > [5] oss-fuzz: be a little bit more specific about what the script does
> >
> > [6] oss-fuzz: stop overwriting all the Makefiles
> >
> > Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>
>
> Sorry for the delay. I have now been able to review and test your
> script and it seems to work perfectly. Thanks!
>
> Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
>

Merged.
Thanks,
Jim

> Thanks,
> Nicolas
>
> > ---
> >  libsepol/fuzz/secilc-fuzzer.c | 69 +++++++++++++++++++++++++++++++++++
> >  scripts/oss-fuzz.sh           | 59 ++++++++++++++++++++++++++++++
> >  2 files changed, 128 insertions(+)
> >  create mode 100644 libsepol/fuzz/secilc-fuzzer.c
> >  create mode 100755 scripts/oss-fuzz.sh
> >
> > diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c
> > new file mode 100644
> > index 00000000..255b3241
> > --- /dev/null
> > +++ b/libsepol/fuzz/secilc-fuzzer.c
> > @@ -0,0 +1,69 @@
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +#include <stdint.h>
> > +#include <string.h>
> > +#include <getopt.h>
> > +#include <sys/stat.h>
> > +
> > +#include <sepol/cil/cil.h>
> > +#include <sepol/policydb.h>
> > +
> > +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
> > +       enum cil_log_level log_level = CIL_ERR;
> > +       struct sepol_policy_file *pf = NULL;
> > +       FILE *dev_null = NULL;
> > +       int target = SEPOL_TARGET_SELINUX;
> > +       int disable_dontaudit = 0;
> > +       int multiple_decls = 0;
> > +       int disable_neverallow = 0;
> > +       int preserve_tunables = 0;
> > +       int policyvers = POLICYDB_VERSION_MAX;
> > +       int mls = -1;
> > +       int attrs_expand_generated = 0;
> > +       struct cil_db *db = NULL;
> > +       sepol_policydb_t *pdb = NULL;
> > +
> > +       cil_set_log_level(log_level);
> > +
> > +       cil_db_init(&db);
> > +       cil_set_disable_dontaudit(db, disable_dontaudit);
> > +       cil_set_multiple_decls(db, multiple_decls);
> > +       cil_set_disable_neverallow(db, disable_neverallow);
> > +       cil_set_preserve_tunables(db, preserve_tunables);
> > +       cil_set_mls(db, mls);
> > +       cil_set_target_platform(db, target);
> > +       cil_set_policy_version(db, policyvers);
> > +       cil_set_attrs_expand_generated(db, attrs_expand_generated);
> > +
> > +       if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK)
> > +               goto exit;
> > +
> > +       if (cil_compile(db) != SEPOL_OK)
> > +               goto exit;
> > +
> > +       if (cil_build_policydb(db, &pdb) != SEPOL_OK)
> > +               goto exit;
> > +
> > +       if (sepol_policydb_optimize(pdb) != SEPOL_OK)
> > +               goto exit;
> > +
> > +       dev_null = fopen("/dev/null", "w");
> > +       if (dev_null == NULL)
> > +               goto exit;
> > +
> > +       if (sepol_policy_file_create(&pf) != 0)
> > +               goto exit;
> > +
> > +       sepol_policy_file_set_fp(pf, dev_null);
> > +
> > +       if (sepol_policydb_write(pdb, pf) != 0)
> > +               goto exit;
> > +exit:
> > +       if (dev_null != NULL)
> > +               fclose(dev_null);
> > +
> > +       cil_db_destroy(&db);
> > +       sepol_policydb_free(pdb);
> > +       sepol_policy_file_free(pf);
> > +       return 0;
> > +}
> > diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh
> > new file mode 100755
> > index 00000000..16cc3c0a
> > --- /dev/null
> > +++ b/scripts/oss-fuzz.sh
> > @@ -0,0 +1,59 @@
> > +#!/bin/bash
> > +
> > +# The script is used to build the fuzz targets run on ClusterFuzz. It has to be
> > +# compatible with the "build.sh" script described at
> > +# https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh
> > +# More precisely, it should use environment variables like OUT, LIB_FUZZING_ENGINE
> > +# and so on (https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh-script-environment),
> > +# and the fuzz targets have to be linked with $CXX even though the project is written
> > +# in C: https://google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements
> > +
> > +# To make it easier to build the fuzz targets locally, the script can also work in "local"
> > +# mode. To run secilc-fuzzer against a test case (named, say, CRASH) triggering an issue
> > +# the following commands should be run
> > +#
> > +# $ ./scripts/oss-fuzz.sh
> > +# $ ./out/secilc-fuzzer CRASH
> > +
> > +# To run the fuzzer against the corpus OSS-Fuzz has accumulated so far it should be
> > +# downloaded, unpacked and passed to the fuzzer:
> > +#
> > +# $ wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
> > +# $ unzip -d CORPUS public.zip
> > +# $ ./out/secilc-fuzzer CORPUS/
> > +
> > +set -eux
> > +
> > +cd "$(dirname -- "$0")/.."
> > +
> > +export DESTDIR=${DESTDIR:-$(pwd)/DESTDIR}
> > +
> > +SANITIZER=${SANITIZER:-address}
> > +flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link"
> > +
> > +export CC=${CC:-clang}
> > +export CFLAGS=${CFLAGS:-$flags}
> > +
> > +export CXX=${CXX:-clang++}
> > +export CXXFLAGS=${CXXFLAGS:-$flags}
> > +
> > +export OUT=${OUT:-$(pwd)/out}
> > +mkdir -p "$OUT"
> > +
> > +export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer}
> > +
> > +rm -rf "$DESTDIR"
> > +make -C libsepol clean
> > +# LIBSO and LIBMAP shouldn't be expanded here because their values are unknown until Makefile
> > +# has been read by make
> > +# shellcheck disable=SC2016
> > +make -C libsepol V=1 LD_SONAME_FLAGS='-soname,$(LIBSO),--version-script=$(LIBMAP)' -j"$(nproc)" install
> > +
> > +# CFLAGS, CXXFLAGS and LIB_FUZZING_ENGINE have to be split to be accepted by
> > +# the compiler/linker so they shouldn't be quoted
> > +# shellcheck disable=SC2086
> > +$CC $CFLAGS -I"$DESTDIR/usr/include" -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -c -o secilc-fuzzer.o libsepol/fuzz/secilc-fuzzer.c
> > +# shellcheck disable=SC2086
> > +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o "$DESTDIR/usr/lib/libsepol.a" -o "$OUT/secilc-fuzzer"
> > +
> > +zip -r "$OUT/secilc-fuzzer_seed_corpus.zip" secilc/test
> > --
> > 2.31.1
> >
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-08-17 18:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-13  0:04 [PATCH] libsepol/cil: move the fuzz target and build script to the selinux repository Evgeny Vereshchagin
2021-07-13 19:51 ` Nicolas Iooss
2021-07-15  6:11   ` [PATCH v2] " Evgeny Vereshchagin
2021-08-16  9:16     ` Nicolas Iooss
2021-08-17 18:42       ` James Carter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).