[PATCH 82/84] libselinux: optimize set*con functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


   This patch looks good to me. acked.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.13 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlD+qX4ACgkQrlYvE4MpobO9VQCffAy0N7x2NCiln61Tv6gPLIcp
UtMAnjGJa+ex95zTiFB0j73P+yh3IaeJ
=6rZI
-----END PGP SIGNATURE-----
>From 3b1c4c3b06f2d98611d3ef0982e5429198783795 Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <ooprala@xxxxxxxxxx>
Date: Wed, 9 Jan 2013 11:37:43 +0100
Subject: [PATCH 82/84] libselinux: optimize set*con functions

Set*con now caches the security context and only re-sets it if it changes.

Signed-off-by: Eric Paris <eparis@xxxxxxxxxx>
---
 libselinux/src/Makefile   |  10 ++--
 libselinux/src/procattr.c | 118 ++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 115 insertions(+), 13 deletions(-)

diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index ac019df..613a4ed 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -20,7 +20,7 @@ RUBYINC ?= $(shell pkg-config --cflags ruby-$(RUBYLIBVER))
 RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
 LIBBASE=$(shell basename $(LIBDIR))
 
-LDFLAGS ?= -lpcre
+LDFLAGS ?= -lpcre -lpthread
 
 VERSION = $(shell cat ../VERSION)
 LIBVERSION = 1
@@ -106,17 +106,17 @@ $(SWIGRUBYLOBJ): $(SWIGRUBYCOUT)
 	$(CC) $(CFLAGS) $(SWIG_CFLAGS) $(RUBYINC) -fPIC -DSHARED -c -o $@ $<
 
 $(SWIGSO): $(SWIGLOBJ)
-	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $< -L. -lselinux -L$(LIBDIR)
+	$(CC) $(CFLAGS) -shared -o $@ $< -L. -lselinux $(LDFLAGS) -L$(LIBDIR)
 
 $(SWIGRUBYSO): $(SWIGRUBYLOBJ)
-	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -L. -lselinux -L$(LIBDIR)
+	$(CC) $(CFLAGS) -shared -o $@ $^ -L. -lselinux $(LDFLAGS) -L$(LIBDIR)
 
 $(LIBA): $(OBJS)
 	$(AR) rcs $@ $^
 	$(RANLIB) $@
 
 $(LIBSO): $(LOBJS)
-	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -ldl -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro
+	$(CC) $(CFLAGS) -shared -o $@ $^ -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro
 	ln -sf $@ $(TARGET) 
 
 $(LIBPC): $(LIBPC).in ../VERSION
@@ -129,7 +129,7 @@ $(AUDIT2WHYLOBJ): audit2why.c
 	$(CC) $(filter-out -Werror, $(CFLAGS)) $(PYINC) -fPIC -DSHARED -c -o $@ $<
 
 $(AUDIT2WHYSO): $(AUDIT2WHYLOBJ)
-	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -L. -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
+	$(CC) $(CFLAGS) -shared -o $@ $^ -L. $(LDFLAGS) -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
 
 %.o:  %.c policy.h
 	$(CC) $(CFLAGS) $(TLSFLAGS) -c -o $@ $<
diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c
index 83381e4..bac6a63 100644
--- a/libselinux/src/procattr.c
+++ b/libselinux/src/procattr.c
@@ -1,6 +1,7 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <pthread.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -8,11 +9,64 @@
 #include "selinux_internal.h"
 #include "policy.h"
 
+static __thread pid_t cpid;
+static __thread pid_t tid;
+static __thread security_context_t prev_current;
+static __thread security_context_t prev_exec;
+static __thread security_context_t prev_fscreate;
+static __thread security_context_t prev_keycreate;
+static __thread security_context_t prev_sockcreate;
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+static pthread_key_t destructor_key;
+static int destructor_key_initialized = 0;
+static __thread char destructor_initialized;
+
 static pid_t gettid(void)
 {
 	return syscall(__NR_gettid);
 }
 
+static void procattr_thread_destructor(void __attribute__((unused)) *unused)
+{
+	free(prev_current);
+	free(prev_exec);
+	free(prev_fscreate);
+	free(prev_keycreate);
+	free(prev_sockcreate);
+}
+
+static void free_procattr(void)
+{
+	procattr_thread_destructor(NULL);
+	cpid = tid = 0;
+	prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = NULL;
+}
+
+void __attribute__((destructor)) procattr_destructor(void);
+
+void hidden __attribute__((destructor)) procattr_destructor(void)
+{
+	if (destructor_key_initialized)
+		__selinux_key_delete(destructor_key);
+}
+
+static inline void init_thread_destructor(void)
+{
+	if (destructor_initialized == 0) {
+		__selinux_setspecific(destructor_key, (void *)1);
+		destructor_initialized = 1;
+	}
+}
+
+static void init_procattr(void)
+{
+	if (__selinux_key_create(&destructor_key, procattr_thread_destructor) == 0) {
+		pthread_atfork(NULL, NULL, free_procattr);
+		destructor_key_initialized = 1;
+	}
+}
+
 static int getprocattrcon_raw(security_context_t * context,
 			      pid_t pid, const char *attr)
 {
@@ -20,13 +74,19 @@ static int getprocattrcon_raw(security_context_t * context,
 	size_t size;
 	int fd, rc;
 	ssize_t ret;
-	pid_t tid;
 	int errno_hold;
 
+	__selinux_once(once, init_procattr);
+	init_thread_destructor();
+
+	if (cpid != getpid())
+		free_procattr();
+
 	if (pid > 0)
 		rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr);
 	else {
-		tid = gettid();
+		if (!tid)
+			tid = gettid();
 		rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr);
 	}
 	if (rc < 0)
@@ -92,14 +152,47 @@ static int setprocattrcon_raw(security_context_t context,
 {
 	char *path;
 	int fd, rc;
-	pid_t tid;
 	ssize_t ret;
 	int errno_hold;
+	security_context_t *prev_context;
+
+	__selinux_once(once, init_procattr);
+	init_thread_destructor();
+
+	if (cpid != getpid())
+		free_procattr();
+
+	switch (attr[0]) {
+		case 'c':
+			prev_context = &prev_current;
+			break;
+		case 'e':
+			prev_context = &prev_exec;
+			break;
+		case 'f':
+			prev_context = &prev_fscreate;
+			break;
+		case 'k':
+			prev_context = &prev_keycreate;
+			break;
+		case 's':
+			prev_context = &prev_sockcreate;
+			break;
+		default:
+			return -1;
+	};
+
+	if (!context && !*prev_context)
+		return 0;
+	if (context && *prev_context && !strcmp(context, *prev_context))
+		return 0;
 
 	if (pid > 0)
 		rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr);
 	else {
-		tid = gettid();
+		if (!tid)
+			tid = gettid();
+
 		rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr);
 	}
 	if (rc < 0)
@@ -109,21 +202,30 @@ static int setprocattrcon_raw(security_context_t context,
 	free(path);
 	if (fd < 0)
 		return -1;
-	if (context)
+	if (context) {
+		ret = -1;
+		context = strdup(context);
+		if (!context)
+			goto out;
 		do {
 			ret = write(fd, context, strlen(context) + 1);
 		} while (ret < 0 && errno == EINTR);
-	else
+	} else {
 		do {
 			ret = write(fd, NULL, 0);	/* clear */
 		} while (ret < 0 && errno == EINTR);
+	}
+out:
 	errno_hold = errno;
 	close(fd);
 	errno = errno_hold;
-	if (ret < 0)
+	if (ret < 0) {
+		free(context);
 		return -1;
-	else
+	} else {
+		*prev_context = context;
 		return 0;
+	}
 }
 
 static int setprocattrcon(const security_context_t context,
-- 
1.8.1


[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux