aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libselinux/src/init.c25
-rw-r--r--libselinux/src/selinux_config.c13
-rw-r--r--libselinux/src/selinux_internal.h17
-rw-r--r--libselinux/src/setrans_client.c28
-rw-r--r--libselinux/src/setrans_internal.h2
-rw-r--r--libselinux/src/stringrep.c28
6 files changed, 60 insertions, 53 deletions
diff --git a/libselinux/src/init.c b/libselinux/src/init.c
index 2d5a1247..ecb31996 100644
--- a/libselinux/src/init.c
+++ b/libselinux/src/init.c
@@ -107,40 +107,15 @@ void set_selinuxmnt(char *mnt)
hidden_def(set_selinuxmnt)
-static void init_obj_class_compat(void)
-{
- char path[PATH_MAX];
- struct stat s;
-
- if (!selinux_mnt)
- return;
-
- snprintf(path,PATH_MAX,"%s/class",selinux_mnt);
- if (stat(path,&s) < 0)
- return;
-
- if (S_ISDIR(s.st_mode))
- obj_class_compat = 0;
-}
-
-static void fini_obj_class_compat(void)
-{
- obj_class_compat = 1;
-}
-
static void init_lib(void) __attribute__ ((constructor));
static void init_lib(void)
{
selinux_page_size = sysconf(_SC_PAGE_SIZE);
init_selinuxmnt();
- init_obj_class_compat();
- init_context_translations();
}
static void fini_lib(void) __attribute__ ((destructor));
static void fini_lib(void)
{
fini_selinuxmnt();
- fini_obj_class_compat();
- fini_context_translations();
}
diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c
index 48cb9712..af8731c5 100644
--- a/libselinux/src/selinux_config.c
+++ b/libselinux/src/selinux_config.c
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
+#include <pthread.h>
#include "selinux_internal.h"
#include "get_default_type_internal.h"
@@ -45,6 +46,10 @@
#define FILE_CONTEXT_SUBS 23
#define NEL 24
+/* Part of one-time lazy init */
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+static void init_selinux_config(void);
+
/* New layout is relative to SELINUXDIR/policytype. */
static char *file_paths[NEL];
#define L1(l) L2(l)
@@ -120,6 +125,7 @@ static char *selinux_policytype;
int selinux_getpolicytype(char **type)
{
+ __selinux_once(once, init_selinux_config);
if (!selinux_policytype)
return -1;
*type = strdup(selinux_policytype);
@@ -129,9 +135,7 @@ int selinux_getpolicytype(char **type)
hidden_def(selinux_getpolicytype)
static char *selinux_policyroot = NULL;
-static char *selinux_rootpath = NULL;
-
-static void init_selinux_config(void) __attribute__ ((constructor));
+static const char *selinux_rootpath = SELINUXDIR;
static void init_selinux_config(void)
{
@@ -144,7 +148,6 @@ static void init_selinux_config(void)
if (selinux_policyroot)
return;
- selinux_rootpath = SELINUXDIR;
fp = fopen(SELINUXCONFIG, "r");
if (fp) {
__fsetlocking(fp, FSETLOCKING_BYCALLER);
@@ -235,6 +238,7 @@ void reset_selinux_config(void)
static const char *get_path(int idx)
{
+ __selinux_once(once, init_selinux_config);
return file_paths[idx];
}
@@ -247,6 +251,7 @@ hidden_def(selinux_default_type_path)
const char *selinux_policy_root()
{
+ __selinux_once(once, init_selinux_config);
return selinux_policyroot;
}
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
index bbd9eee7..7a2c1ad5 100644
--- a/libselinux/src/selinux_internal.h
+++ b/libselinux/src/selinux_internal.h
@@ -1,4 +1,5 @@
#include <selinux/selinux.h>
+#include <pthread.h>
#include "dso.h"
hidden_proto(selinux_mkload_policy)
@@ -92,3 +93,19 @@ extern void reset_selinux_config(void) hidden;
extern int load_setlocaldefs hidden;
extern int require_seusers hidden;
extern int selinux_page_size hidden;
+
+/* Make pthread_once optional */
+#pragma weak pthread_once
+
+/* Call handler iff the first call. */
+#define __selinux_once(ONCE_CONTROL, INIT_FUNCTION) \
+ do { \
+ if (pthread_once != NULL) \
+ pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \
+ else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
+ INIT_FUNCTION (); \
+ (ONCE_CONTROL) = 2; \
+ } \
+ } while (0)
+
+
diff --git a/libselinux/src/setrans_client.c b/libselinux/src/setrans_client.c
index 500225e7..2bbcbde1 100644
--- a/libselinux/src/setrans_client.c
+++ b/libselinux/src/setrans_client.c
@@ -33,6 +33,8 @@ static __thread security_context_t prev_r2t_raw = NULL;
static __thread char *prev_r2c_trans = NULL;
static __thread security_context_t prev_r2c_raw = NULL;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
/*
* setransd_open
*
@@ -238,20 +240,9 @@ out:
return ret;
}
-hidden void fini_context_translations(void)
-{
- free(prev_r2t_trans);
- free(prev_r2t_raw);
- free(prev_t2r_trans);
- free(prev_t2r_raw);
- free(prev_r2c_trans);
- free(prev_r2c_raw);
-}
-
-hidden int init_context_translations(void)
+static void init_context_translations(void)
{
mls_enabled = is_selinux_mls_enabled();
- return 0;
}
int selinux_trans_to_raw_context(security_context_t trans,
@@ -262,6 +253,8 @@ int selinux_trans_to_raw_context(security_context_t trans,
return 0;
}
+ __selinux_once(once, init_context_translations);
+
if (!mls_enabled) {
*rawp = strdup(trans);
goto out;
@@ -301,6 +294,8 @@ int selinux_raw_to_trans_context(security_context_t raw,
return 0;
}
+ __selinux_once(once, init_context_translations);
+
if (!mls_enabled) {
*transp = strdup(raw);
goto out;
@@ -366,15 +361,6 @@ int selinux_raw_context_to_color(security_context_t raw, char **transp)
hidden_def(selinux_raw_context_to_color)
#else /*DISABLE_SETRANS*/
-hidden void fini_context_translations(void)
-{
-}
-
-hidden int init_context_translations(void)
-{
- return 0;
-}
-
int selinux_trans_to_raw_context(security_context_t trans,
security_context_t * rawp)
{
diff --git a/libselinux/src/setrans_internal.h b/libselinux/src/setrans_internal.h
index f6e25b1d..a801ee85 100644
--- a/libselinux/src/setrans_internal.h
+++ b/libselinux/src/setrans_internal.h
@@ -7,5 +7,3 @@
#define RAW_CONTEXT_TO_COLOR 4
#define MAX_DATA_BUF 8192
-extern int init_context_translations(void);
-extern void fini_context_translations(void);
diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c
index b3f3120e..b19bce73 100644
--- a/libselinux/src/stringrep.c
+++ b/libselinux/src/stringrep.c
@@ -152,7 +152,25 @@ static const struct av_inherit {
#define NVECTORS ARRAY_SIZE(av_perm_to_string)
#define MAXVECTORS 8*sizeof(access_vector_t)
-extern int obj_class_compat;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static int obj_class_compat;
+
+static void init_obj_class_compat(void)
+{
+ char path[PATH_MAX];
+ struct stat s;
+
+ if (!selinux_mnt)
+ return;
+
+ snprintf(path,PATH_MAX,"%s/class",selinux_mnt);
+ if (stat(path,&s) < 0)
+ return;
+
+ if (S_ISDIR(s.st_mode))
+ obj_class_compat = 0;
+}
struct discover_class_node {
char *name;
@@ -420,6 +438,8 @@ security_class_t string_to_security_class(const char *s)
{
struct discover_class_node *node;
+ __selinux_once(once, init_obj_class_compat);
+
if (obj_class_compat)
return string_to_security_class_compat(s);
@@ -441,6 +461,8 @@ access_vector_t string_to_av_perm(security_class_t tclass, const char *s)
struct discover_class_node *node;
security_class_t kclass = unmap_class(tclass);
+ __selinux_once(once, init_obj_class_compat);
+
if (obj_class_compat)
return map_perm(tclass, string_to_av_perm_compat(kclass, s));
@@ -462,6 +484,8 @@ const char *security_class_to_string(security_class_t tclass)
tclass = unmap_class(tclass);
+ __selinux_once(once, init_obj_class_compat);
+
if (obj_class_compat)
return security_class_to_string_compat(tclass);
@@ -481,6 +505,8 @@ const char *security_av_perm_to_string(security_class_t tclass,
av = unmap_perm(tclass, av);
tclass = unmap_class(tclass);
+ __selinux_once(once, init_obj_class_compat);
+
if (obj_class_compat)
return security_av_perm_to_string_compat(tclass,av);