From 70e7dd0da58071557c897fbce2f48c8169633a54 Mon Sep 17 00:00:00 2001
From: wujing <wujing50@huawei.com>
Date: Fri, 15 Apr 2022 11:11:38 +0800
Subject: [PATCH] Refactor the way to convert selinux label to shared mode

Signed-off-by: wujing <wujing50@huawei.com>
---
 src/lxc/lsm/selinux.c | 58 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 46 insertions(+), 12 deletions(-)

diff --git a/src/lxc/lsm/selinux.c b/src/lxc/lsm/selinux.c
index 79697c5..0a1e205 100644
--- a/src/lxc/lsm/selinux.c
+++ b/src/lxc/lsm/selinux.c
@@ -230,15 +230,11 @@ static int selinux_chcon(const char *fpath, const char *label, bool recurse)
 {
 	struct stat s_buf;
 
-	if (fpath == NULL) {
-		ERROR("Empty file path");
+	if (fpath == NULL || label == NULL) {
+		ERROR("Invalid parameters!");
 		return -1;
 	}
 
-	if (label == NULL) {
-		return 0;
-	}
-
 	if (bad_prefix(fpath) != 0) {
 		return -1;
 	}
@@ -257,6 +253,42 @@ static int selinux_chcon(const char *fpath, const char *label, bool recurse)
 	return 0;
 }
 
+/*
+ * convert_context_to_share_mode: set sensitivity to s0 and remove categories
+ * user:role:type:sensitivity[:categories] => user:role:type:s0
+ *
+ * @label   : label string
+ *
+ * Returns label with share mode on success, NULL on failure
+ */
+static char *convert_context_to_share_mode(const char *label) {
+	__do_free char *converted_label = strdup(label);
+	char *s = converted_label;
+	const char *shared_level = "s0";
+	int cnt = 0;
+
+	// selinux label format: user:role:type:sensitivity[:categories]
+	// locates the ":" position in front of the sensitivity
+	while (cnt++ < 3 && (s = strchr(s, ':')) != NULL) {
+		s++;
+	}
+
+	// make sure sensitivity can set s0 value
+	if (s == NULL || strlen(s) < strlen(shared_level)) {
+		ERROR("Invalid selinux file context: %s", label);	
+		return NULL;
+	}
+
+	if (strcmp(s, shared_level) == 0) {
+		return move_ptr(converted_label);
+	}
+
+	*s = '\0';
+	strcat(converted_label, shared_level);
+
+	return move_ptr(converted_label);
+}
+
 /*
  * selinux_relabel: Relabel changes the label of path to the filelabel string.
  * It changes the MCS label to s0 if shared is true.
@@ -280,20 +312,22 @@ static int selinux_relabel(const char *path, const char *label, bool shared)
 		return 0;
 	}
 
-	tmp_file_label = strdup(label);
 	if (is_exclude_relabel_path(path)) {
 		ERROR("SELinux relabeling of %s is not allowed", path);
 		return -1;
 	}
 
 	if (shared) {
-		context_t c = context_new(label);
-		context_range_set(c, "s0");
-		free(tmp_file_label);
-		tmp_file_label = strdup(context_str(c));
-		context_free(c);
+		tmp_file_label = convert_context_to_share_mode(label);
+		if (tmp_file_label == NULL) {
+			ERROR("Failed to convert context to share mode: %s", label);
+			return -1;
+		}
+	} else {
+		tmp_file_label = strdup(label);
 	}
 
+
 	if (selinux_chcon(path, tmp_file_label, true) != 0) {
 		ERROR("Failed to modify %s's selinux context: %s", path, tmp_file_label);
 		return -1;
-- 
2.35.1

