From d0c4fc7d68c2a91c722f2fd6075f595766acad99 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Wed, 17 Mar 2021 05:18:05 -0700 Subject: [PATCH] [4/7] libapparmor: fix available and enabled checks Make it easier to separate errors from an actual answer, and ensure we do a fallback check if there was an error. Also fix the error code returned from aa_is_enabled() which got broken by the addition of the private_enabled() check. Finally make sure the private enabled error code is documented. Fixes: https://gitlab.com/apparmor/apparmor/-/issues/150 MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/713 Signed-off-by: John Johansen --- .../libapparmor/doc/aa_find_mountpoint.pod | 4 ++ libraries/libapparmor/src/kernel.c | 40 +++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/libraries/libapparmor/doc/aa_find_mountpoint.pod b/libraries/libapparmor/doc/aa_find_mountpoint.pod index 33c72e67d..0a86e971e 100644 --- a/libraries/libapparmor/doc/aa_find_mountpoint.pod +++ b/libraries/libapparmor/doc/aa_find_mountpoint.pod @@ -70,6 +70,10 @@ AppArmor extensions to the system are not available. AppArmor is available on the system but has been disabled at boot. +=item B + +AppArmor is available but only via private interfaces. + =item B AppArmor is available (and maybe even enforcing policy) but the interface is diff --git a/libraries/libapparmor/src/kernel.c b/libraries/libapparmor/src/kernel.c index 4858f63f2..464fd5ffa 100644 --- a/libraries/libapparmor/src/kernel.c +++ b/libraries/libapparmor/src/kernel.c @@ -100,18 +100,18 @@ int aa_find_mountpoint(char **mnt) int rc, fd; \ fd = open("/sys/module/apparmor/parameters/" PARAM, O_RDONLY); \ if (fd == -1) { \ - rc = errno; \ + rc = -errno; \ } else { \ char buffer[2]; \ int size = read(fd, &buffer, 2); \ - rc = errno; \ + rc = -errno; \ close(fd); \ - errno = rc; \ + errno = -rc; \ if (size > 0) { \ if (buffer[0] == 'Y') \ - rc = 0; \ + rc = 1; \ else \ - rc = ECANCELED; \ + rc = 0; \ } \ } \ (rc); \ @@ -130,14 +130,17 @@ static void param_check_enabled_init_once(void) static int param_check_enabled() { - if (pthread_once(¶m_enabled_ctl, param_check_enabled_init_once) == 0) + if (pthread_once(¶m_enabled_ctl, param_check_enabled_init_once) == 0 && param_enabled >= 0) return param_enabled; + /* fallback if not initialized OR we recorded an error when + * initializing. + */ return param_check_base("enabled"); } static int is_enabled(void) { - return !param_check_enabled(); + return param_check_enabled() == 1; } static void param_check_private_enabled_init_once(void) @@ -147,14 +150,17 @@ static void param_check_private_enabled_init_once(void) static int param_check_private_enabled() { - if (pthread_once(¶m_private_enabled_ctl, param_check_private_enabled_init_once) == 0) + if (pthread_once(¶m_private_enabled_ctl, param_check_private_enabled_init_once) == 0 && param_private_enabled >= 0) return param_private_enabled; + /* fallback if not initialized OR we recorded an error when + * initializing. + */ return param_check_base("available"); } static int is_private_enabled(void) { - return !param_check_private_enabled(); + return param_check_private_enabled() == 1; } /** @@ -174,15 +180,17 @@ int aa_is_enabled(void) bool private = false; rc = param_check_enabled(); - if (rc) { - if (rc == ENOENT) - errno = ENOSYS; - else - errno = rc; + if (rc < 1) { + if (!is_private_enabled()) { + if (rc == 0) + errno = ECANCELED; + else if (rc == -ENOENT) + errno = ENOSYS; + else + errno = -rc; - if (!is_private_enabled()) return 0; - + } /* actually available but only on private interfaces */ private = true; }