diff mbox series

[v2] libsemanage: create semanage_basename to ensure posix compliance

Message ID 20250221093910.657484-1-nvraxn@gmail.com (mailing list archive)
State New
Headers show
Series [v2] libsemanage: create semanage_basename to ensure posix compliance | expand

Commit Message

Rahul Sandhu Feb. 21, 2025, 9:39 a.m. UTC
Passing a const char * to basename(3) is a glibc-specific extension, so
create our own basename implementation. As it's a trivial 2 LOC, always
use our implementation of basename even if glibc is available to avoid
the complications of attaining the non-posix glibc implementation of
basename(3) as _GNU_SOURCE needs to be defined, but libgen.h also needs
to have not been included.

Also fix a missing check for selinux_policy_root(3). From the man page:
On failure, selinux_policy_root returns NULL.

As the glibc basename(3) (unlike posix basename(3)) does not support
having a nullptr passed to it, only pass the policy_root to basename(3)
if it is non-null.

Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
---
 libsemanage/src/conf-parse.y       | 13 ++++++++++---
 libsemanage/src/direct_api.c       |  1 +
 libsemanage/src/utilities.c        |  9 +++++++++
 libsemanage/src/utilities.h        | 13 +++++++++++++
 libsemanage/tests/test_utilities.c | 26 ++++++++++++++++++++++++++
 5 files changed, 59 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/libsemanage/src/conf-parse.y b/libsemanage/src/conf-parse.y
index 6cb8a598..d3ca5f1f 100644
--- a/libsemanage/src/conf-parse.y
+++ b/libsemanage/src/conf-parse.y
@@ -21,6 +21,7 @@ 
 %{
 
 #include "semanage_conf.h"
+#include "utilities.h"
 
 #include <sepol/policydb.h>
 #include <selinux/selinux.h>
@@ -382,7 +383,10 @@  external_opt:   PROG_PATH '=' ARG  { PASSIGN(new_external->path, $3); }
 static int semanage_conf_init(semanage_conf_t * conf)
 {
 	conf->store_type = SEMANAGE_CON_DIRECT;
-	conf->store_path = strdup(basename(selinux_policy_root()));
+	const char *policy_root = selinux_policy_root();
+	if (policy_root != NULL) {
+		conf->store_path = strdup(semanage_basename(policy_root));
+	}
 	conf->ignoredirs = NULL;
 	conf->store_root_path = strdup("/var/lib/selinux");
 	conf->compiler_directory_path = strdup("/usr/libexec/selinux/hll");
@@ -544,8 +548,11 @@  static int parse_module_store(char *arg)
 	free(current_conf->store_path);
 	if (strcmp(arg, "direct") == 0) {
 		current_conf->store_type = SEMANAGE_CON_DIRECT;
-		current_conf->store_path =
-		    strdup(basename(selinux_policy_root()));
+		const char *policy_root = selinux_policy_root();
+		if (policy_root != NULL) {
+			current_conf->store_path =
+			    strdup(semanage_basename(policy_root));
+		}
 		current_conf->server_port = -1;
 	} else if (*arg == '/') {
 		current_conf->store_type = SEMANAGE_CON_POLSERV_LOCAL;
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index 99cba7f7..ce12ccaf 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -26,6 +26,7 @@ 
 
 #include <assert.h>
 #include <fcntl.h>
+#include <libgen.h>
 #include <stdio.h>
 #include <stdio_ext.h>
 #include <stdlib.h>
diff --git a/libsemanage/src/utilities.c b/libsemanage/src/utilities.c
index 70b5b677..004ffb62 100644
--- a/libsemanage/src/utilities.c
+++ b/libsemanage/src/utilities.c
@@ -349,3 +349,12 @@  int write_full(int fd, const void *buf, size_t len)
 
 	return 0;
 }
+
+#ifdef __GNUC__
+__attribute__((nonnull))
+#endif
+char *semanage_basename(const char *filename)
+{
+	char *p = strrchr(filename, '/');
+	return p ? p + 1 : (char *)filename;
+}
diff --git a/libsemanage/src/utilities.h b/libsemanage/src/utilities.h
index c2d484a7..7481077a 100644
--- a/libsemanage/src/utilities.h
+++ b/libsemanage/src/utilities.h
@@ -156,4 +156,17 @@  semanage_list_t *semanage_slurp_file_filter(FILE * file,
 
 int write_full(int fd, const void *buf, size_t len) WARN_UNUSED;
 
+/**
+ * Portable implementation of the glibc version of basename(3).
+ *
+ * @param filename  path to find basename of
+ *
+ * @return          basename of filename
+ */
+
+#ifdef __GNUC__
+__attribute__((nonnull))
+#endif
+char *semanage_basename(const char *filename);
+
 #endif
diff --git a/libsemanage/tests/test_utilities.c b/libsemanage/tests/test_utilities.c
index bbd5af30..70a76fe7 100644
--- a/libsemanage/tests/test_utilities.c
+++ b/libsemanage/tests/test_utilities.c
@@ -46,6 +46,7 @@  static void test_semanage_rtrim(void);
 static void test_semanage_str_replace(void);
 static void test_semanage_findval(void);
 static void test_slurp_file_filter(void);
+static void test_semanage_basename(void);
 
 static char fname[] = {
 	'T', 'E', 'S', 'T', '_', 'T', 'E', 'M', 'P', '_', 'X', 'X', 'X', 'X',
@@ -117,6 +118,10 @@  int semanage_utilities_add_tests(CU_pSuite suite)
 				test_slurp_file_filter)) {
 		goto err;
 	}
+	if (NULL == CU_add_test(suite, "semanage_basename",
+				test_semanage_basename)) {
+		goto err;
+	}
 	return 0;
       err:
 	CU_cleanup_registry();
@@ -346,3 +351,24 @@  static void test_slurp_file_filter(void)
 
 	semanage_list_destroy(&data);
 }
+
+static void test_semanage_basename(void)
+{
+	char *basename1 = semanage_basename("/foo/bar");
+	CU_ASSERT_STRING_EQUAL(basename1, "bar");
+
+	char *basename2 = semanage_basename("/foo/bar/");
+	CU_ASSERT_STRING_EQUAL(basename2, "");
+
+	char *basename3 = semanage_basename("/foo.bar");
+	CU_ASSERT_STRING_EQUAL(basename3, "foo.bar");
+
+	char *basename5 = semanage_basename(".");
+	CU_ASSERT_STRING_EQUAL(basename5, ".");
+
+	char *basename6 = semanage_basename("");
+	CU_ASSERT_STRING_EQUAL(basename6, "");
+
+	char *basename7 = semanage_basename("/");
+	CU_ASSERT_STRING_EQUAL(basename7, "");
+}