From dd3f5ee49924cd44c2ff6a7fff6b45677361a54e Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Sun, 5 Apr 2026 20:56:26 -0700 Subject: [PATCH 1/2] Add versioned symbol support --- auparse/Makefile.am | 3 ++ auparse/libauparse.map | 90 ++++++++++++++++++++++++++++++++++++++++ auplugin/Makefile.am | 5 ++- auplugin/libauplugin.map | 27 ++++++++++++ configure.ac | 1 + lib/Makefile.am | 3 ++ lib/libaudit.map | 86 ++++++++++++++++++++++++++++++++++++++ m4/ld-version-script.m4 | 50 ++++++++++++++++++++++ 8 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 auparse/libauparse.map create mode 100644 auplugin/libauplugin.map create mode 100644 lib/libaudit.map create mode 100644 m4/ld-version-script.m4 diff --git a/auparse/Makefile.am b/auparse/Makefile.am index a68209346..20715dfab 100644 --- a/auparse/Makefile.am +++ b/auparse/Makefile.am @@ -50,6 +50,9 @@ nodist_libauparse_la_SOURCES = $(BUILT_SOURCES) libauparse_la_LIBADD = ${top_builddir}/lib/libaudit.la ${top_builddir}/common/libaucommon.la libauparse_la_DEPENDENCIES = $(libauparse_la_SOURCES) ${top_builddir}/config.h ${top_builddir}/common/libaucommon.la libauparse_la_LDFLAGS = -Wl,-z,relro +if HAVE_LD_VERSION_SCRIPT +libauparse_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libauparse.map +endif message.c: cp ${top_srcdir}/lib/message.c . diff --git a/auparse/libauparse.map b/auparse/libauparse.map new file mode 100644 index 000000000..5a6232469 --- /dev/null +++ b/auparse/libauparse.map @@ -0,0 +1,90 @@ +/* Avoid modifying a symbol set after it has been released + When adding features in a new release, add a new set + Removing features is a breaking change */ +LIBAUDIT_4.1 { + global: + auparse_add_callback; + auparse_destroy; + auparse_destroy_ext; + auparse_do_interpretation; + auparse_feed; + auparse_feed_age_events; + auparse_feed_has_data; + auparse_feed_has_ready_event; + auparse_find_field; + auparse_find_field_next; + auparse_first_field; + auparse_first_record; + _auparse_flush_caches; + auparse_flush_feed; + _auparse_free_interpretations; + auparse_get_field_int; + auparse_get_field_name; + auparse_get_field_num; + auparse_get_field_str; + auparse_get_field_type; + auparse_get_filename; + auparse_get_line_number; + auparse_get_milli; + auparse_get_node; + auparse_get_num_fields; + auparse_get_num_records; + auparse_get_record_interpretations; + auparse_get_record_num; + auparse_get_record_text; + auparse_get_serial; + auparse_get_time; + auparse_get_timestamp; + auparse_get_type; + auparse_get_type_name; + auparse_goto_field_num; + auparse_goto_record_num; + auparse_init; + auparse_interp_adjust_type; + auparse_interpret_field; + auparse_interpret_realpath; + auparse_interpret_sock_address; + auparse_interpret_sock_family; + auparse_interpret_sock_port; + _auparse_load_interpretations; + _auparse_lookup_interpretation; + auparse_metrics; + auparse_new_buffer; + auparse_next_event; + auparse_next_field; + auparse_next_record; + auparse_node_compare; + auparse_normalize; + auparse_normalize_get_action; + auparse_normalize_get_event_kind; + auparse_normalize_get_results; + auparse_normalize_how; + auparse_normalize_key; + auparse_normalize_object_first_attribute; + auparse_normalize_object_kind; + auparse_normalize_object_kind_int; + auparse_normalize_object_next_attribute; + auparse_normalize_object_primary; + auparse_normalize_object_primary2; + auparse_normalize_object_secondary; + auparse_normalize_session; + auparse_normalize_subject_first_attribute; + auparse_normalize_subject_kind; + auparse_normalize_subject_next_attribute; + auparse_normalize_subject_primary; + auparse_normalize_subject_secondary; + auparse_reset; + auparse_set_eoe_timeout; + auparse_set_escape_mode; + auparse_timestamp_compare; + ausearch_add_expression; + ausearch_add_interpreted_item; + ausearch_add_item; + ausearch_add_regex; + ausearch_add_timestamp_item; + ausearch_add_timestamp_item_ex; + ausearch_clear; + ausearch_cur_event; + ausearch_next_event; + ausearch_set_stop; +}; diff --git a/auplugin/Makefile.am b/auplugin/Makefile.am index 4fec6f1c4..05df511ae 100644 --- a/auplugin/Makefile.am +++ b/auplugin/Makefile.am @@ -31,8 +31,11 @@ AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/lib -I${top_srcdir}/common \ lib_LTLIBRARIES = libauplugin.la include_HEADERS = auplugin.h -libauplugin_la_SOURCES = auplugin-fgets.c auplugin.c +libauplugin_la_SOURCES = auplugin-fgets.c auplugin.c libauplugin_la_LDFLAGS = -Wl,-z,relro -version-info $(VERSION_INFO) +if HAVE_LD_VERSION_SCRIPT +libauplugin_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libauplugin.map +endif libauplugin_la_LIBADD = ${top_builddir}/audisp/libqueue.la \ ${top_builddir}/auparse/libauparse.la -lpthread diff --git a/auplugin/libauplugin.map b/auplugin/libauplugin.map new file mode 100644 index 000000000..6c9e64352 --- /dev/null +++ b/auplugin/libauplugin.map @@ -0,0 +1,27 @@ +/* Avoid modifying a symbol set after it has been released + When adding features in a new release, add a new set + Removing features is a breaking change */ +LIBAUDIT_4.1 { + global: + auplugin_event_feed; + auplugin_event_loop; + auplugin_fgets; + auplugin_fgets_clear; + auplugin_fgets_clear_r; + auplugin_fgets_destroy; + auplugin_fgets_eof; + auplugin_fgets_eof_r; + auplugin_fgets_init; + auplugin_fgets_more; + auplugin_fgets_more_r; + auplugin_fgets_r; + auplugin_init; + auplugin_queue_depth; + auplugin_queue_max_depth; + auplugin_queue_overflow; + auplugin_register_stats_callback; + auplugin_report_stats; + auplugin_setvbuf; + auplugin_setvbuf_r; + auplugin_stop; +}; diff --git a/configure.ac b/configure.ac index 9fe8ecd1b..f2881faa3 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_TARGET AM_INIT_AUTOMAKE([subdir-objects foreign]) LT_INIT +gl_LD_VERSION_SCRIPT AC_SUBST(LIBTOOL_DEPS) OLDLIBS="$LIBS" m4_include([src/libev/libev.m4]) diff --git a/lib/Makefile.am b/lib/Makefile.am index 18af4bb2a..ac0e9e01c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -42,6 +42,9 @@ libaudit_la_SOURCES = libaudit.c netlink.c \ libaudit_la_LIBADD = $(CAPNG_LDADD) ${top_builddir}/common/libaucommon.la libaudit_la_DEPENDENCIES = $(libaudit_la_SOURCES) ../config.h ${top_builddir}/common/libaucommon.la libaudit_la_LDFLAGS = -Wl,-z,relro -version-info $(VERSION_INFO) +if HAVE_LD_VERSION_SCRIPT +libaudit_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libaudit.map +endif nodist_libaudit_la_SOURCES = $(BUILT_SOURCES) BUILT_SOURCES = actiontabs.h errtabs.h fieldtabs.h flagtabs.h \ diff --git a/lib/libaudit.map b/lib/libaudit.map new file mode 100644 index 000000000..2fe6b1c67 --- /dev/null +++ b/lib/libaudit.map @@ -0,0 +1,86 @@ +/* Avoid modifying a symbol set after it has been released + When adding features in a new release, add a new set + Removing features is a breaking change */ +LIBAUDIT_4.1 { + global: + audit_action_to_name; + audit_add_rule_data; + audit_add_watch; + audit_add_watch_dir; + audit_can_control; + audit_can_read; + audit_can_write; + audit_close; + audit_delete_rule_data; + audit_detect_machine; + audit_determine_machine; + audit_elf_to_machine; + audit_encode_nv_string; + audit_encode_value; + audit_errno_to_name; + audit_field_to_name; + audit_flag_to_name; + audit_format_signal_info; + audit_fstype_to_name; + audit_ftype_to_name; + audit_get_features; + audit_getloginuid; + audit_get_reply; + audit_get_session; + audit_is_enabled; + audit_log_acct_message; + audit_log_semanage_message; + audit_log_user_avc_message; + audit_log_user_command; + audit_log_user_comm_message; + audit_log_user_message; + audit_machine_to_elf; + audit_machine_to_name; + audit_make_equivalent; + audit_msg_type_to_name; + audit_name_to_action; + audit_name_to_errno; + audit_name_to_field; + audit_name_to_flag; + audit_name_to_fstype; + audit_name_to_ftype; + audit_name_to_machine; + audit_name_to_msg_type; + audit_name_to_syscall; + audit_name_to_uringop; + audit_number_to_errmsg; + audit_open; + audit_operator_to_symbol; + _audit_parse_syscall; + audit_request_features; + audit_request_rules_list_data; + audit_request_signal_info; + audit_request_status; + audit_reset_backlog_wait_time_actual; + audit_reset_lost; + audit_rule_create_data; + audit_rule_fieldpair_data; + audit_rule_free_data; + audit_rule_init_data; + audit_rule_interfield_comp_data; + audit_rule_io_uringbyname_data; + audit_rule_syscallbyname_data; + __audit_send; + audit_send; + audit_set_backlog_limit; + audit_set_backlog_wait_time; + audit_set_enabled; + audit_set_failure; + audit_set_feature; + audit_setloginuid; + audit_set_loginuid_immutable; + audit_set_pid; + audit_set_rate_limit; + audit_syscall_to_name; + audit_trim_subtrees; + audit_update_watch_perms; + audit_uringop_to_name; + audit_value_needs_encoding; + get_auditfail_action; + set_aumessage_mode; +}; diff --git a/m4/ld-version-script.m4 b/m4/ld-version-script.m4 new file mode 100644 index 000000000..1c6eba71c --- /dev/null +++ b/m4/ld-version-script.m4 @@ -0,0 +1,50 @@ +# ld-version-script.m4 +# serial 7 +dnl Copyright (C) 2008-2026 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl This file is offered as-is, without any warranty. + +dnl From Simon Josefsson + +# FIXME: The test below returns a false positive for mingw +# cross-compiles, 'local:' statements does not reduce number of +# exported symbols in a DLL. Use --disable-ld-version-script to work +# around the problem. + +# gl_LD_VERSION_SCRIPT +# -------------------- +# Check if LD supports linker scripts, and define automake conditional +# HAVE_LD_VERSION_SCRIPT if so. +AC_DEFUN([gl_LD_VERSION_SCRIPT], +[ + AC_ARG_ENABLE([ld-version-script], + [AS_HELP_STRING([[--enable-ld-version-script]], + [enable linker version script (default is enabled when possible)])], + [have_ld_version_script=$enableval], + [AC_CACHE_CHECK([if LD -Wl,--version-script works], + [gl_cv_sys_ld_version_script], + [gl_cv_sys_ld_version_script=no + saved_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map" + echo foo >conftest.map + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [], + [cat > conftest.map < Date: Tue, 14 Apr 2026 09:36:47 -0700 Subject: [PATCH 2/2] versioned symbols: Print a list of un-versioned symbols during CI --- .github/scripts/check-versioned-symbols.sh | 80 ++++++++++++++++++++++ .github/workflows/ci.yml | 3 + 2 files changed, 83 insertions(+) create mode 100755 .github/scripts/check-versioned-symbols.sh diff --git a/.github/scripts/check-versioned-symbols.sh b/.github/scripts/check-versioned-symbols.sh new file mode 100755 index 000000000..59548e50b --- /dev/null +++ b/.github/scripts/check-versioned-symbols.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# Check for unversioned symbols in libraries + +set -e + +# Function to check if a library has versioned symbols +has_versioned_symbols() { + local lib=$1 + # Check if the library has version definitions + if readelf -V "$lib" 2>/dev/null | grep -q "Version definition section"; then + return 0 + else + return 1 + fi +} + +# Function to get unversioned symbols from a library +get_unversioned_symbols() { + local lib=$1 + objdump -T "$lib" | \ + grep -F .text | \ + awk '{if($6=="Base") {print $7;}}' | \ + c++filt | \ + awk '/[() ]/ {print " \"" $0 "\";";} + !/[() ]/ {print " " $0 ";";}' | \ + sort +} + +# Libraries to check +LIBRARIES=( + "lib/.libs/libaudit.so" + "auparse/.libs/libauparse.so" + "auplugin/.libs/libauplugin.so" +) + +echo "Checking for versioned symbols in built libraries..." + +# Track if any library uses versioned symbols +has_versioned=0 +# Track if we found any unversioned symbols +found_unversioned=0 + +for lib in "${LIBRARIES[@]}"; do + if [ ! -f "$lib" ]; then + echo "Warning: Library $lib not found, skipping..." + continue + fi + + if has_versioned_symbols "$lib"; then + echo "- Library $lib has versioned symbols" + has_versioned=1 + + # Check for unversioned symbols + unversioned=$(get_unversioned_symbols "$lib") + if [ -n "$unversioned" ]; then + echo "ERROR: Found unversioned symbols in $lib:" + echo "$unversioned" + found_unversioned=1 + else + echo " No unversioned symbols found" + fi + else + echo "- Library $lib does not have versioned symbols (version script not applied)" + fi + echo +done + +if [ $has_versioned -eq 0 ]; then + echo "No libraries with versioned symbols were found." + echo "This is expected if the linker does not support version scripts." + exit 0 +fi + +if [ $found_unversioned -eq 1 ]; then + echo "FAIL: Unversioned symbols were found in libraries with version scripts!" + exit 1 +fi + +echo "SUCCESS: All libraries with versioned symbols have all symbols properly versioned." +exit 0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76ec28530..f04f54aed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,3 +61,6 @@ jobs: - name: Run tests run: make check + + - name: Check for unversioned symbols + run: ./.github/scripts/check-versioned-symbols.sh