summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Craig <rpcraig@tycho.ncsc.mil>2014-03-17 20:53:06 -0400
committerNick Kralevich <nnk@google.com>2014-05-30 20:43:57 +0000
commit5b5183f9b7c1a09429cfb113b4d144882c03530f (patch)
treecb57ee2640aec6b35dc329680fa4ea564849eaf1
parenta8e4ad3c81df866583a8929bcb5d48a2000ce738 (diff)
downloadlibselinux-5b5183f9b7c1a09429cfb113b4d144882c03530f.tar.gz
SELinux changes to check policy versions during a reload.
New construct which validates /data/security/current/selinux_version against the base version file /selinux_version when policy overrides could occur. This change covers the cases where sepolicy, seapp_contexts and file_contexts under /data/security/current can be used to override their rootfs counterparts. Change-Id: I4716039bb0f5ba1e961977a18350347a67969dca Signed-off-by: rpcraig <rpcraig@tycho.ncsc.mil>
-rw-r--r--include/selinux/android.h3
-rw-r--r--src/android.c138
2 files changed, 111 insertions, 30 deletions
diff --git a/include/selinux/android.h b/include/selinux/android.h
index a131400..ae6c05d 100644
--- a/include/selinux/android.h
+++ b/include/selinux/android.h
@@ -1,6 +1,7 @@
#ifndef _SELINUX_ANDROID_H_
#define _SELINUX_ANDROID_H_
+#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
@@ -42,6 +43,8 @@ extern int selinux_android_restorecon_pkgdir(const char *pkgdir,
extern int selinux_android_seapp_context_reload(void);
+extern bool selinux_android_use_data_policy(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/android.c b/src/android.c
index 29236e0..d0432d4 100644
--- a/src/android.c
+++ b/src/android.c
@@ -35,15 +35,18 @@
*/
static char const * const seapp_contexts_file[] = {
"/seapp_contexts",
+ "/data/security/current/seapp_contexts",
NULL };
static const struct selinux_opt seopts[] = {
{ SELABEL_OPT_PATH, "/file_contexts" },
+ { SELABEL_OPT_PATH, "/data/security/current/file_contexts" },
{ 0, NULL } };
static const char *const sepolicy_file[] = {
- "/sepolicy",
- NULL };
+ "/sepolicy",
+ "/data/security/current/sepolicy",
+ NULL };
enum levelFrom {
LEVELFROM_NONE,
@@ -52,6 +55,77 @@ enum levelFrom {
LEVELFROM_ALL
};
+#define POLICY_OVERRIDE_VERSION "/data/security/current/selinux_version"
+#define POLICY_BASE_VERSION "/selinux_version"
+static int policy_index = 0;
+
+static void set_policy_index(void)
+{
+ int fd_base = -1, fd_override = -1;
+ struct stat sb_base;
+ struct stat sb_override;
+ void *map_base, *map_override;
+
+ policy_index = 0;
+
+ fd_base = open(POLICY_BASE_VERSION, O_RDONLY | O_NOFOLLOW);
+ if (fd_base < 0)
+ return;
+
+ if (fstat(fd_base, &sb_base) < 0) {
+ close(fd_base);
+ return;
+ }
+
+ fd_override = open(POLICY_OVERRIDE_VERSION, O_RDONLY | O_NOFOLLOW);
+ if (fd_override < 0) {
+ close(fd_base);
+ return;
+ }
+
+ if (fstat(fd_override, &sb_override) < 0) {
+ close(fd_base);
+ close(fd_override);
+ return;
+ }
+
+ if (sb_base.st_size != sb_override.st_size) {
+ close(fd_base);
+ close(fd_override);
+ return;
+ }
+
+ map_base = mmap(NULL, sb_base.st_size, PROT_READ, MAP_PRIVATE, fd_base, 0);
+ if (map_base == MAP_FAILED) {
+ close(fd_base);
+ close(fd_override);
+ return;
+ }
+
+ map_override = mmap(NULL, sb_override.st_size, PROT_READ, MAP_PRIVATE, fd_override, 0);
+ if (map_override == MAP_FAILED) {
+ munmap(map_base, sb_base.st_size);
+ close(fd_base);
+ close(fd_override);
+ return;
+ }
+
+ if (memcmp(map_base, map_override, sb_base.st_size) == 0)
+ policy_index = 1;
+
+
+ close(fd_base);
+ close(fd_override);
+ munmap(map_base, sb_base.st_size);
+ munmap(map_override, sb_override.st_size);
+}
+
+bool selinux_android_use_data_policy(void)
+{
+ set_policy_index();
+ return (policy_index == 1);
+}
+
#if DEBUG
static char const * const levelFromName[] = {
"none",
@@ -205,11 +279,11 @@ int selinux_android_seapp_context_reload(void)
struct seapp_context *cur;
char *p, *name = NULL, *value = NULL, *saveptr;
size_t len;
- int i = 0, n, ret;
+ int n, ret;
- while ((fp==NULL) && seapp_contexts_file[i])
- fp = fopen(seapp_contexts_file[i++], "r");
+ set_policy_index();
+ fp = fopen(seapp_contexts_file[policy_index], "r");
if (!fp) {
selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__);
return -1;
@@ -364,7 +438,7 @@ int selinux_android_seapp_context_reload(void)
if (cur->name.str &&
(!cur->seinfo || !strcmp(cur->seinfo, "default"))) {
selinux_log(SELINUX_ERROR, "%s: No specific seinfo value specified with name=\"%s\", on line %u: insecure configuration!\n",
- seapp_contexts_file[i - 1], cur->name.str, lineno);
+ seapp_contexts_file[policy_index], cur->name.str, lineno);
free_seapp_context(cur);
goto err;
}
@@ -400,7 +474,7 @@ out:
err:
selinux_log(SELINUX_ERROR, "%s: Invalid entry on line %u\n",
- seapp_contexts_file[i - 1], lineno);
+ seapp_contexts_file[policy_index], lineno);
free_seapp_contexts();
ret = -1;
goto out;
@@ -724,38 +798,32 @@ static uint8_t fc_digest[FC_DIGEST_SIZE];
static struct selabel_handle *get_selabel_handle(const struct selinux_opt opts[])
{
struct selabel_handle *h;
- unsigned int i = 0;
int fd;
struct stat sb;
void *map;
- h = NULL;
- while ((h == NULL) && opts[i].value) {
- h = selabel_open(SELABEL_CTX_FILE, &opts[i], 1);
- if (h)
- break;
- i++;
- }
+ set_policy_index();
+ h = selabel_open(SELABEL_CTX_FILE, &opts[policy_index], 1);
if (!h)
return NULL;
- fd = open(opts[i].value, O_RDONLY | O_NOFOLLOW);
+ fd = open(opts[policy_index].value, O_RDONLY | O_NOFOLLOW);
if (fd < 0) {
selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s\n",
- opts[i].value, strerror(errno));
+ opts[policy_index].value, strerror(errno));
goto err;
}
if (fstat(fd, &sb) < 0) {
selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
- opts[i].value, strerror(errno));
+ opts[policy_index].value, strerror(errno));
close(fd);
goto err;
}
map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
- opts[i].value, strerror(errno));
+ opts[policy_index].value, strerror(errno));
close(fd);
goto err;
}
@@ -764,7 +832,7 @@ static struct selabel_handle *get_selabel_handle(const struct selinux_opt opts[]
close(fd);
selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts from %s\n",
- opts[i].value);
+ opts[policy_index].value);
return h;
@@ -1219,17 +1287,22 @@ void selinux_android_set_sehandle(const struct selabel_handle *hndl)
sehandle = (struct selabel_handle *) hndl;
}
-int selinux_android_reload_policy(void)
+static int selinux_android_load_policy_helper(bool reload)
{
int fd = -1, rc;
struct stat sb;
void *map = NULL;
- int i = 0;
- while (fd < 0 && sepolicy_file[i]) {
- fd = open(sepolicy_file[i], O_RDONLY | O_NOFOLLOW);
- i++;
- }
+ /*
+ * If reloading policy and there is no /data policy or
+ * that /data policy has the wrong version or the /data
+ * policy is disabled via safe mode, then just return.
+ * There is no point in reloading policy from / a second time.
+ */
+ if (reload && !selinux_android_use_data_policy())
+ return 0;
+
+ fd = open(sepolicy_file[policy_index], O_RDONLY | O_NOFOLLOW);
if (fd < 0) {
selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
strerror(errno));
@@ -1237,14 +1310,14 @@ int selinux_android_reload_policy(void)
}
if (fstat(fd, &sb) < 0) {
selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
- sepolicy_file[i-1], strerror(errno));
+ sepolicy_file[policy_index], strerror(errno));
close(fd);
return -1;
}
map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
- sepolicy_file[i-1], strerror(errno));
+ sepolicy_file[policy_index], strerror(errno));
close(fd);
return -1;
}
@@ -1260,11 +1333,16 @@ int selinux_android_reload_policy(void)
munmap(map, sb.st_size);
close(fd);
- selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file[i-1]);
+ selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file[policy_index]);
return 0;
}
+int selinux_android_reload_policy(void)
+{
+ return selinux_android_load_policy_helper(true);
+}
+
int selinux_android_load_policy(void)
{
const char *mnt = SELINUXMNT;
@@ -1294,5 +1372,5 @@ int selinux_android_load_policy(void)
}
set_selinuxmnt(mnt);
- return selinux_android_reload_policy();
+ return selinux_android_load_policy_helper(false);
}