From 3e0151348587edf7ba64a11ad2bc0b2c49dfb20d Mon Sep 17 00:00:00 2001 From: Georgia Garcia Date: Thu, 9 Sep 2021 18:30:40 +0000 Subject: [PATCH] pstree: add apparmor support While the current fallback method might obtain the correct AppArmor context by checking /proc/self/attr/current, it is not guaranteed that this value will be the context attributed by AppArmor. The current interface being used upstream is /proc/self/attr/apparmor/current, and that can be obtained by using the AppArmor library functions. In order to avoid link time dependencies, we are loading the apparmor library dynamically, just like is currently done by SELinux. Signed-off-by: Georgia Garcia --- configure.ac | 17 +++++++++++++++++ src/pstree.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 182a0df..ecc0c02 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,23 @@ if test "$enable_selinux" = "yes"; then fi AC_SUBST([DL_LIB]) +# AppArmor support - off by default +DL_LIB= +AC_SUBST([WITH_AppArmor]) +AC_ARG_ENABLE([apparmor], + [AS_HELP_STRING([--enable-apparmor], [Enable AppArmor features])], + [enable_apparmor=$enableval], + [enable_apparmor="no"]) +if test "$enable_apparmor" = "yes"; then + AC_DEFINE([WITH_APPARMOR], [1], [Use AppArmor features]) + AC_SEARCH_LIBS([dlopen], [dl], [], + [AC_MSG_ERROR([dynamic linking unavailable, circumvent with --disable-apparmor])]) + if test "x$ac_cv_search_dlopen" != "xnone required"; then + DL_LIB="$ac_cv_search_dlopen" + fi +fi +AC_SUBST([DL_LIB]) + # Call fork before all stat calls to stop hanging on NFS mounts AC_SUBST([WITH_TIMEOUT_STAT]) AC_ARG_ENABLE([timeout_stat], diff --git a/src/pstree.c b/src/pstree.c index 63387ce..02e83bb 100644 --- a/src/pstree.c +++ b/src/pstree.c @@ -50,9 +50,16 @@ #ifdef WITH_SELINUX #include #include -#else +#endif /*WITH_SELINUX */ + +#ifdef WITH_APPARMOR +#include +#include +#endif /* WITH_APPARMOR */ + +#if !defined(WITH_SELINUX) && !defined(WITH_APPARMOR) typedef void* security_context_t; /* DUMMY to remove most ifdefs */ -#endif /*WITH_SELINUX */ +#endif /* !WITH_SELINUX && !WITH_APPARMOR */ extern const char *__progname; @@ -503,6 +510,39 @@ static bool out_selinux_context(const PROC *current) } #endif /* WITH_SELINUX */ +#ifdef WITH_APPARMOR +static bool out_apparmor_context(const PROC *current) +{ + static int (*my_aa_gettaskcon)(pid_t pid, char **context, char **mode) = 0; + static int (*my_aa_is_enabled)(void) = 0; + static int apparmor_enabled = 0; + static int tried_load = 0; + bool ret = false; + char *context; + + if (!my_aa_gettaskcon && !tried_load) { + void *handle = dlopen("libapparmor.so.1", RTLD_NOW); + if (handle) { + my_aa_gettaskcon = dlsym(handle, "aa_gettaskcon"); + if (dlerror()) + my_aa_gettaskcon = 0; + my_aa_is_enabled = dlsym(handle, "aa_is_enabled"); + if (dlerror()) + my_aa_is_enabled = 0; + else + apparmor_enabled = my_aa_is_enabled(); + } + tried_load++; + } + if (my_aa_gettaskcon && apparmor_enabled && my_aa_gettaskcon(current->pid, &context, NULL) >= 0) { + out_string(context); + free(context); + ret = true; + } + return ret; +} +#endif /* WITH_APPARMOR */ + /* * Print the security context of the current process. This is largely lifted * from pr_context from procps ps/output.c @@ -516,6 +556,10 @@ static void out_scontext(const PROC *current) success = out_selinux_context(current); #endif /* WITH_SELINUX */ +#ifdef WITH_APPARMOR + success |= out_apparmor_context(current); +#endif /* WITH_APPARMOR */ + if (!success) { FILE *file; char path[50]; -- 2.40.0