2021-12-22 23:42:08

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v3 1/4] build: Add sanitizer options

From: Luiz Augusto von Dentz <[email protected]>

Build using Address Sanitizer (asan), Leak Sanitizer (lsan), or
Undefined Behavior Sanitizer (ubsan) by using one of these options for
the configure script:

--enable-asan
--enable-lsan
--enable-ubsan

For each of these to work, the compiler must support the requested
sanitizer and the requisite libraries must be installed (libasan,
liblsan, libubsan).
---
v2: Attempt to fix CI findings
v3: Yet again attempt to fix CI findings, disable running tests with
valgrind if either asan or lsan are enabled are they are likely going
to conflict.

Makefile.am | 8 +++++-
acinclude.m4 | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 7 ++++-
3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 993168f00..308f13c50 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,7 +24,7 @@ pkgincludedir = $(includedir)/bluetooth

pkginclude_HEADERS =

-AM_CFLAGS = $(WARNING_CFLAGS) $(MISC_CFLAGS) $(UDEV_CFLAGS) $(LIBEBOOK_CFLAGS) \
+AM_CFLAGS = $(MISC_CFLAGS) $(WARNING_CFLAGS) $(UDEV_CFLAGS) $(LIBEBOOK_CFLAGS) \
$(LIBEDATASERVER_CFLAGS) $(ell_cflags)
AM_LDFLAGS = $(MISC_LDFLAGS)

@@ -243,6 +243,8 @@ src_libshared_glib_la_SOURCES = $(shared_sources) \
src/shared/mainloop-notify.h \
src/shared/mainloop-notify.c \
src/shared/tester.c
+src_libshared_glib_la_LDFLAGS = $(AM_LDFLAGS)
+src_libshared_glib_la_CFLAGS = $(AM_CFLAGS)

src_libshared_mainloop_la_SOURCES = $(shared_sources) \
src/shared/io-mainloop.c \
@@ -250,6 +252,8 @@ src_libshared_mainloop_la_SOURCES = $(shared_sources) \
src/shared/mainloop.h src/shared/mainloop.c \
src/shared/mainloop-notify.h \
src/shared/mainloop-notify.c
+src_libshared_mainloop_la_LDFLAGS = $(AM_LDFLAGS)
+src_libshared_mainloop_la_CFLAGS = $(AM_CFLAGS)

if LIBSHARED_ELL
src_libshared_ell_la_SOURCES = $(shared_sources) \
@@ -257,6 +261,8 @@ src_libshared_ell_la_SOURCES = $(shared_sources) \
src/shared/timeout-ell.c \
src/shared/mainloop.h \
src/shared/mainloop-ell.c
+src_libshared_ell_la_LDFLAGS = $(AM_LDFLAGS)
+src_libshared_ell_la_CFLAGS = $(AM_CFLAGS)
endif

attrib_sources = attrib/att.h attrib/att-database.h attrib/att.c \
diff --git a/acinclude.m4 b/acinclude.m4
index 529848357..b388dfc11 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -10,6 +10,45 @@ AC_DEFUN([AC_PROG_CC_PIE], [
])
])

+AC_DEFUN([AC_PROG_CC_ASAN], [
+ AC_CACHE_CHECK([whether ${CC-cc} accepts -fsanitize=address],
+ ac_cv_prog_cc_asan, [
+ echo 'void f(){}' > asan.c
+ if test -z "`${CC-cc} -fsanitize=address -c asan.c 2>&1`"; then
+ ac_cv_prog_cc_asan=yes
+ else
+ ac_cv_prog_cc_asan=no
+ fi
+ rm -rf asan*
+ ])
+])
+
+AC_DEFUN([AC_PROG_CC_LSAN], [
+ AC_CACHE_CHECK([whether ${CC-cc} accepts -fsanitize=leak],
+ ac_cv_prog_cc_lsan, [
+ echo 'void f(){}' > lsan.c
+ if test -z "`${CC-cc} -fsanitize=leak -c lsan.c 2>&1`"; then
+ ac_cv_prog_cc_lsan=yes
+ else
+ ac_cv_prog_cc_lsan=no
+ fi
+ rm -rf lsan*
+ ])
+])
+
+AC_DEFUN([AC_PROG_CC_UBSAN], [
+ AC_CACHE_CHECK([whether ${CC-cc} accepts -fsanitize=undefined],
+ ac_cv_prog_cc_ubsan, [
+ echo 'void f(){}' > ubsan.c
+ if test -z "`${CC-cc} -fsanitize=undefined -c ubsan.c 2>&1`"; then
+ ac_cv_prog_cc_ubsan=yes
+ else
+ ac_cv_prog_cc_ubsan=no
+ fi
+ rm -rf ubsan*
+ ])
+])
+
AC_DEFUN([COMPILER_FLAGS], [
with_cflags=""
if (test "$USE_MAINTAINER_MODE" = "yes"); then
@@ -38,6 +77,44 @@ AC_DEFUN([MISC_FLAGS], [
misc_cflags="$misc_cflags -O0"
fi
])
+ AC_ARG_ENABLE(asan, AC_HELP_STRING([--enable-asan],
+ [enable linking with address sanitizer]), [
+ save_LIBS=$LIBS
+ AC_CHECK_LIB(asan, _init)
+ LIBS=$save_LIBS
+ if (test "${enableval}" = "yes" &&
+ test "${ac_cv_lib_asan__init}" = "yes" &&
+ test "${ac_cv_prog_cc_asan}" = "yes"); then
+ misc_cflags="$misc_cflags -fsanitize=address";
+ misc_ldflags="$misc_ldflags -fsanitize=address"
+ AC_SUBST([ASAN_LIB], ${ac_cv_lib_asan__init})
+ fi
+ ])
+ AC_ARG_ENABLE(lsan, AC_HELP_STRING([--enable-lsan],
+ [enable linking with address sanitizer]), [
+ save_LIBS=$LIBS
+ AC_CHECK_LIB(lsan, _init)
+ LIBS=$save_LIBS
+ if (test "${enableval}" = "yes" &&
+ test "${ac_cv_lib_lsan__init}" = "yes" &&
+ test "${ac_cv_prog_cc_lsan}" = "yes"); then
+ misc_cflags="$misc_cflags -fsanitize=leak";
+ misc_ldflags="$misc_ldflags -fsanitize=leak"
+ AC_SUBST([ASAN_LIB], ${ac_cv_lib_lsan__init})
+ fi
+ ])
+ AC_ARG_ENABLE(ubsan, AC_HELP_STRING([--enable-ubsan],
+ [enable linking with address sanitizer]), [
+ save_LIBS=$LIBS
+ AC_CHECK_LIB(ubsan, _init)
+ LIBS=$save_LIBS
+ if (test "${enableval}" = "yes" &&
+ test "${ac_cv_lib_ubsan__init}" = "yes" &&
+ test "${ac_cv_prog_cc_ubsan}" = "yes"); then
+ misc_cflags="$misc_cflags -fsanitize=undefined";
+ misc_ldflags="$misc_ldflags -fsanitize=undefined";
+ fi
+ ])
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],
[enable compiling with debugging information]), [
if (test "${enableval}" = "yes" &&
diff --git a/configure.ac b/configure.ac
index 2674e30d3..849e1db46 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,6 +23,9 @@ AC_C_RESTRICT
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CC_PIE
+AC_PROG_CC_ASAN
+AC_PROG_CC_LSAN
+AC_PROG_CC_UBSAN
AC_PROG_INSTALL
AC_PROG_MKDIR_P

@@ -40,10 +43,12 @@ if (test "$USE_MAINTAINER_MODE" = "yes"); then
fi
AM_CONDITIONAL(COVERAGE, test "${enable_coverage}" = "yes")
AM_CONDITIONAL(DBUS_RUN_SESSION, test "${enable_dbus_run_session}" = "yes")
-AM_CONDITIONAL(VALGRIND, test "${enable_valgrind}" = "yes")

MISC_FLAGS

+AM_CONDITIONAL(VALGRIND, test "${enable_valgrind}" = "yes" &&
+ test "$ASAN_LIB" != "yes" && test "LSAN_LIB" != "yes")
+
AC_ARG_ENABLE(threads, AC_HELP_STRING([--enable-threads],
[enable threading support]), [enable_threads=${enableval}])

--
2.33.1



2021-12-22 23:42:08

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v3 2/4] build: Fix build when sanitizer are enabled

From: Luiz Augusto von Dentz <[email protected]>

This fixes various issues found when sanitizers are enabled.
---
monitor/packet.c | 3 ++-
peripheral/main.c | 2 +-
profiles/audio/a2dp.c | 5 ++++-
profiles/network/bnep.c | 4 ++--
src/shared/gatt-server.c | 2 --
tools/mesh-gatt/util.c | 11 ++++++++---
tools/test-runner.c | 2 +-
7 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/monitor/packet.c b/monitor/packet.c
index 71f711dc5..397000644 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -330,7 +330,8 @@ static void print_packet(struct timeval *tv, struct ucred *cred, char ident,
if ((filter_mask & PACKET_FILTER_SHOW_INDEX) &&
index != HCI_DEV_NONE) {
if (use_color()) {
- n = sprintf(ts_str + ts_pos, "%s", COLOR_INDEX_LABEL);
+ n = snprintf(ts_str + ts_pos, sizeof(ts_str) - ts_pos,
+ "%s", COLOR_INDEX_LABEL);
if (n > 0)
ts_pos += n;
}
diff --git a/peripheral/main.c b/peripheral/main.c
index 0f5210403..91adb45fc 100644
--- a/peripheral/main.c
+++ b/peripheral/main.c
@@ -73,7 +73,7 @@ static void prepare_filesystem(void)
if (!is_init)
return;

- for (i = 0; mount_table[i].fstype; i++) {
+ for (i = 0; mount_table[i].fstype && mount_table[i].target; i++) {
struct stat st;

if (lstat(mount_table[i].target, &st) < 0) {
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index eba2f9822..d0808c77a 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1338,9 +1338,12 @@ static gboolean a2dp_reconfigure(gpointer data)
if (setup->rsep) {
cap = avdtp_get_codec(setup->rsep->sep);
rsep_codec = (struct avdtp_media_codec_capability *) cap->data;
+ /* Check that codec really match after closing */
+ if (sep->codec != rsep_codec->media_codec_type)
+ setup->rsep = NULL;
}

- if (!setup->rsep || sep->codec != rsep_codec->media_codec_type)
+ if (!setup->rsep)
setup->rsep = find_remote_sep(setup->chan, sep);

if (!setup->rsep) {
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index f94f1da8a..54b950058 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -108,7 +108,7 @@ static int bnep_connadd(int sk, uint16_t role, char *dev)
struct bnep_connadd_req req;

memset(&req, 0, sizeof(req));
- strncpy(req.device, dev, 16);
+ strncpy(req.device, dev, 15);
req.device[15] = '\0';

req.sock = sk;
@@ -345,7 +345,7 @@ struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
session->io = g_io_channel_unix_new(dup_fd);
session->src = local_role;
session->dst = remote_role;
- strncpy(session->iface, iface, 16);
+ strncpy(session->iface, iface, 15);
session->iface[15] = '\0';

g_io_channel_set_close_on_unref(session->io, TRUE);
diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 9beec44be..776e5ce2b 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -1119,8 +1119,6 @@ static void read_multiple_cb(struct bt_att_chan *chan, uint8_t opcode,
}

data = read_mult_data_new(server, chan, opcode, length / 2);
- if (!data)
- goto error;

for (i = 0; i < data->num_handles; i++)
data->handles[i] = get_le16(pdu + i * 2);
diff --git a/tools/mesh-gatt/util.c b/tools/mesh-gatt/util.c
index e845c4112..eb8b8eb29 100644
--- a/tools/mesh-gatt/util.c
+++ b/tools/mesh-gatt/util.c
@@ -41,9 +41,14 @@ void print_byte_array(const char *prefix, const void *ptr, int len)
char *line, *bytes;
int i;

- line = g_malloc(strlen(prefix) + (16 * 3) + 2);
- sprintf(line, "%s ", prefix);
- bytes = line + strlen(prefix) + 1;
+ if (prefix) {
+ line = g_malloc(strlen(prefix) + (16 * 3) + 2);
+ sprintf(line, "%s ", prefix);
+ bytes = line + strlen(prefix) + 1;
+ } else {
+ line = g_malloc((16 * 3) + 2);
+ bytes = line + 1;
+ }

for (i = 0; i < len; ++i) {
sprintf(bytes, "%2.2x ", data[i]);
diff --git a/tools/test-runner.c b/tools/test-runner.c
index eac120f4a..71cc0d2df 100644
--- a/tools/test-runner.c
+++ b/tools/test-runner.c
@@ -136,7 +136,7 @@ static void prepare_sandbox(void)
{
int i;

- for (i = 0; mount_table[i].fstype; i++) {
+ for (i = 0; mount_table[i].fstype && mount_table[i].target; i++) {
struct stat st;

if (lstat(mount_table[i].target, &st) < 0) {
--
2.33.1


2021-12-22 23:42:10

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v3 3/4] bootstrap-configure: Enable sanitizer options

From: Luiz Augusto von Dentz <[email protected]>

This makes bootstrap-configure enables all sanitizers.
---
bootstrap-configure | 3 +++
1 file changed, 3 insertions(+)

diff --git a/bootstrap-configure b/bootstrap-configure
index a34be8320..8172840d5 100755
--- a/bootstrap-configure
+++ b/bootstrap-configure
@@ -28,6 +28,9 @@ fi
--enable-btpclient \
--enable-logger \
--enable-pie \
+ --enable-asan \
+ --enable-lsan \
+ --enable-ubsan \
--enable-cups \
--enable-library \
--enable-admin \
--
2.33.1


2021-12-22 23:42:11

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v3 4/4] gattrib: Fix passing NULL to memcpy

From: Luiz Augusto von Dentz <[email protected]>

This fixes the following runtime error:

attrib/gattrib.c:198:2: runtime error: null pointer passed as
argument 2, which is declared to never be null
---
attrib/gattrib.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 270a37ebe..041b9d289 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -195,7 +195,9 @@ static uint8_t *construct_full_pdu(uint8_t opcode, const void *pdu,
return NULL;

buf[0] = opcode;
- memcpy(buf + 1, pdu, length);
+
+ if (pdu && length)
+ memcpy(buf + 1, pdu, length);

return buf;
}
--
2.33.1


2021-12-23 01:01:57

by bluez.test.bot

[permalink] [raw]
Subject: RE: [v3,1/4] build: Add sanitizer options

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=600885

---Test result---

Test Summary:
CheckPatch PASS 5.48 seconds
GitLint PASS 3.86 seconds
Prep - Setup ELL PASS 41.56 seconds
Build - Prep PASS 0.61 seconds
Build - Configure PASS 8.38 seconds
Build - Make FAIL 1290.39 seconds
Make Check FAIL 2.25 seconds
Make Distcheck PASS 228.21 seconds
Build w/ext ELL - Configure PASS 8.62 seconds
Build w/ext ELL - Make FAIL 1277.13 seconds
Incremental Build with patchesFAIL 1720.80 seconds

Details
##############################
Test: Build - Make - FAIL
Desc: Build the BlueZ source tree
Output:
tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:12364:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
12364 | int main(int argc, char *argv[])
| ^~~~
unit/test-avdtp.c: In function ‘main’:
unit/test-avdtp.c:766:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
766 | int main(int argc, char *argv[])
| ^~~~
unit/test-avrcp.c: In function ‘main’:
unit/test-avrcp.c:989:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
989 | int main(int argc, char *argv[])
| ^~~~
In file included from /usr/include/string.h:495,
from /usr/include/glib-2.0/glib/gtestutils.h:30,
from /usr/include/glib-2.0/glib.h:85,
from profiles/audio/avctp.c:30:
In function ‘strncpy’,
inlined from ‘uinput_create.constprop’ at profiles/audio/avctp.c:1180:3:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound 80 equals destination size [-Werror=stringop-truncation]
106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:9501: profiles/audio/bluetoothd-avctp.o] Error 1
make: *** [Makefile:4302: all] Error 2


##############################
Test: Make Check - FAIL
Desc: Run 'make check'
Output:
In file included from /usr/include/string.h:495,
from /usr/include/glib-2.0/glib/gtestutils.h:30,
from /usr/include/glib-2.0/glib.h:85,
from profiles/audio/avctp.c:30:
In function ‘strncpy’,
inlined from ‘uinput_create.constprop’ at profiles/audio/avctp.c:1180:3:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound 80 equals destination size [-Werror=stringop-truncation]
106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:9501: profiles/audio/bluetoothd-avctp.o] Error 1
make: *** [Makefile:11306: check] Error 2


##############################
Test: Build w/ext ELL - Make - FAIL
Desc: Build BlueZ source with '--enable-external-ell' configuration
Output:
tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:12364:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
12364 | int main(int argc, char *argv[])
| ^~~~
unit/test-avdtp.c: In function ‘main’:
unit/test-avdtp.c:766:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
766 | int main(int argc, char *argv[])
| ^~~~
unit/test-avrcp.c: In function ‘main’:
unit/test-avrcp.c:989:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
989 | int main(int argc, char *argv[])
| ^~~~
In file included from /usr/include/string.h:495,
from /usr/include/glib-2.0/glib/gtestutils.h:30,
from /usr/include/glib-2.0/glib.h:85,
from profiles/audio/avctp.c:30:
In function ‘strncpy’,
inlined from ‘uinput_create.constprop’ at profiles/audio/avctp.c:1180:3:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound 80 equals destination size [-Werror=stringop-truncation]
106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:9501: profiles/audio/bluetoothd-avctp.o] Error 1
make: *** [Makefile:4302: all] Error 2


##############################
Test: Incremental Build with patches - FAIL
Desc: Incremental build per patch in the series
Output:
tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:12364:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
12364 | int main(int argc, char *argv[])
| ^~~~
unit/test-avdtp.c: In function ‘main’:
unit/test-avdtp.c:766:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
766 | int main(int argc, char *argv[])
| ^~~~
unit/test-avrcp.c: In function ‘main’:
unit/test-avrcp.c:989:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
989 | int main(int argc, char *argv[])
| ^~~~
In file included from /usr/include/string.h:495,
from /usr/include/glib-2.0/glib/gtestutils.h:30,
from /usr/include/glib-2.0/glib.h:85,
from profiles/audio/avctp.c:30:
In function ‘strncpy’,
inlined from ‘uinput_create.constprop’ at profiles/audio/avctp.c:1180:3:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound 80 equals destination size [-Werror=stringop-truncation]
106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:9501: profiles/audio/bluetoothd-avctp.o] Error 1
make: *** [Makefile:4302: all] Error 2




---
Regards,
Linux Bluetooth