From 0af2762cbf439507c4a31f538f2e476a8f5e118d Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 7 Feb 2018 11:10:31 +0100 Subject: [PATCH 1/5] build: allow building with address sanitizer only for executables Shared libraries built with sanitizers are a bit inconvenient to use because they require that any application linking to them is run with libasan preloaded using LD_PRELOAD. This limitation makes the sanitizer support less useful because applications will refuse to start unless there is a special environment variable set. Let's turn the --enable-address-sanitizer configure flag into --with-address-sanitizer=yes|no|exec so that is possible to enable asan only for executables. --- Makefile.am | 125 ++++++++++++++++++++++++++++++++--------- configure.ac | 38 ++++++++----- docs/libnm/Makefile.am | 6 +- 3 files changed, 128 insertions(+), 41 deletions(-) diff --git a/Makefile.am b/Makefile.am index 325a7a428f..e3e58f7639 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,7 +53,7 @@ INTROSPECTION_SCANNER_ARGS = INTROSPECTION_COMPILER_ARGS = # Pass SANITIZER_ENV where a command that uses built libraries is # executed, to suppress possible errors -INTROSPECTION_SCANNER_ENV = $(SANITIZER_ENV) +INTROSPECTION_SCANNER_ENV = $(SANITIZER_ENV) LDFLAGS="$(SANITIZER_LIB_LDFLAGS)" libnmincludedir = $(includedir)/libnm libnminclude_HEADERS = @@ -104,12 +104,13 @@ endif set_sanitizer_env = \ [ -n "$(SANITIZER_ENV)" ] && export $(SANITIZER_ENV) ; \ - if [ -n "$(1)" ] && echo $(CFLAGS) | grep -e -fsanitize=address ; then \ - export LD_PRELOAD="$${LD_PRELOAD}:$$(ldd $(1) | grep libasan\.so\.. -o | head -n 1)"; \ + if echo $(SANITIZER_LIB_CFLAGS) $(SANITIZER_EXEC_CFLAGS) | grep -e -fsanitize=address > /dev/null; then \ + [ -n "$(1)" ] && export LD_PRELOAD="$${LD_PRELOAD}:$$(ldd $(1) | grep libasan\.so\.. -o | head -n 1)"; \ + [ -n "$(2)" ] && export LD_PRELOAD="$${LD_PRELOAD}:$$(ldd $(2) | grep libasan\.so\.. -o | head -n 1)"; \ fi check_so_symbols = \ - $(call set_sanitizer_env,$(1)); \ + $(call set_sanitizer_env,$(1),$(builddir)/src/NetworkManager); \ LD_BIND_NOW=1 LD_PRELOAD=$${LD_PRELOAD}:$(1) $(builddir)/src/NetworkManager --version >/dev/null ############################################################################### @@ -545,7 +546,8 @@ dflt_cppflags_libnm_core = \ -I$(builddir)/libnm-core \ $(CODE_COVERAGE_CFLAGS) \ $(GLIB_CFLAGS) \ - $(LIBUDEV_CFLAGS) + $(LIBUDEV_CFLAGS) \ + $(SANITIZER_LIB_CFLAGS) if WITH_GNUTLS dflt_cppflags_libnm_core += $(GNUTLS_CFLAGS) @@ -609,7 +611,8 @@ libnm_core_libnm_core_la_LIBADD = \ $(LIBUDEV_LIBS) libnm_core_libnm_core_la_LDFLAGS = \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_LIB_LDFLAGS) if WITH_GNUTLS libnm_core_lib_c_real += libnm-core/crypto_gnutls.c @@ -693,6 +696,9 @@ libnm_core_tests_ldadd = \ libnm-core/libnm-core.la \ $(GLIB_LIBS) +libnm_core_tests_ldflags = \ + $(SANITIZER_LIB_LDFLAGS) + libnm_core_tests_test_compare_LDADD = $(libnm_core_tests_ldadd) libnm_core_tests_test_crypto_LDADD = $(libnm_core_tests_ldadd) libnm_core_tests_test_general_LDADD = $(libnm_core_tests_ldadd) @@ -701,6 +707,14 @@ libnm_core_tests_test_secrets_LDADD = $(libnm_core_tests_ldadd) libnm_core_tests_test_setting_LDADD = $(libnm_core_tests_ldadd) libnm_core_tests_test_settings_defaults_LDADD = $(libnm_core_tests_ldadd) +libnm_core_tests_test_compare_LDFLAGS = $(libnm_core_tests_ldflags) +libnm_core_tests_test_crypto_LDFLAGS = $(libnm_core_tests_ldflags) +libnm_core_tests_test_general_LDFLAGS = $(libnm_core_tests_ldflags) +libnm_core_tests_test_keyfile_LDFLAGS = $(libnm_core_tests_ldflags) +libnm_core_tests_test_secrets_LDFLAGS = $(libnm_core_tests_ldflags) +libnm_core_tests_test_setting_LDFLAGS = $(libnm_core_tests_ldflags) +libnm_core_tests_test_settings_defaults_LDFLAGS = $(libnm_core_tests_ldflags) + $(libnm_core_tests_test_compare_OBJECTS): $(libnm_core_lib_h_pub_mkenums) $(libnm_core_tests_test_crypto_OBJECTS): $(libnm_core_lib_h_pub_mkenums) $(libnm_core_tests_test_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums) @@ -901,7 +915,8 @@ $(libnm_tests_libnm_vpn_plugin_utils_test_la_OBJECTS): $(libnm_core_lib_h_pub_m libnm_libnm_la_CPPFLAGS = \ $(libnm_lib_cppflags) \ - $(LIBUDEV_CFLAGS) + $(LIBUDEV_CFLAGS) \ + $(SANITIZER_LIB_CFLAGS) libnm_libnm_la_SOURCES = \ $(libnm_lib_h_pub_real) \ @@ -925,6 +940,7 @@ libnm_libnm_la_LIBADD = \ libnm_libnm_la_LDFLAGS = \ -Wl,--version-script="$(srcdir)/libnm/libnm.ver" \ $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_LIB_LDFLAGS) \ -version-info "1:0:1" check-local-exports-libnm: libnm/libnm.la @@ -1071,6 +1087,9 @@ libnm_tests_ldadd = \ libnm/libnm.la \ $(GLIB_LIBS) +libnm_tests_ldflags = \ + $(SANITIZER_LIB_LDFLAGS) + libnm_tests_test_general_CPPFLAGS = $(libnm_tests_cppflags) libnm_tests_test_nm_client_CPPFLAGS = $(libnm_tests_cppflags) libnm_tests_test_remote_settings_client_CPPFLAGS = $(libnm_tests_cppflags) @@ -1102,6 +1121,11 @@ libnm_tests_test_nm_client_LDADD = $(libnm_tests_ldadd) libnm_tests_test_remote_settings_client_LDADD = $(libnm_tests_ldadd) libnm_tests_test_secret_agent_LDADD = $(libnm_tests_ldadd) +libnm_tests_test_general_LDFLAGS = $(libnm_tests_ldflags) +libnm_tests_test_nm_client_LDFLAGS = $(libnm_tests_ldflags) +libnm_tests_test_remote_settings_client_LDFLAGS = $(libnm_tests_ldflags) +libnm_tests_test_secret_agent_LDFLAGS = $(libnm_tests_ldflags) + $(libnm_tests_test_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums) $(libnm_tests_test_nm_client_OBJECTS): $(libnm_core_lib_h_pub_mkenums) $(libnm_tests_test_remote_settings_client_OBJECTS): $(libnm_core_lib_h_pub_mkenums) @@ -1125,6 +1149,7 @@ libnm_tests_libnm_vpn_plugin_utils_test_la_CFLAGS = \ -I$(srcdir)/libnm \ -I$(builddir)/libnm \ $(GLIB_CFLAGS) \ + $(SANITIZER_EXEC_CFLAGS) \ -DNETWORKMANAGER_COMPILATION_TEST \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT @@ -1175,6 +1200,7 @@ src_cppflags = \ $(LIBAUDIT_CFLAGS) \ $(SYSTEMD_LOGIN_CFLAGS) \ $(SYSTEMD_JOURNAL_CFLAGS) \ + $(SANITIZER_EXEC_CFLAGS) \ \ $(NULL) @@ -1640,6 +1666,7 @@ check_ltlibraries += src/libNetworkManagerTest.la src_tests_cppflags = \ $(src_cppflags) \ + $(SANITIZER_EXEC_CFLAGS) \ -DNETWORKMANAGER_COMPILATION_TEST if REQUIRE_ROOT_TESTS @@ -1688,7 +1715,8 @@ src_NetworkManager_LDADD = \ src_NetworkManager_LDFLAGS = \ -rdynamic \ - -Wl,--version-script="src/NetworkManager.ver" + -Wl,--version-script="src/NetworkManager.ver" \ + $(SANITIZER_EXEC_LDFLAGS) $(src_NetworkManager_OBJECTS): $(libnm_core_lib_h_pub_mkenums) @@ -1709,7 +1737,8 @@ src_nm_iface_helper_LDADD = \ $(DL_LIBS) src_nm_iface_helper_LDFLAGS = \ - -Wl,--version-script="$(srcdir)/linker-script-binary.ver" + -Wl,--version-script="$(srcdir)/linker-script-binary.ver" \ + $(SANITIZER_EXEC_LDFLAGS) $(src_nm_iface_helper_OBJECTS): $(libnm_core_lib_h_pub_mkenums) @@ -1768,6 +1797,9 @@ src_dhcp_tests_test_dhcp_utils_CPPFLAGS = $(src_dhcp_tests_cppflags) src_dhcp_tests_test_dhcp_dhclient_LDADD = $(src_dhcp_tests_ldadd) src_dhcp_tests_test_dhcp_utils_LDADD = $(src_dhcp_tests_ldadd) +src_dhcp_tests_test_dhcp_dhclient_LDFLAGS = $(src_tests_ldflags) +src_dhcp_tests_test_dhcp_utils_LDFLAGS = $(src_tests_ldflags) + $(src_dhcp_tests_test_dhcp_dhclient_OBJECTS): $(libnm_core_lib_h_pub_mkenums) $(src_dhcp_tests_test_dhcp_utils_OBJECTS): $(libnm_core_lib_h_pub_mkenums) @@ -1861,7 +1893,8 @@ src_settings_plugins_keyfile_tests_test_keyfile_CPPFLAGS = \ src_settings_plugins_keyfile_tests_test_keyfile_LDFLAGS = \ $(GLIB_LIBS) \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_EXEC_LDFLAGS) src_settings_plugins_keyfile_tests_test_keyfile_LDADD = \ src/libNetworkManagerTest.la @@ -1973,7 +2006,8 @@ src_settings_plugins_ibft_tests_test_ibft_CPPFLAGS = \ src_settings_plugins_ibft_tests_test_ibft_LDFLAGS = \ $(GLIB_LIBS) \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_EXEC_LDFLAGS) src_settings_plugins_ibft_tests_test_ibft_LDADD = \ src/settings/plugins/ibft/libnms-ibft-core.la \ @@ -2024,6 +2058,7 @@ src_settings_plugins_ifcfg_rh_cppflags = \ -I$(builddir)/libnm-core \ $(GLIB_CFLAGS) \ $(NSS_CFLAGS) \ + $(SANITIZER_EXEC_CFLAGS) \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_DAEMON \ -DSYSCONFDIR=\"$(sysconfdir)\" \ -DSBINDIR=\"$(sbindir)\" @@ -2080,7 +2115,8 @@ src_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_CPPFLAGS = $(src src_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_LDFLAGS = \ -module -avoid-version \ - -Wl,--version-script="$(srcdir)/linker-script-settings.ver" + -Wl,--version-script="$(srcdir)/linker-script-settings.ver" \ + $(SANITIZER_EXEC_LDFLAGS) src_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_LIBADD = \ src/settings/plugins/ifcfg-rh/libnms-ifcfg-rh-core.la @@ -2109,7 +2145,8 @@ src_settings_plugins_ifcfg_rh_tests_test_ifcfg_rh_CPPFLAGS = \ src_settings_plugins_ifcfg_rh_tests_test_ifcfg_rh_LDFLAGS = \ $(GLIB_LIBS) \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_EXEC_LDFLAGS) src_settings_plugins_ifcfg_rh_tests_test_ifcfg_rh_LDADD = \ src/settings/plugins/ifcfg-rh/libnms-ifcfg-rh-core.la \ @@ -2416,7 +2453,8 @@ src_settings_plugins_ifupdown_tests_test_ifupdown_CPPFLAGS = \ src_settings_plugins_ifupdown_tests_test_ifupdown_LDFLAGS = \ $(GLIB_LDFLAGS) \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_EXEC_LDFLAGS) src_settings_plugins_ifupdown_tests_test_ifupdown_LDADD = \ src/settings/plugins/ifupdown/libnms-ifupdown-core.la \ @@ -2718,6 +2756,7 @@ src_devices_wifi_tests_test_general_CPPFLAGS = \ $(GLIB_CFLAGS) src_devices_wifi_tests_test_general_LDADD = src/libNetworkManagerTest.la +src_devices_wifi_tests_test_general_LDFLAGS = $(SANITIZER_EXEC_LDFLAGS) $(src_devices_wifi_tests_test_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums) @@ -2846,6 +2885,9 @@ src_dnsmasq_tests_test_dnsmasq_utils_CPPFLAGS = \ src_dnsmasq_tests_test_dnsmasq_utils_LDADD = \ src/libNetworkManagerTest.la +src_dnsmasq_tests_test_dnsmasq_utils_LDFLAGS = \ + $(SANITIZER_EXEC_LDFLAGS) + $(src_dnsmasq_tests_test_dnsmasq_utils_OBJECTS): $(libnm_core_lib_h_pub_mkenums) EXTRA_DIST += \ @@ -2856,7 +2898,8 @@ EXTRA_DIST += \ ############################################################################### src_platform_tests_ldflags = \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_EXEC_LDFLAGS) src_platform_tests_libadd = \ src/libNetworkManagerTest.la \ @@ -2951,7 +2994,8 @@ EXTRA_DIST += \ ############################################################################### src_devices_tests_ldflags = \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_EXEC_LDFLAGS) check_programs += \ src/devices/tests/test-lldp \ @@ -2978,7 +3022,8 @@ EXTRA_DIST += \ ############################################################################### src_ndisc_tests_ldflags = \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_EXEC_LDFLAGS) src_ndisc_tests_ldadd = \ src/libNetworkManagerTest.la \ @@ -2988,11 +3033,11 @@ check_programs += src/ndisc/tests/test-ndisc-fake check_programs_norun += src/ndisc/tests/test-ndisc-linux src_ndisc_tests_test_ndisc_linux_CPPFLAGS = $(src_tests_cppflags) -src_ndisc_tests_test_ndisc_linux_LDFLAGS = $(src_ndisc_tests_flags) +src_ndisc_tests_test_ndisc_linux_LDFLAGS = $(src_ndisc_tests_ldflags) src_ndisc_tests_test_ndisc_linux_LDADD = $(src_ndisc_tests_ldadd) src_ndisc_tests_test_ndisc_fake_CPPFLAGS = $(src_tests_cppflags) -src_ndisc_tests_test_ndisc_fake_LDFLAGS = $(src_ndisc_tests_flags) +src_ndisc_tests_test_ndisc_fake_LDFLAGS = $(src_ndisc_tests_ldflags) src_ndisc_tests_test_ndisc_fake_LDADD = $(src_ndisc_tests_ldadd) $(src_ndisc_tests_test_ndisc_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums) @@ -3014,6 +3059,9 @@ src_supplicant_tests_test_supplicant_config_CPPFLAGS = \ src_supplicant_tests_test_supplicant_config_LDADD = \ src/libNetworkManagerTest.la +src_supplicant_tests_test_supplicant_config_LDFLAGS = \ + $(SANITIZER_EXEC_LDFLAGS) + $(src_supplicant_tests_test_supplicant_config_OBJECTS): $(libnm_core_lib_h_pub_mkenums) EXTRA_DIST += \ @@ -3040,6 +3088,9 @@ src_tests_config_test_config_CPPFLAGS = \ src_tests_config_test_config_LDADD = \ src/libNetworkManagerTest.la +src_tests_config_test_config_LDFLAGS = \ + $(SANITIZER_EXEC_LDFLAGS) + $(src_tests_config_test_config_OBJECTS): $(libnm_core_lib_h_pub_mkenums) EXTRA_DIST += \ @@ -3058,7 +3109,8 @@ EXTRA_DIST += \ ############################################################################### src_tests_ldflags = \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_EXEC_LDFLAGS) src_tests_ldadd = \ src/libNetworkManagerTest.la @@ -3251,7 +3303,11 @@ dispatcher_tests_test_dispatcher_envp_CPPFLAGS = \ -DSRCDIR=\"$(abs_srcdir)/dispatcher/tests\" \ -DNETWORKMANAGER_COMPILATION_TEST \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT \ - $(GLIB_CFLAGS) + $(GLIB_CFLAGS) \ + $(SANITIZER_EXEC_CFLAGS) + +dispatcher_tests_test_dispatcher_envp_LDFLAGS = \ + $(SANITIZER_EXEC_LDFLAGS) dispatcher_tests_test_dispatcher_envp_LDADD = \ libnm/libnm.la \ @@ -3413,7 +3469,11 @@ clients_common_tests_test_general_CPPFLAGS = \ -I$(srcdir)/clients/common/tests \ $(clients_cppflags) \ -DNETWORKMANAGER_COMPILATION_TEST \ - -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT \ + $(SANITIZER_EXEC_CFLAGS) + +clients_common_tests_test_general_LDFLAGS = \ + $(SANITIZER_EXEC_LDFLAGS) clients_common_tests_test_general_LDADD = \ libnm/libnm.la \ @@ -3455,6 +3515,7 @@ clients_cli_nmcli_SOURCES = \ clients_cli_nmcli_CPPFLAGS = \ -I$(srcdir)/clients/cli \ $(clients_cppflags) \ + $(SANITIZER_EXEC_CFLAGS) \ -DG_LOG_DOMAIN=\""nmcli"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT \ -DNMCLI_LOCALEDIR=\"$(datadir)/locale\" @@ -3475,7 +3536,8 @@ clients_cli_nmcli_LDADD += $(POLKIT_LIBS) endif clients_cli_nmcli_LDFLAGS = \ - -Wl,--version-script="$(srcdir)/linker-script-binary.ver" + -Wl,--version-script="$(srcdir)/linker-script-binary.ver" \ + $(SANITIZER_EXEC_LDFLAGS) $(clients_cli_nmcli_OBJECTS): $(libnm_core_lib_h_pub_mkenums) @@ -3563,6 +3625,7 @@ clients_tui_newt_libnmt_newt_a_CPPFLAGS = \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT \ $(GLIB_CFLAGS) \ $(NEWT_CFLAGS) \ + $(SANITIZER_EXEC_CFLAGS) \ $(NULL) bin_PROGRAMS += clients/tui/nmtui @@ -3661,7 +3724,8 @@ clients_tui_nmtui_CPPFLAGS = \ -DLOCALEDIR=\""$(localedir)"\" clients_tui_nmtui_LDFLAGS = \ - -Wl,--version-script="$(srcdir)/linker-script-binary.ver" + -Wl,--version-script="$(srcdir)/linker-script-binary.ver" \ + $(SANITIZER_EXEC_LDFLAGS) clients_tui_nmtui_LDADD = \ libnm/libnm.la \ @@ -4005,13 +4069,17 @@ libnm_util_tests_cppflags = \ -DBUILD_DIR=\"$(abs_builddir)/libnm-util/tests\" \ -DTEST_CERT_DIR=\"$(abs_srcdir)/libnm-core/tests/certs\" \ -DNETWORKMANAGER_COMPILATION_TEST \ - -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_UTIL + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_UTIL \ + $(SANITIZER_EXEC_CFLAGS) libnm_util_tests_ldadd = \ libnm-util/libnm-util.la \ $(GLIB_LIBS) \ $(DBUS_LIBS) +libnm_util_tests_ldflags = \ + $(SANITIZER_EXEC_LDFLAGS) + check_programs += \ libnm-util/tests/test-settings-defaults \ libnm-util/tests/test-crypto \ @@ -4025,29 +4093,36 @@ check_programs_norun += \ libnm_util_tests_test_settings_defaults_CPPFLAGS = $(libnm_util_tests_cppflags) libnm_util_tests_test_settings_defaults_LDADD = $(libnm_util_tests_ldadd) +libnm_util_tests_test_settings_defaults_LDFLAGS = $(libnm_util_tests_ldflags) libnm_util_tests_test_crypto_CPPFLAGS = $(libnm_util_tests_cppflags) libnm_util_tests_test_crypto_LDADD = \ libnm-util/libtest-crypto.la \ $(libnm_util_tests_ldadd) +libnm_util_tests_test_crypto_LDFLAGS = $(libnm_util_tests_ldflags) libnm_util_tests_test_secrets_CPPFLAGS = $(libnm_util_tests_cppflags) libnm_util_tests_test_secrets_LDADD = $(libnm_util_tests_ldadd) +libnm_util_tests_test_secrets_LDFLAGS = $(libnm_util_tests_ldflags) libnm_util_tests_test_general_DEPENDENCIES = libnm-util/tests/test-libnm-linking libnm_util_tests_test_general_CPPFLAGS = $(libnm_util_tests_cppflags) libnm_util_tests_test_general_LDADD = $(libnm_util_tests_ldadd) +libnm_util_tests_test_general_LDFLAGS = $(libnm_util_tests_ldflags) libnm_util_tests_test_setting_8021x_CPPFLAGS = $(libnm_util_tests_cppflags) libnm_util_tests_test_setting_8021x_LDADD = $(libnm_util_tests_ldadd) +libnm_util_tests_test_setting_8021x_LDFLAGS = $(libnm_util_tests_ldflags) libnm_util_tests_test_setting_dcb_CPPFLAGS = $(libnm_util_tests_cppflags) libnm_util_tests_test_setting_dcb_LDADD = $(libnm_util_tests_ldadd) +libnm_util_tests_test_setting_dcb_LDFLAGS = $(libnm_util_tests_ldflags) libnm_util_tests_test_libnm_linking_CPPFLAGS = $(libnm_util_tests_cppflags) libnm_util_tests_test_libnm_linking_LDADD = \ libnm/libnm.la \ $(libnm_util_tests_ldadd) +libnm_util_tests_test_libnm_linking_LDFLAGS = $(libnm_util_tests_ldflags) $(libnm_util_tests_test_settings_defaults_OBJECTS): $(libnm_core_lib_h_pub_mkenums) $(libnm_util_tests_test_crypto_OBJECTS): $(libnm_core_lib_h_pub_mkenums) diff --git a/configure.ac b/configure.ac index f7a1eea937..62dae15eef 100644 --- a/configure.ac +++ b/configure.ac @@ -1139,16 +1139,24 @@ fi NM_LTO NM_LD_GC -AC_ARG_ENABLE(address-sanitizer, - AS_HELP_STRING([--enable-address-sanitizer], [Compile with address sanitizer (default: no)])) -if (test "${enable_address_sanitizer}" = "yes"); then +AC_ARG_WITH(address-sanitizer, + AS_HELP_STRING([--with-address-sanitizer=yes|no|exec], [Enable address sanitizer (default: no)])) +if test "$with_address_sanitizer" = yes -o "$with_address_sanitizer" = "exec"; then CC_CHECK_FLAGS_APPEND([asan_cflags], [CFLAGS], [-fsanitize=address]) AS_IF([test -z "$asan_cflags"], [AC_MSG_ERROR([*** -fsanitize=address is not supported])]) - sanitizer_cflags="$sanitizer_cflags -fsanitize=address" - sanitizer_ldflags="$sanitizer_ldflags -Wc,-fsanitize=address" - sanitizers="${sanitizers}asan " + sanitizer_exec_cflags="$sanitizer_exec_cflags -fsanitize=address" + sanitizer_exec_ldflags="$sanitizer_exec_ldflags -Wc,-fsanitize=address" + + if test "$with_address_sanitizer" = "yes"; then + sanitizer_lib_cflags="$sanitizer_lib_cflags -fsanitize=address" + sanitizer_lib_ldflags="$sanitizer_lib_ldflags -Wc,-fsanitize=address" + sanitizers="${sanitizers}address " + asan_options="ASAN_OPTIONS=detect_leaks=0" + else + sanitizers="${sanitizers}address(executables-only) " + fi fi AC_ARG_ENABLE(undefined-sanitizer, @@ -1159,20 +1167,22 @@ if (test "${enable_undefined_sanitizer}" = "yes"); then AS_IF([test -z "$ubsan_cflags"], [AC_MSG_ERROR([*** -fsanitize=undefined is not supported])]) - sanitizer_cflags="$sanitizer_cflags -fsanitize=undefined" - sanitizer_ldflags="$sanitizer_ldflags -Wc,-fsanitize=undefined" - sanitizers="${sanitizers}ubsan " + sanitizer_exec_cflags="$sanitizer_exec_cflags -fsanitize=undefined" + sanitizer_lib_cflags="$sanitizer_lib_cflags -fsanitize=undefined" + sanitizer_exec_ldflags="$sanitizer_exec_ldflags -Wc,-fsanitize=undefined" + sanitizer_lib_ldflags="$sanitizer_lib_ldflags -Wc,-fsanitize=undefined" + sanitizers="${sanitizers}undefined-behavior " fi if test -n "$sanitizers"; then - CFLAGS="$CFLAGS $sanitizer_cflags -DVALGRIND=1 -fno-omit-frame-pointer" - LDFLAGS="$LDFLAGS $sanitizer_ldflags" sanitizers="${sanitizers% }" - AC_SUBST(SANITIZER_ENV, [ASAN_OPTIONS=detect_leaks=0]) + AC_SUBST(SANITIZER_ENV, ["$asan_options"]) + AC_SUBST(SANITIZER_EXEC_CFLAGS, ["$sanitizer_exec_cflags -DVALGRIND=1 -fno-omit-frame-pointer"]) + AC_SUBST(SANITIZER_LIB_CFLAGS, ["$sanitizer_lib_cflags -DVALGRIND=1 -fno-omit-frame-pointer"]) + AC_SUBST(SANITIZER_EXEC_LDFLAGS, [$sanitizer_exec_ldflags]) + AC_SUBST(SANITIZER_LIB_LDFLAGS, [$sanitizer_lib_ldflags]) fi -AC_SUBST(SANITIZERS, [$sanitizers]) - AC_MSG_CHECKING([CC support C11 _Generic()]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int foo(void); int foo() { int a = 0; int b = _Generic (a, int: 4); return b + a; }]], [[foo();]])], diff --git a/docs/libnm/Makefile.am b/docs/libnm/Makefile.am index 89784967fa..c2bcff1be5 100644 --- a/docs/libnm/Makefile.am +++ b/docs/libnm/Makefile.am @@ -72,11 +72,13 @@ GTKDOC_CFLAGS = \ -I$(top_srcdir)/libnm \ -I$(top_builddir)/libnm \ -DNM_VERSION_MIN_REQUIRED=NM_VERSION_0_9_8 \ - $(GLIB_CFLAGS) + $(GLIB_CFLAGS) \ + $(SANITIZER_EXEC_CFLAGS) GTKDOC_LIBS = \ $(top_builddir)/libnm/libnm.la \ - $(GLIB_LIBS) + $(GLIB_LIBS) \ + $(SANITIZER_EXEC_LDFLAGS) # include common portion ... From 936e0a51fea31f9ba0484c29d1dcbe1e367ce9e2 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 7 Feb 2018 15:02:53 +0100 Subject: [PATCH 2/5] libnm-core: don't use RTLD_DEEPBIND when building with asan The address sanitizer is not compatible [1] with libraries dynamically opened using RTLD_DEEPBIND: disable the flag when building with asan. [1] https://github.com/google/sanitizers/issues/611 --- configure.ac | 1 + libnm-core/nm-json.c | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 62dae15eef..01984dec76 100644 --- a/configure.ac +++ b/configure.ac @@ -1148,6 +1148,7 @@ if test "$with_address_sanitizer" = yes -o "$with_address_sanitizer" = "exec"; t sanitizer_exec_cflags="$sanitizer_exec_cflags -fsanitize=address" sanitizer_exec_ldflags="$sanitizer_exec_ldflags -Wc,-fsanitize=address" + AC_DEFINE(ASAN_BUILD, 1, [Whether NM is built with address sanitizer]) if test "$with_address_sanitizer" = "yes"; then sanitizer_lib_cflags="$sanitizer_lib_cflags -fsanitize=address" diff --git a/libnm-core/nm-json.c b/libnm-core/nm-json.c index f359a76046..aa181a4aec 100644 --- a/libnm-core/nm-json.c +++ b/libnm-core/nm-json.c @@ -94,6 +94,7 @@ nm_jansson_load (void) MISSING, } state = UNKNOWN; void *handle; + int mode; if (G_LIKELY (state != UNKNOWN)) goto out; @@ -102,7 +103,13 @@ nm_jansson_load (void) if (!bind_symbols (RTLD_DEFAULT)) goto out; - handle = dlopen (JANSSON_SONAME, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); + mode = RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND; +#if defined (ASAN_BUILD) + /* Address sanitizer is incompatible with RTLD_DEEPBIND. */ + mode &= ~RTLD_DEEPBIND; +#endif + handle = dlopen (JANSSON_SONAME, mode); + if (!handle) goto out; From 0fb79890925920b40f52862896cbb7ed95a1973f Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 8 Feb 2018 09:05:54 +0100 Subject: [PATCH 3/5] rpm: add requirements for sanitizer builds --- contrib/fedora/rpm/NetworkManager.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index 17fff3cef9..b9d844754a 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -168,6 +168,12 @@ BuildRequires: dbus-python BuildRequires: libselinux-devel BuildRequires: polkit-devel BuildRequires: jansson-devel +%if %{with sanitizer} +BuildRequires: libasan +%if 0%{?fedora} +BuildRequires: libubsan +%endif +%endif %description From f548806213bbfe72bb1013be70316e099da313d7 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 8 Feb 2018 09:07:16 +0100 Subject: [PATCH 4/5] rpm: update sanitizer build flags Disable undefined sanitizer on RHEL since it's not supported. Also, enable address sanitizer only for executables, as having it enabled in libraries causes problems when applications built without asan load them. --- contrib/fedora/rpm/NetworkManager.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index b9d844754a..baca13ea90 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -409,10 +409,12 @@ intltoolize --automake --copy --force --with-config-dhcp-default=dhclient \ --with-crypto=nss \ %if %{with sanitizer} - --enable-address-sanitizer \ + --with-address-sanitizer=exec \ +%if 0%{?fedora} --enable-undefined-sanitizer \ +%endif %else - --disable-address-sanitizer \ + --with-address-sanitizer=no \ --disable-undefined-sanitizer \ %endif %if %{with debug} From 43960d4b15f05436088cc2cb4087984c3cc3c6f9 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Fri, 9 Feb 2018 11:33:39 +0100 Subject: [PATCH 5/5] connectivity: fix wrong memory access Don't use message data after calling curl_multi_remove_handle(). Fixes the following asan error: ================================================================= ==13238==ERROR: AddressSanitizer: heap-use-after-free on address 0x608000091ad0 at pc 0x55750f8d9a10 bp 0x7ffeb7f5f210 sp 0x7ffeb7f5f200 READ of size 8 at 0x608000091ad0 thread T0 #0 0x55750f8d9a0f in curl_check_connectivity (/usr/sbin/NetworkManager+0x190a0f) #1 0x55750f8da7dd in curl_socketevent_cb (/usr/sbin/NetworkManager+0x1917dd) #2 0x7f73cb64e8f8 in g_main_context_dispatch (/lib64/libglib-2.0.so.0+0x4a8f8) #3 0x7f73cb64ec57 (/lib64/libglib-2.0.so.0+0x4ac57) #4 0x7f73cb64ef29 in g_main_loop_run (/lib64/libglib-2.0.so.0+0x4af29) #5 0x55750f85c3f4 (/usr/sbin/NetworkManager+0x1133f4) #6 0x7f73c9f19384 in __libc_start_main (/lib64/libc.so.6+0x22384) #7 0x55750f85d7f7 (/usr/sbin/NetworkManager+0x1147f7) 0x608000091ad0 is located 48 bytes inside of 88-byte region [0x608000091aa0,0x608000091af8) freed by thread T0 here: #0 0x7f73cd61f508 in __interceptor_free (/lib64/libasan.so.4+0xde508) #1 0x7f73ca710eaa in curl_multi_remove_handle (/lib64/libcurl.so.4+0x32eaa) previously allocated by thread T0 here: #0 0x7f73cd61fa88 in __interceptor_calloc (/lib64/libasan.so.4+0xdea88) #1 0x7f73ca710b3d in curl_multi_add_handle (/lib64/libcurl.so.4+0x32b3d) SUMMARY: AddressSanitizer: heap-use-after-free (/usr/sbin/NetworkManager+0x190a0f) --- src/nm-connectivity.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 656d02b9da..d8d4bf7d88 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -137,6 +137,7 @@ curl_check_connectivity (CURLM *mhandle, CURLMcode ret) ConCheckCbData *cb_data; CURLMsg *msg; CURLcode eret; + CURL *easy_handle; gint m_left; long response_code; @@ -182,8 +183,10 @@ curl_check_connectivity (CURLM *mhandle, CURLMcode ret) finish_cb_data (cb_data, c); } - curl_multi_remove_handle (mhandle, msg->easy_handle); - curl_easy_cleanup (msg->easy_handle); + /* Do not use message data after calling curl_multi_remove_handle() */ + easy_handle = msg->easy_handle; + curl_multi_remove_handle (mhandle, easy_handle); + curl_easy_cleanup (easy_handle); } }