include/debug.h \
include/default_shell.h \
include/dl-cryptsetup.h \
+ include/dl-selinux.h \
include/dl-utils.h \
include/encode.h \
include/env.h \
--- /dev/null
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ */
+#ifndef UTIL_LINUX_DL_SELINUX_H
+#define UTIL_LINUX_DL_SELINUX_H
+
+#ifdef HAVE_LIBSELINUX
+
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+#include <selinux/label.h>
+#include <selinux/get_context_list.h>
+
+#include "dl-utils.h"
+
+/* Pointers to libselinux functions (initialized by dlsym()) */
+struct ul_selinux_opers {
+ int (*is_selinux_enabled)(void);
+
+ int (*getfilecon)(const char *, char **);
+ int (*getfilecon_raw)(const char *, char **);
+ int (*fgetfilecon)(int, char **);
+ int (*lgetfilecon)(const char *, char **);
+
+ int (*getcon)(char **);
+ int (*getprevcon)(char **);
+ int (*getpidcon)(pid_t, char **);
+
+ int (*getseuserbyname)(const char *, char **, char **);
+
+ int (*setfilecon)(const char *, const char *);
+ int (*fsetfilecon)(int, const char *);
+ int (*setfscreatecon)(const char *);
+ int (*setexeccon)(const char *);
+
+ void (*freecon)(char *);
+
+ int (*selinux_check_access)(const char *, const char *,
+ const char *, const char *, void *);
+ int (*security_compute_relabel)(const char *, const char *,
+ security_class_t, char **);
+#ifdef HAVE_SECURITY_GET_INITIAL_CONTEXT
+ int (*security_get_initial_context)(const char *, char **);
+#endif
+ int (*selinux_file_context_cmp)(const char *, const char *);
+ int (*selinux_trans_to_raw_context)(const char *, char **);
+ security_class_t (*string_to_security_class)(const char *);
+
+ int (*get_default_context_with_level)(const char *, const char *,
+ context_t, char **);
+
+ struct selabel_handle *(*selabel_open)(unsigned int,
+ const struct selinux_opt *, unsigned);
+ int (*selabel_lookup)(struct selabel_handle *, char **,
+ const char *, int);
+ void (*selabel_close)(struct selabel_handle *);
+
+ context_t (*context_new)(const char *);
+ int (*context_type_set)(context_t, const char *);
+ const char *(*context_str)(context_t);
+ void (*context_free)(context_t);
+};
+
+typedef struct ul_selinux_opers ul_selinux_opers;
+
+extern struct ul_selinux_opers ul_selinux;
+
+extern int ul_dlopen_libselinux(void);
+
+#define selinux_call(_func) (ul_selinux._func)
+
+#endif /* HAVE_LIBSELINUX */
+#endif /* UTIL_LINUX_DL_SELINUX_H */
--- /dev/null
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ */
+#include <dlfcn.h>
+
+#include "c.h"
+#include "dl-selinux.h"
+
+#ifdef HAVE_LIBSELINUX
+
+UL_ELF_NOTE_DLOPEN("selinux",
+ "Support for SELinux",
+ UL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
+ "libselinux.so.1");
+
+struct ul_selinux_opers ul_selinux;
+
+static const struct ul_dlsym ul_selinux_symbols[] =
+{
+ UL_DLSYM( ul_selinux_opers, is_selinux_enabled ),
+
+ UL_DLSYM( ul_selinux_opers, getfilecon ),
+ UL_DLSYM( ul_selinux_opers, getfilecon_raw ),
+ UL_DLSYM( ul_selinux_opers, fgetfilecon ),
+ UL_DLSYM( ul_selinux_opers, lgetfilecon ),
+
+ UL_DLSYM( ul_selinux_opers, getcon ),
+ UL_DLSYM( ul_selinux_opers, getprevcon ),
+ UL_DLSYM( ul_selinux_opers, getpidcon ),
+
+ UL_DLSYM( ul_selinux_opers, getseuserbyname ),
+
+ UL_DLSYM( ul_selinux_opers, setfilecon ),
+ UL_DLSYM( ul_selinux_opers, fsetfilecon ),
+ UL_DLSYM( ul_selinux_opers, setfscreatecon ),
+ UL_DLSYM( ul_selinux_opers, setexeccon ),
+
+ UL_DLSYM( ul_selinux_opers, freecon ),
+
+ UL_DLSYM( ul_selinux_opers, selinux_check_access ),
+ UL_DLSYM( ul_selinux_opers, security_compute_relabel ),
+#ifdef HAVE_SECURITY_GET_INITIAL_CONTEXT
+ UL_DLSYM( ul_selinux_opers, security_get_initial_context ),
+#endif
+ UL_DLSYM( ul_selinux_opers, selinux_file_context_cmp ),
+ UL_DLSYM( ul_selinux_opers, selinux_trans_to_raw_context ),
+ UL_DLSYM( ul_selinux_opers, string_to_security_class ),
+
+ UL_DLSYM( ul_selinux_opers, get_default_context_with_level ),
+
+ UL_DLSYM( ul_selinux_opers, selabel_open ),
+ UL_DLSYM( ul_selinux_opers, selabel_lookup ),
+ UL_DLSYM( ul_selinux_opers, selabel_close ),
+
+ UL_DLSYM( ul_selinux_opers, context_new ),
+ UL_DLSYM( ul_selinux_opers, context_type_set ),
+ UL_DLSYM( ul_selinux_opers, context_str ),
+ UL_DLSYM( ul_selinux_opers, context_free ),
+};
+
+int ul_dlopen_libselinux(void)
+{
+ /* 0 = not tried, 1 = loaded, -1 = failed */
+ static int status = 0;
+ static void *dl = NULL;
+ int flags = RTLD_LAZY | RTLD_LOCAL;
+
+ if (status)
+ return status > 0 ? 0 : -ENOSYS;
+
+#ifdef RTLD_NODELETE
+ flags |= RTLD_NODELETE;
+#endif
+ status = ul_dlopen_symbols("libselinux.so.1", flags,
+ ul_selinux_symbols,
+ ARRAY_SIZE(ul_selinux_symbols),
+ &ul_selinux, &dl) == 0 ? 1 : -1;
+
+ return status > 0 ? 0 : -ENOSYS;
+}
+
+#endif /* HAVE_LIBSELINUX */
dl_utils_c = files('dl-utils.c')
dl_cryptsetup_c = files('dl-cryptsetup.c')
+dl_selinux_c = files('dl-selinux.c')
selinux_utils_c = files('selinux-utils.c')
*
* Written by Karel Zak <kzak@redhat.com> [January 2021]
*/
-#include <selinux/context.h>
-#include <selinux/selinux.h>
-#include <selinux/label.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
+#include "dl-selinux.h"
#include "selinux-utils.h"
+#ifdef HAVE_LIBSELINUX
+
/* set the SELinux security context used for _creating_ a new file system object
*
* returns 0 on success,
*/
int ul_setfscreatecon_from_file(char *orig_file)
{
- if (is_selinux_enabled() > 0) {
+ if (ul_dlopen_libselinux() == 0
+ && selinux_call(is_selinux_enabled)() > 0) {
char *scontext = NULL;
- if (getfilecon(orig_file, &scontext) < 0)
+ if (selinux_call(getfilecon)(orig_file, &scontext) < 0)
return -1;
- if (setfscreatecon(scontext) < 0) {
- freecon(scontext);
+ if (selinux_call(setfscreatecon)(scontext) < 0) {
+ selinux_call(freecon)(scontext);
return -1;
}
- freecon(scontext);
+ selinux_call(freecon)(scontext);
}
return 0;
}
if (user_cxt)
*user_cxt = NULL;
- if (getprevcon(&user) != 0)
+ if (ul_dlopen_libselinux() != 0)
+ return 0;
+
+ if (selinux_call(getprevcon)(&user) != 0)
return 0;
- rc = selinux_check_access(user, user, classstr, perm, NULL);
+ rc = selinux_call(selinux_check_access)(user, user, classstr, perm, NULL);
if (rc != 0 && user_cxt)
*user_cxt = user;
else
- freecon(user);
+ selinux_call(freecon)(user);
return rc == 0 ? 1 : 0;
}
*cxt = NULL;
- hnd = selabel_open(SELABEL_CTX_FILE, options, SELABEL_NOPT);
+ if (ul_dlopen_libselinux() != 0)
+ return -ENOSYS;
+
+ hnd = selinux_call(selabel_open)(SELABEL_CTX_FILE, options, SELABEL_NOPT);
if (!hnd)
return -errno;
- if (selabel_lookup(hnd, cxt, path, st_mode) != 0)
- rc = -errno
- ;
- selabel_close(hnd);
+ if (selinux_call(selabel_lookup)(hnd, cxt, path, st_mode) != 0)
+ rc = -errno;
+ selinux_call(selabel_close)(hnd);
return rc;
}
+
+#endif /* HAVE_LIBSELINUX */
lib_mount_sources += 'src/btrfs.c'
endif
+if lib_selinux.found()
+ lib_mount_sources += [dl_utils_c, dl_selinux_c, selinux_utils_c]
+endif
+
if lib_cryptsetup.found()
- lib_mount_sources += [dl_utils_c, dl_cryptsetup_c]
+ if not lib_selinux.found()
+ lib_mount_sources += dl_utils_c
+ endif
+ lib_mount_sources += dl_cryptsetup_c
endif
libmount_sym = 'src/libmount.sym'
endif
lib__mount_compile_deps = [blkid_dep]
+if lib_selinux.found()
+ lib__mount_compile_deps += lib_selinux.partial_dependency(compile_args : true, includes : true)
+endif
if lib_cryptsetup.found()
lib__mount_compile_deps += lib_cryptsetup.partial_dependency(compile_args : true, includes : true)
endif
mount_static_dep = declare_dependency(link_with: lib_mount_static, include_directories: '.')
lib__mount_deps = [
- lib_selinux,
lib_dl,
realtime_libs
]
libmount_la_LIBADD = \
libcommon.la \
libblkid.la \
- $(SELINUX_LIBS) \
$(REALTIME_LIBS)
-if HAVE_CRYPTSETUP
+if HAVE_SELINUX
libmount_la_SOURCES += \
lib/dl-utils.c \
include/dl-utils.h \
+ lib/dl-selinux.c \
+ include/dl-selinux.h \
+ lib/selinux-utils.c \
+ include/selinux-utils.h
+libmount_la_LIBADD += -ldl
+endif
+
+if HAVE_CRYPTSETUP
+libmount_la_SOURCES += \
lib/dl-cryptsetup.c \
include/dl-cryptsetup.h
+if !HAVE_SELINUX
+libmount_la_SOURCES += \
+ lib/dl-utils.c \
+ include/dl-utils.h
+endif
libmount_la_LIBADD += -ldl
endif
-I$(ul_libmount_incdir) \
-I$(top_srcdir)/libmount/src \
$(SOLIB_CFLAGS) \
- $(CRYPTSETUP_CFLAGS)
+ $(CRYPTSETUP_CFLAGS) \
+ $(SELINUX_CFLAGS)
EXTRA_libmount_la_DEPENDENCIES = \
libmount/src/libmount.sym
libmount_tests_ldadd = libmount.la libblkid.la $(LDADD) $(REALTIME_LIBS)
if HAVE_SELINUX
-libmount_tests_ldadd += $(SELINUX_LIBS)
+libmount_tests_ldadd += -ldl
endif
if HAVE_CRYPTSETUP
+if !HAVE_SELINUX
libmount_tests_ldadd += -ldl
endif
+endif
test_mount_cache_SOURCES = libmount/src/cache.c
test_mount_cache_CFLAGS = $(libmount_tests_cflags)
* Please, see the comment in libmount/src/hooks.c to understand how hooks work.
*/
#ifdef HAVE_LIBSELINUX
-#include <selinux/selinux.h>
-#include <selinux/context.h>
#include "mountP.h"
+#include "dl-selinux.h"
#include "fileutils.h"
#include "linux_version.h"
return 0;
- rc = getfilecon_raw(tgt, &raw);
+ rc = selinux_call(getfilecon_raw)(tgt, &raw);
if (rc <= 0 || !raw) {
rc = errno ? -errno : -EINVAL;
DBG_OBJ(HOOK, hs, ul_debug(" SELinux fix @target failed [rc=%d]", rc));
if (!rc)
rc = mnt_opt_set_quoted_value(opt, raw);
if (raw)
- freecon(raw);
+ selinux_call(freecon)(raw);
return rc != 0 ? -MNT_ERR_MOUNTOPT : 0;
}
if (!ol)
return -EINVAL;
- if (!is_selinux_enabled())
- /* Always remove SELinux garbage if SELinux disabled */
+ if (ul_dlopen_libselinux() != 0) {
+ DBG_OBJ(HOOK, hs, ul_debug("libselinux not available via dlopen"));
se_rem = 1;
- else if (mnt_optlist_is_remount(ol))
+ } else if (!selinux_call(is_selinux_enabled)()) {
+ DBG_OBJ(HOOK, hs, ul_debug("SELinux disabled"));
+ se_rem = 1;
+ } else if (mnt_optlist_is_remount(ol))
/*
* Linux kernel < 2.6.39 does not support remount operation
* with any selinux specific mount options.
hook_selinux_target);
continue;
} else {
- rc = selinux_trans_to_raw_context(val, &raw);
+ rc = selinux_call(selinux_trans_to_raw_context)(val, &raw);
if (rc == -1 || !raw)
rc = -EINVAL;
}
rc = mnt_opt_set_quoted_value(opt, raw);
}
if (raw)
- freecon(raw);
+ selinux_call(freecon)(raw);
/* temporary for broken fsconfig() syscall */
cxt->has_selinux_opt = 1;