Building a coreutils snapshot in Termux on Android, I see several
link errors, not only of coreutils programs, but also among the
gnulib-tests unit tests:

-------------------------------------------------------------------------------

clang -ferror-limit=0 -std=gnu23   -Wno-error -Wno-cast-qual -Wno-conversion 
-Wno-float-equal -Wno-sign-compare -Wno-undef -Wno-unused-function 
-Wno-unused-parameter -Wno-float-conversion -Wimplicit-fallthrough 
-Wno-pedantic -Wno-tautological-constant-out-of-range-compare 
-Wno-sign-conversion -Wno-type-limits -Wno-unused-const-variable -Wno-error 
-Wno-cast-qual -Wno-conversion -Wno-float-equal -Wno-sign-compare -Wno-undef 
-Wno-unused-function -Wno-unused-parameter -Wno-float-conversion 
-Wimplicit-fallthrough -Wno-pedantic 
-Wno-tautological-constant-out-of-range-compare -Wno-sign-conversion 
-Wno-type-limits -Wno-unused-const-variable -O2  
-L/data/data/com.termux/files/home/local/lib -o test-copy-acl test-copy-acl.o 
libtests.a ../lib/libcoreutils.a libtests.a ../lib/libcoreutils.a libtests.a  
-lacl -lattr  -lselinux  /data/data/com.termux/files/home/local/lib/libintl.so 
/data/data/com.termux/files/home/local/lib/libiconv.so -Wl,-rpath 
-Wl,/data/data/com.termux/files/home/local/lib   
ld.lld: error: undefined symbol: getfilecon_raw
>>> referenced by getfilecon.c
>>>               libcoreutils_a-getfilecon.o:(rpl_getfilecon_raw) in archive 
>>> ../lib/libcoreutils.a
>>> did you mean: fgetfilecon_raw
>>> defined in: /system/lib/libselinux.so

ld.lld: error: undefined symbol: lgetfilecon_raw
>>> referenced by getfilecon.c
>>>               libcoreutils_a-getfilecon.o:(rpl_lgetfilecon_raw) in archive 
>>> ../lib/libcoreutils.a
>>> did you mean: fgetfilecon_raw
>>> defined in: /system/lib/libselinux.so
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [Makefile:8037: test-copy-acl] Error 1

clang -ferror-limit=0 -std=gnu23   -Wno-error -Wno-cast-qual -Wno-conversion 
-Wno-float-equal -Wno-sign-compare -Wno-undef -Wno-unused-function 
-Wno-unused-parameter -Wno-float-conversion -Wimplicit-fallthrough 
-Wno-pedantic -Wno-tautological-constant-out-of-range-compare 
-Wno-sign-conversion -Wno-type-limits -Wno-unused-const-variable -Wno-error 
-Wno-cast-qual -Wno-conversion -Wno-float-equal -Wno-sign-compare -Wno-undef 
-Wno-unused-function -Wno-unused-parameter -Wno-float-conversion 
-Wimplicit-fallthrough -Wno-pedantic 
-Wno-tautological-constant-out-of-range-compare -Wno-sign-conversion 
-Wno-type-limits -Wno-unused-const-variable -O2  
-L/data/data/com.termux/files/home/local/lib -o test-file-has-acl 
test-file-has-acl.o libtests.a ../lib/libcoreutils.a libtests.a 
../lib/libcoreutils.a libtests.a  -lselinux 
ld.lld: error: undefined symbol: getfilecon_raw
>>> referenced by getfilecon.c
>>>               libcoreutils_a-getfilecon.o:(rpl_getfilecon_raw) in archive 
>>> ../lib/libcoreutils.a
>>> did you mean: fgetfilecon_raw
>>> defined in: /system/lib/libselinux.so

ld.lld: error: undefined symbol: lgetfilecon_raw
>>> referenced by getfilecon.c
>>>               libcoreutils_a-getfilecon.o:(rpl_lgetfilecon_raw) in archive 
>>> ../lib/libcoreutils.a
>>> did you mean: fgetfilecon_raw
>>> defined in: /system/lib/libselinux.so
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [Makefile:8259: test-file-has-acl] Error 1

clang -ferror-limit=0 -std=gnu23   -Wno-error -Wno-cast-qual -Wno-conversion 
-Wno-float-equal -Wno-sign-compare -Wno-undef -Wno-unused-function 
-Wno-unused-parameter -Wno-float-conversion -Wimplicit-fallthrough 
-Wno-pedantic -Wno-tautological-constant-out-of-range-compare 
-Wno-sign-conversion -Wno-type-limits -Wno-unused-const-variable -Wno-error 
-Wno-cast-qual -Wno-conversion -Wno-float-equal -Wno-sign-compare -Wno-undef 
-Wno-unused-function -Wno-unused-parameter -Wno-float-conversion 
-Wimplicit-fallthrough -Wno-pedantic 
-Wno-tautological-constant-out-of-range-compare -Wno-sign-conversion 
-Wno-type-limits -Wno-unused-const-variable -O2  
-L/data/data/com.termux/files/home/local/lib -o test-selinux-context-h 
test-selinux-context-h.o libtests.a ../lib/libcoreutils.a libtests.a 
../lib/libcoreutils.a libtests.a  -lselinux 
ld.lld: error: undefined symbol: context_new
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_type_set
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_range_set
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_role_set
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_user_set
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_type_get
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_range_get
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_role_get
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_user_get
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_str
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)

ld.lld: error: undefined symbol: context_free
>>> referenced by test-selinux-context-h.c
>>>               test-selinux-context-h.o:(main)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [Makefile:9199: test-selinux-context-h] Error 1

-------------------------------------------------------------------------------

The reason is that on Android, there are two different SELinux libraries:
  - libselinux.so from the system,
  - libandroid-selinux.so from a Termux package.
And the system one does not define the API functions that gnulib and coreutils
expect:

$ nm -D /system/lib/libselinux.so | grep ' T '
0000b43c T fgetfilecon@@LIBSELINUX_R
0000b380 T fgetfilecon_raw@@LIBSELINUX_R
00004c2c T freecon@@LIBSELINUX_R
0000b528 T fsetfilecon@@LIBSELINUX_R
0000c844 T getcon@@LIBSELINUX_R
0000b734 T getfilecon@@LIBSELINUX_R
0000b9a8 T getpeercon@@LIBSELINUX_R
0000cac8 T getpidcon@@LIBSELINUX_R
0000b36c T is_selinux_enabled@@LIBSELINUX_R
0000be24 T lgetfilecon@@LIBSELINUX_R
0000bfe0 T lsetfilecon@@LIBSELINUX_R
0000af88 T security_compute_create@@LIBSELINUX_R
0000b8b4 T security_get_initial_context@@LIBSELINUX_R
0000b574 T security_getenforce@@LIBSELINUX_R
0000be84 T security_load_policy@@LIBSELINUX_R
0000c534 T security_policyvers@@LIBSELINUX_R
0000cfa8 T security_setenforce@@LIBSELINUX_R
0000535c T selabel_close@@LIBSELINUX_R
000053ca T selabel_lookup@@LIBSELINUX_R
0000544a T selabel_lookup_best_match@@LIBSELINUX_R
0000524c T selabel_open@@LIBSELINUX_R
0000d55c T selinux_android_file_context_handle@@LIBSELINUX_R
00008eec T selinux_android_hw_service_context_handle@@LIBSELINUX_R
0000f26c T selinux_android_load_policy@@LIBSELINUX_R
0000f2d0 T selinux_android_load_policy_from_fd@@LIBSELINUX_R
0000eb44 T selinux_android_restorecon@@LIBSELINUX_R
0000f258 T selinux_android_restorecon_pkgdir@@LIBSELINUX_R
0000e488 T selinux_android_seapp_context_init@@LIBSELINUX_R
00008cf0 T selinux_android_service_context_handle@@LIBSELINUX_R
0000f260 T selinux_android_set_sehandle@@LIBSELINUX_R
0000e4c8 T selinux_android_setcon@@LIBSELINUX_R
0000e4dc T selinux_android_setcontext@@LIBSELINUX_R
00009130 T selinux_android_vendor_service_context_handle@@LIBSELINUX_R
0000a8e0 T selinux_check_access@@LIBSELINUX_R
000091b8 T selinux_log_callback@@LIBSELINUX_R
00004be8 T selinux_set_callback@@LIBSELINUX_R
0000cdf0 T selinux_status_open@@LIBSELINUX_R
0000cd80 T selinux_status_updated@@LIBSELINUX_R
00009234 T selinux_vendor_log_callback@@LIBSELINUX_R
0000ba8c T set_selinuxmnt@@LIBSELINUX_R
0000ca7c T setcon@@LIBSELINUX_R
0000cb2c T setexeccon@@LIBSELINUX_R
0000d104 T setfilecon@@LIBSELINUX_R
0000cb78 T setfscreatecon@@LIBSELINUX_R
0000cbd0 T setsockcreatecon@@LIBSELINUX_R
0000cbc4 T setsockcreatecon_raw@@LIBSELINUX_R
0000d190 T string_to_security_class@@LIBSELINUX_R
(47 symbols)

$ nm -D /data/data/com.termux/files/usr/lib/libandroid-selinux.so | grep ' T '
00024908 T Sha1Finalise
00020628 T Sha1Initialise
000206a0 T Sha1Update
0000cc48 T avc_add_callback
0000b860 T avc_audit
0000b0a8 T avc_av_stats
0000ae9c T avc_cache_stats
0000b300 T avc_cleanup
0000c9a0 T avc_compute_create
0000cb48 T avc_compute_member
0000a38c T avc_context_to_sid
0000a248 T avc_context_to_sid_raw
0000b5a8 T avc_destroy
0000a4f8 T avc_get_initial_sid
0000c8f0 T avc_has_perm
0000c1a0 T avc_has_perm_noaudit
0000ae58 T avc_init
0000f300 T avc_netlink_acquire_fd
0000e388 T avc_netlink_check_nb
0000e33c T avc_netlink_close
0000f01c T avc_netlink_loop
0000e1d8 T avc_netlink_open
0000f4b0 T avc_netlink_release_fd
0000a560 T avc_open
0000df20 T avc_process_policyload
0000dc24 T avc_process_setenforce
0000b304 T avc_reset
0000aecc T avc_sid_stats
0000a47c T avc_sid_to_context
0000a3ec T avc_sid_to_context_raw
0000cd88 T avc_ss_grant
0000d124 T avc_ss_reset
0000d0cc T avc_ss_revoke
0000d1a0 T avc_ss_set_auditallow
0000d248 T avc_ss_set_auditdeny
0000d070 T avc_ss_try_revoke
0001059c T checkPasswdAccess
0001ba24 T compat_validate
000119f8 T context_free
00007384 T context_handle
00011640 T context_new
00011c88 T context_range_get
00011ea0 T context_range_set
00011cac T context_role_get
00011e40 T context_role_set
00011ad0 T context_str
00011c40 T context_type_get
00011cd0 T context_type_set
00011c64 T context_user_get
00011e70 T context_user_set
0001a524 T digest_add_specfile
0001a460 T digest_gen_hash
00012558 T fgetfilecon
00012284 T fgetfilecon_raw
00006f68 T find_existing_files
0001310c T fini_selinuxmnt
00012600 T freecon
00012858 T fsetfilecon
00012620 T fsetfilecon_raw
0001d850 T getcon
0001d598 T getcon_raw
0001dd90 T getexeccon
0001dd40 T getexeccon_raw
00012dec T getfilecon
00012c54 T getfilecon_raw
0001dec0 T getfscreatecon
0001de70 T getfscreatecon_raw
0001e120 T getkeycreatecon
0001e0d0 T getkeycreatecon_raw
00012fc4 T getpeercon
00012e94 T getpeercon_raw
0001e268 T getpidcon
0001e200 T getpidcon_raw
0001e338 T getpidprevcon
0001e2d0 T getpidprevcon_raw
0001dd0c T getprevcon
0001dcd8 T getprevcon_raw
0001dff0 T getsockcreatecon
0001dfa0 T getsockcreatecon_raw
000070a8 T initialize_backend
00012108 T is_selinux_enabled
00012138 T is_selinux_mls_enabled
0001a954 T lgetfilecon
0001a7bc T lgetfilecon_raw
0001abd0 T lsetfilecon
0001aae8 T lsetfilecon_raw
0001b3b4 T map_class
0001b5d8 T map_decision
0001b484 T map_perm
0001cba8 T matchpathcon
0001cfdc T matchpathcon_checkmatches
0001bf60 T matchpathcon_filespec_add
0001c444 T matchpathcon_filespec_destroy
0001c2fc T matchpathcon_filespec_eval
0001c918 T matchpathcon_fini
0001cd20 T matchpathcon_index
0001c8f4 T matchpathcon_init
0001c680 T matchpathcon_init_prefix
0001c624 T matchpathcon_lib_destructor
000250b8 T mode_to_security_class
00007040 T paths_to_opts
000256d0 T print_access_vector
0001d53c T procattr_destructor
0001a0ac T read_spec_entries
0001c98c T realpath_not_final
0001e738 T regex_arch_string
0001f27c T regex_cmp
0001e8f8 T regex_data_create
0001ea30 T regex_data_free
0001f388 T regex_format_error
0001eaf0 T regex_load_mmap
0001ef98 T regex_match
0001e818 T regex_prepare_data
0001ea80 T regex_version
0001ece4 T regex_writef
0000a0d8 T seapp_context_lookup
0000965c T seapp_context_lookup_internal
000076e4 T seapp_context_reload_internal
000253e8 T security_av_perm_to_string
000254bc T security_av_string
0000ff94 T security_canonicalize_context
0000fd88 T security_canonicalize_context_raw
000106c0 T security_check_context
000105bc T security_check_context_raw
0002538c T security_class_to_string
0000fafc T security_commit_booleans
00010b40 T security_compute_av
00010a90 T security_compute_av_flags
00010718 T security_compute_av_flags_raw
000109f8 T security_compute_av_raw
000111c8 T security_compute_create
000110f4 T security_compute_create_name
00010bd8 T security_compute_create_name_raw
000110b0 T security_compute_create_raw
00011564 T security_compute_member
00011314 T security_compute_member_raw
00011ed0 T security_deny_unknown
00011ffc T security_disable
0000fad0 T security_get_boolean_active
0000faa4 T security_get_boolean_names
0000fabc T security_get_boolean_pending
00012ab4 T security_get_initial_context
000128b8 T security_get_initial_context_raw
00012b08 T security_getenforce
0000fa90 T security_load_booleans
0001a9fc T security_load_policy
0001d3f4 T security_policyvers
0001f620 T security_reject_unknown
0000fae4 T security_set_boolean
0000fa74 T security_set_boolean_list
000202c4 T security_setenforce
000137ec T selabel_close
00013e54 T selabel_cmp
00013ec4 T selabel_digest
000146dc T selabel_exact_match_init
00015348 T selabel_file_init
00013b00 T selabel_get_digests_all_partial_matches
00013b80 T selabel_hash_all_partial_matches
000138b4 T selabel_lookup
00013bec T selabel_lookup_best_match
00013d80 T selabel_lookup_best_match_raw
00013a04 T selabel_lookup_raw
000134b0 T selabel_open
00013a9c T selabel_partial_match
0001410c T selabel_property_init
00014018 T selabel_stats
0001342c T selabel_validate
00007654 T selinux_android_file_context_handle
0000740c T selinux_android_hw_service_context_handle
00007464 T selinux_android_keystore2_key_context_handle
00009400 T selinux_android_seapp_context_init
000093e4 T selinux_android_seapp_context_reload
000073e0 T selinux_android_service_context_handle
00007438 T selinux_android_vendor_service_context_handle
0000fb04 T selinux_boolean_sub
00010018 T selinux_check_access
00010464 T selinux_check_passwd_access
0001d00c T selinux_file_context_cmp
0001d124 T selinux_file_context_verify
00024a38 T selinux_flush_class_cache
0000fc9c T selinux_get_callback
00007490 T selinux_log_callback
0001d2e4 T selinux_lsetfilecon_default
000205a8 T selinux_raw_to_trans_context
0000fbe0 T selinux_set_callback
0001ac30 T selinux_set_mapping
00020184 T selinux_status_close
0001fc68 T selinux_status_deny_unknown
0001fa48 T selinux_status_getenforce
0001fd60 T selinux_status_open
0001fb64 T selinux_status_policyload
0001f7dc T selinux_status_updated
00020528 T selinux_trans_to_raw_context
00007604 T selinux_vendor_log_callback
00013018 T selinuxfs_exists
0001bd6c T set_matchpathcon_canoncon
0001beb0 T set_matchpathcon_flags
0001bd48 T set_matchpathcon_invalidcon
0001b9bc T set_matchpathcon_printf
00009490 T set_range_from_level
00013140 T set_selinuxmnt
0001dc28 T setcon
0001d904 T setcon_raw
0001de28 T setexeccon
0001dde0 T setexeccon_raw
000204c8 T setfilecon
000203e0 T setfilecon_raw
0001df58 T setfscreatecon
0001df10 T setfscreatecon_raw
0001e1b8 T setkeycreatecon
0001e170 T setkeycreatecon_raw
0001e088 T setsockcreatecon
0001e040 T setsockcreatecon_raw
0000a4d0 T sidget
0000a4e4 T sidput
0000f78c T sidtab_context_to_sid
0000f9a0 T sidtab_destroy
0000f4c8 T sidtab_init
0000f5c8 T sidtab_insert
0000f87c T sidtab_sid_stats
00025204 T string_to_av_perm
00024b00 T string_to_security_class
0001f74c T strlcpy
0001b1cc T unmap_class
0001b26c T unmap_perm
(225 symbols)

The effect is that the configure test
  checking for library containing setfilecon... -lselinux
picks the system library, which then later causes the link errors.

This patch fixes the problem, by picking -landroid-selinux in this case.


2026-01-24  Bruno Haible  <[email protected]>

        selinux-h: Fix compilation errors in Termux on Android.
        * m4/selinux-selinux-h.m4 (gl_LIBSELINUX): Prefer libandroid-selinux to
        libselinux.

diff --git a/m4/selinux-selinux-h.m4 b/m4/selinux-selinux-h.m4
index b3fcd2102e..0db23ebe87 100644
--- a/m4/selinux-selinux-h.m4
+++ b/m4/selinux-selinux-h.m4
@@ -1,5 +1,5 @@
 # selinux-selinux-h.m4
-# serial 10   -*- Autoconf -*-
+# serial 11   -*- Autoconf -*-
 dnl Copyright (C) 2006-2007, 2009-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,
@@ -79,7 +79,9 @@ AC_DEFUN([gl_LIBSELINUX]
   LIB_SELINUX=
   if test "$with_selinux" != no; then
     gl_saved_LIBS=$LIBS
-    AC_SEARCH_LIBS([setfilecon], [selinux],
+    dnl On Android, in Termux, prefer libandroid-selinux.so, because it
+    dnl defines many more API functions than /system/lib/libselinux.so.
+    AC_SEARCH_LIBS([setfilecon], [android-selinux selinux],
                    [test "$ac_cv_search_setfilecon" = "none required" ||
                     LIB_SELINUX=$ac_cv_search_setfilecon])
     LIBS=$gl_saved_LIBS




Reply via email to