summaryrefslogtreecommitdiffstats
path: root/src/apparmor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/apparmor.c')
-rw-r--r--src/apparmor.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/apparmor.c b/src/apparmor.c
new file mode 100644
index 0000000..8ec7a85
--- /dev/null
+++ b/src/apparmor.c
@@ -0,0 +1,118 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Will Shand <wss2ec@virginia.edu>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_APPARMOR
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <sys/apparmor.h>
+
+# include <sudo.h>
+# include <sudo_debug.h>
+
+/**
+ * @brief Check whether AppArmor is enabled.
+ *
+ * @return 1 if AppArmor is enabled, 0 otherwise.
+ */
+int
+apparmor_is_enabled(void)
+{
+ int ret;
+ FILE *fd;
+ debug_decl(apparmor_is_enabled, SUDO_DEBUG_APPARMOR);
+
+ /*
+ * Check whether AppArmor is enabled by reading
+ * /sys/module/apparmor/parameters/enabled
+ *
+ * When this file exists and its contents are equal to "Y", AppArmor
+ * is enabled. This is a little more reliable than using
+ * aa_is_enabled(2), which performs an additional check on securityfs
+ * that will fail in settings where securityfs isn't available
+ * (e.g. inside a container).
+ */
+
+ fd = fopen("/sys/module/apparmor/parameters/enabled", "r");
+ if (fd == NULL)
+ debug_return_int(0);
+
+ ret = (fgetc(fd) == 'Y');
+
+ fclose(fd);
+ debug_return_int(ret);
+}
+
+/**
+ * @brief Prepare to transition into a new AppArmor profile.
+ *
+ * @param new_profile The AppArmor profile to transition into on the
+ * next exec.
+ *
+ * @return 0 on success, and a nonzero value on failure.
+ */
+int
+apparmor_prepare(const char *new_profile)
+{
+ int ret;
+ char *mode, *old_profile;
+ debug_decl(apparmor_prepare, SUDO_DEBUG_APPARMOR);
+
+ /* Determine the current AppArmor confinement status */
+ if ((ret = aa_getcon(&old_profile, &mode)) == -1) {
+ sudo_warn("%s", U_("failed to determine AppArmor confinement"));
+ old_profile = NULL;
+ goto done;
+ }
+
+ /* Tell AppArmor to transition into the new profile on the
+ * next exec */
+ if ((ret = aa_change_onexec(new_profile)) != 0) {
+ sudo_warn(U_("unable to change AppArmor profile to %s"), new_profile);
+ goto done;
+ }
+
+ if (mode == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: changing AppArmor profile: %s -> %s", __func__,
+ old_profile, new_profile ? new_profile : "?");
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: changing AppArmor profile: %s (%s) -> %s", __func__,
+ old_profile, mode, new_profile ? new_profile : "?");
+ }
+
+done:
+ /*
+ * The profile string returned by aa_getcon must be free'd, while the
+ * mode string must _not_ be free'd.
+ */
+ if (old_profile != NULL)
+ free(old_profile);
+
+ debug_return_int(ret);
+}
+
+#endif /* HAVE_APPARMOR */