[redhat-lspp] [PATCH] setrans - selinux translation daemon
Chad Hanson
chanson at trustedcs.com
Wed Apr 26 21:12:07 UTC 2006
I am attaching the following patches as an initial framework for the SELinux
translation daemon.
The patches include functionality in the following areas: daemon, client,
initialization, and initial policy.
After implementing, we should change the file contexts of the translation
configuration files to SystemHigh. A label arbitration routine needs to be
added into the daemon to determine whether caller should be able translate
the requested labels.
-Chad
-------------- next part --------------
diff -Nur libsetrans-0.1.20.orig/include/setrans.h libsetrans-0.1.20/include/setrans.h
--- libsetrans-0.1.20.orig/include/setrans.h 1970-01-01 00:00:00.000000000 +0000
+++ libsetrans-0.1.20/include/setrans.h 2006-04-25 19:07:08.000000000 +0000
@@ -0,0 +1,26 @@
+/* Copyright (c) 2006 Trusted Computer Solutions, Inc. */
+
+#ifndef _SETRANS_H
+#define _SETRANS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This must be called once, prior to calling any other
+ translation function.
+ Returns nonzero if translations cannot be performed,
+ or 0 otherwise. */
+int init_context_translations(void);
+
+/* Perform context translation.
+ Caller must free the resulting context.
+ Returns nonzero if error or 0 otherwise. */
+int translate_context(const char *, char **);
+int untranslate_context(const char *, char **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SETRANS_H */
diff -Nur libsetrans-0.1.20.orig/src/Makefile libsetrans-0.1.20/src/Makefile
--- libsetrans-0.1.20.orig/src/Makefile 2005-09-27 16:21:13.000000000 +0000
+++ libsetrans-0.1.20/src/Makefile 2006-04-25 19:07:08.000000000 +0000
@@ -2,6 +2,7 @@
PREFIX ?= $(DESTDIR)/usr
LIBDIR ?= $(PREFIX)/lib
SHLIBDIR ?= $(DESTDIR)/lib
+SBINDIR ?= $(DESTDIR)/sbin
LIBVERSION = 0
@@ -9,13 +10,17 @@
LIBA=libsetrans.a
TARGET=libsetrans.so
LIBSO=$(TARGET).$(LIBVERSION)
-OBJS= $(patsubst %.c,%.o,$(wildcard *.c))
-LOBJS= $(patsubst %.c,%.lo,$(wildcard *.c))
+LIBRARY_SRC=setrans_client.c
+OBJS= $(patsubst %.c,%.o,$(LIBRARY_SRC))
+LOBJS= $(patsubst %.c,%.lo,$(LIBRARY_SRC))
+PROG_SRC=setrans.c setransd.c
+PROG_OBJS= $(patsubst %.c,%.o,$(PROG_SRC))
+PROG=setransd
CFLAGS ?= -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute
override CFLAGS += -I../include -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
RANLIB=ranlib
-all: $(LIBA) $(LIBSO)
+all: $(LIBA) $(LIBSO) $(PROG)
$(LIBA): $(OBJS)
$(AR) rcs $@ $^
@@ -25,6 +30,9 @@
$(CC) $(LDFLAGS) -shared -o $@ $^ -ldl -Wl,-soname,$(LIBSO),-z,defs -lselinux
ln -sf $@ $(TARGET)
+$(PROG): $(PROG_OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^ -lselinux -lpthread -L. -lsetrans
+
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
@@ -37,10 +45,12 @@
test -d $(SHLIBDIR) || install -m 755 -d $(SHLIBDIR)
install -m 755 $(LIBSO) $(SHLIBDIR)
cd $(LIBDIR) && ln -sf ../../`basename $(SHLIBDIR)`/$(LIBSO) $(TARGET)
+ test -d $(SBINDIR) || install -m 755 -d $(SBINDIR)
+ install -m 755 $(PROG) $(SBINDIR)
relabel:
/sbin/restorecon $(SHLIBDIR)/$(LIBSO)
clean:
- -rm -f $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) *~ \#*
+ -rm -f $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) $(PROG) $(PROG_OBJS) *~ \#*
diff -Nur libsetrans-0.1.20.orig/src/setrans.c libsetrans-0.1.20/src/setrans.c
--- libsetrans-0.1.20.orig/src/setrans.c 2006-03-13 18:58:23.000000000 +0000
+++ libsetrans-0.1.20/src/setrans.c 2006-04-25 19:07:08.000000000 +0000
@@ -376,7 +376,7 @@
Might want to change to some kind of reload eventually, for long running
processes.
*/
-int init_context_translations(void) {
+int init_translations(void) {
FILE *cfg=NULL;
labels_t *ptr=NULL;
labels_t *next=NULL;
@@ -415,7 +415,7 @@
}
/* Look for selabel via external name */
-int translate_context( const security_context_t oldcon, security_context_t *rcon) {
+int trans_context( const security_context_t oldcon, security_context_t *rcon) {
const char *range=NULL;
context_t con=context_new(oldcon);
@@ -435,7 +435,7 @@
}
/* Look for selabel via external name */
-int untranslate_context( const security_context_t oldcon, security_context_t *rcon) {
+int untrans_context( const security_context_t oldcon, security_context_t *rcon) {
const char *range=NULL;
const char *newrange=NULL;
context_t con=context_new(oldcon);
@@ -447,9 +447,7 @@
const char *ptr=strchr(range,'-');
/* if ranged label */
if(ptr) {
- /* Now tmpbuf has minimum level string
- * and &range[i] has clearance level string.
- * If minimum and clearance level is same
+ /* If minimum and clearance level is same
* use single level string as range.
* This removes the need to define same
* level ranges (ex: SystemHigh-SystemHigh)
diff -Nur libsetrans-0.1.20.orig/src/setrans_client.c libsetrans-0.1.20/src/setrans_client.c
--- libsetrans-0.1.20.orig/src/setrans_client.c 1970-01-01 00:00:00.000000000 +0000
+++ libsetrans-0.1.20/src/setrans_client.c 2006-04-25 19:08:40.000000000 +0000
@@ -0,0 +1,222 @@
+/* Copyright (c) 2006 Trusted Computer Solutions, Inc. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <netdb.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <selinux/selinux.h>
+#include "dso.h"
+#include "setrans_internal.h"
+#include "setrans.h"
+
+
+/*
+ * setransd_open
+ *
+ * This function opens a socket to the setransd.
+ * Returns: on success, a file descriptor ( >= 0 ) to the socket
+ * on error, a negative value
+ */
+static int
+setransd_open(void)
+{
+ struct sockaddr_un addr;
+ int fd;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, SETRANS_UNIX_SOCKET);
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+/* Returns: 0 on success, <0 on failure */
+static int
+send_request(int fd, uint32_t function, const char *data1, const char *data2)
+{
+ struct iovec req_hdr[4];
+ uint32_t data1_size;
+ uint32_t data2_size;
+ struct iovec req_data[2];
+ ssize_t count;
+
+ if (fd < 0)
+ return -1;
+
+ if (!data1)
+ data1 = "";
+ if (!data2)
+ data2 = "";
+
+ data1_size = strlen(data1) + 1;
+ data2_size = strlen(data2) + 1;
+
+ req_hdr[0].iov_base = &function;
+ req_hdr[0].iov_len = sizeof(function);
+ req_hdr[1].iov_base = &data1_size;
+ req_hdr[1].iov_len = sizeof(data1_size);
+ req_hdr[2].iov_base = &data2_size;
+ req_hdr[2].iov_len = sizeof(data2_size);
+
+ while (((count = writev(fd, req_hdr, 3)) < 0) && (errno == EINTR));
+ if (count != (sizeof(function) + sizeof(data1_size) +
+ sizeof(data2_size) )) {
+ return -1;
+ }
+
+ req_data[0].iov_base = (char *)data1;
+ req_data[0].iov_len = data1_size;
+ req_data[1].iov_base = (char *)data2;
+ req_data[1].iov_len = data2_size;
+
+ while (((count = writev(fd, req_data, 2)) < 0) && (errno == EINTR));
+ if (count < 0 || (uint32_t)count != (data1_size + data2_size)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Returns: 0 on success, <0 on failure */
+static int
+receive_response(int fd, uint32_t function, char **outdata, int32_t *ret_val)
+{
+ struct iovec resp_hdr[3];
+ uint32_t func;
+ uint32_t data_size;
+ char *data;
+ struct iovec resp_data;
+ ssize_t count;
+
+ if (fd < 0)
+ return -1;
+
+ resp_hdr[0].iov_base = &func;
+ resp_hdr[0].iov_len = sizeof(func);
+ resp_hdr[1].iov_base = &data_size;
+ resp_hdr[1].iov_len = sizeof(data_size);
+ resp_hdr[2].iov_base = ret_val;
+ resp_hdr[2].iov_len = sizeof(*ret_val);
+
+ while (((count = readv(fd, resp_hdr, 3)) < 0) && (errno == EINTR));
+ if (count != (sizeof(func) + sizeof(data_size) + sizeof(*ret_val))) {
+ return -1;
+ }
+
+ if (func != function || !data_size) {
+ return -1;
+ }
+
+ data = malloc(data_size);
+ if (!data) {
+ return -1;
+ }
+
+ resp_data.iov_base = data;
+ resp_data.iov_len = data_size;
+
+ while (((count = readv(fd, &resp_data, 1))) < 0 && (errno == EINTR));
+ if (count < 0 || (uint32_t)count != data_size || data[data_size - 1] != '\0') {
+ free(data);
+ return -1;
+ }
+
+ *outdata = data;
+ return 0;
+}
+
+int
+translate_context(const char *in, char **out)
+{
+ int ret;
+ int32_t ret_val;
+ int fd;
+
+ *out = NULL;
+
+ fd = setransd_open();
+ if (fd < 0)
+ return fd;
+
+ ret = send_request(fd, RAW_TO_TRANS_CONTEXT, in, NULL);
+ if (ret)
+ goto out;
+
+ ret = receive_response(fd, RAW_TO_TRANS_CONTEXT, out, &ret_val);
+ if (ret)
+ goto out;
+
+ ret = ret_val;
+out:
+ close(fd);
+ return ret;
+}
+
+int
+untranslate_context(const char *in, char **out)
+{
+ int ret;
+ int32_t ret_val;
+ int fd;
+
+ *out = NULL;
+
+ fd = setransd_open();
+ if (fd < 0)
+ return fd;
+ ret = send_request(fd, TRANS_TO_RAW_CONTEXT, in, NULL);
+ if (ret)
+ goto out;
+
+ ret = receive_response(fd, TRANS_TO_RAW_CONTEXT, out, &ret_val);
+ if (ret)
+ goto out;
+
+ ret = ret_val;
+out:
+ close(fd);
+ return ret_val;
+}
+
+
+int
+init_context_translations(void)
+{
+ int ret, fd;
+ int32_t ret_val;
+ char *out = NULL;
+
+ fd = setransd_open();
+ if (fd < 0)
+ return fd;
+
+ ret = send_request(fd, SETRANS_INIT, NULL, NULL);
+ if (ret)
+ goto out;
+
+ ret = receive_response(fd, SETRANS_INIT, &out, &ret_val);
+ free(out);
+ if (!ret)
+ ret = ret_val;
+out:
+ close(fd);
+ return ret;
+}
+
diff -Nur libsetrans-0.1.20.orig/src/setransd.c libsetrans-0.1.20/src/setransd.c
--- libsetrans-0.1.20.orig/src/setransd.c 1970-01-01 00:00:00.000000000 +0000
+++ libsetrans-0.1.20/src/setransd.c 2006-04-25 19:10:36.000000000 +0000
@@ -0,0 +1,510 @@
+/* Copyright (c) 2006 Trusted Computer Solutions, Inc. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <selinux/selinux.h>
+
+#include "setrans_internal.h"
+#include "setrans.h"
+
+#ifdef DEBUG
+#define log_debug(fmt, ...) syslog(LOG_DEBUG, fmt, __VA_ARGS__)
+#else
+#define log_debug(fmt, ...) ;
+#endif
+
+int init_translations(void);
+int trans_context(const security_context_t, security_context_t *);
+int untrans_context(const security_context_t, security_context_t *);
+
+#define SETRANSD_PATHNAME "/sbin/setransd"
+
+/* name of program (for error messages) */
+#define SETRANSD_PROGNAME "setransd"
+
+static int sockfd = -1; /* socket we are listening on */
+
+static int restart_daemon = 0;
+
+static void
+cleanup_exit(int ret)
+{
+ if (sockfd >=0)
+ (void)unlink(SETRANS_UNIX_SOCKET);
+ exit(ret);
+}
+
+
+/*
+ * Convert raw label portion of a security context to translated label
+ * Returns: 0 on success, 1 on failure
+ */
+static int
+raw_to_trans_context(char *in, char **out, char *pcon)
+{
+
+ *out = NULL;
+
+ /* TODO: Check if MLS clearance (in "pcon") dominates the MLS label
+ * (in "in").
+ */
+
+ trans_context(in, out);
+
+ return 0;
+}
+
+
+/*
+ * Convert translated label of a security context to raw label
+ * Returns: 0 on success, 1 on failure
+ */
+static int
+trans_to_raw_context(char *in, char **out, char *pcon)
+{
+ *out = NULL;
+
+ /* TODO: Check if MLS clearance (in "pcon") dominates the MLS label
+ * (in "in").
+ */
+
+ untrans_context(in, out);
+
+ return 0;
+}
+
+static int
+send_response(int fd, uint32_t function, char *data, int32_t ret_val)
+{
+ struct iovec resp_hdr[3];
+ uint32_t data_size;
+ struct iovec resp_data;
+ ssize_t count;
+
+ if (!data)
+ data = "";
+
+ data_size = strlen(data) + 1;
+
+ resp_hdr[0].iov_base = &function;
+ resp_hdr[0].iov_len = sizeof(function);
+ resp_hdr[1].iov_base = &data_size;
+ resp_hdr[1].iov_len = sizeof(data_size);
+ resp_hdr[2].iov_base = &ret_val;
+ resp_hdr[2].iov_len = sizeof(ret_val);
+
+ log_debug("Response header func=%d size=%d ret_val=%d",
+ function, data_size, ret_val);
+
+ while (((count = writev(fd, resp_hdr, 3)) < 0) && (errno == EINTR));
+ if (count != (sizeof(function) + sizeof(data_size) + sizeof(ret_val))) {
+ syslog(LOG_ERR, "Failed to write response header");
+ return -1;
+ }
+
+ resp_data.iov_base = data;
+ resp_data.iov_len = data_size;
+
+ log_debug("Response data=%s", data);
+
+ while (((count = writev(fd, &resp_data, 1)) < 0) && (errno == EINTR));
+ if (count < 0 || count != data_size) {
+ syslog(LOG_ERR, "Failed to write response data");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+process_request(int fd, uint32_t function, char *data1, char *data2)
+{
+ int32_t result;
+ char *out = NULL;
+ char *peercon;
+ struct ucred peercred;
+ socklen_t size = sizeof(struct ucred);
+ int ret;
+
+ log_debug("Processing request func=%d data1=%s data2=%s"
+ , function, data1, data2);
+
+ /* get the context of the requesting process */
+ ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &size);
+ if (ret < 0) {
+ syslog(LOG_ERR, "Failed to get PID of client process");
+ return -1;
+ }
+ ret = getpidcon_raw(peercred.pid, &peercon);
+ if (ret) {
+ syslog(LOG_ERR, "Failed to get context of client process");
+ return -1;
+ }
+
+ switch (function) {
+ case SETRANS_INIT:
+ result = 0;
+ ret = send_response(fd, function, NULL, result);
+ break;
+ case RAW_TO_TRANS_CONTEXT:
+ result = raw_to_trans_context(data1, &out, peercon);
+ ret = send_response(fd, function, out, result);
+ break;
+ case TRANS_TO_RAW_CONTEXT:
+ result = trans_to_raw_context(data1, &out, peercon);
+ ret = send_response(fd, function, out, result);
+ break;
+ default:
+ syslog(LOG_ERR, "Invalid request func=%d", function);
+ ret = -1;
+ break;
+ }
+
+ free(out);
+ freecon(peercon);
+
+ return ret;
+}
+
+static int
+service_request(int fd)
+{
+ struct iovec req_hdr[3];
+ uint32_t function;
+ uint32_t data1_size;
+ uint32_t data2_size;
+ struct iovec req_data[2];
+ char *data1;
+ char *data2;
+ int ret;
+ ssize_t count;
+
+ req_hdr[0].iov_base = &function;
+ req_hdr[0].iov_len = sizeof(function);
+ req_hdr[1].iov_base = &data1_size;
+ req_hdr[1].iov_len = sizeof(data1_size);
+ req_hdr[2].iov_base = &data2_size;
+ req_hdr[2].iov_len = sizeof(data2_size);
+
+ while (((count = readv(fd, req_hdr, 3)) < 0) && (errno == EINTR));
+ if (!count) {
+ log_debug("Received no data for fd (%d)", fd);
+ return 1;
+ }
+ if (count != (sizeof(function) + sizeof(data1_size) +
+ sizeof(data2_size) )) {
+ syslog(LOG_ERR, "Failed to read request header");
+ return -1;
+ }
+
+ log_debug("Received header func=%d size1=%d size2=%d"
+ , function, data1_size, data2_size);
+
+ if (!data1_size || !data2_size) {
+ syslog(LOG_ERR, "Header invalid data1_size=%d data2_size=%d",
+ data1_size, data2_size);
+ return -1;
+ }
+
+ data1 = malloc(data1_size);
+ if (!data1) {
+ syslog(LOG_ERR, "Could not allocate %d bytes", data1_size);
+ return -1;
+ }
+ data2 = malloc(data2_size);
+ if (!data2) {
+ free(data1);
+ syslog(LOG_ERR, "Could not allocate %d bytes", data2_size);
+ return -1;
+ }
+
+ req_data[0].iov_base = data1;
+ req_data[0].iov_len = data1_size;
+ req_data[1].iov_base = data2;
+ req_data[1].iov_len = data2_size;
+
+ while (((count = readv(fd, req_data, 2)) < 0) && (errno == EINTR));
+ if (count < 0 || count != (data1_size + data2_size) ||
+ data1[data1_size - 1] != '\0' || data2[data2_size - 1] != '\0') {
+ free(data1);
+ free(data2);
+ syslog(LOG_ERR, "Failed to read request data");
+ return -1;
+ }
+
+ log_debug("Received data1=%s data2=%s", data1, data2);
+
+ ret = process_request(fd, function, data1, data2);
+
+ free(data1);
+ free(data2);
+
+ return ret;
+}
+
+static int
+add_pollfd(struct pollfd **ufds, int *nfds, int connfd)
+{
+ int ii = 0;
+
+ /* First see if we can find an already invalidated ufd */
+ for (ii = 0; ii < *nfds; ii++) {
+ if ((*ufds)[ii].fd == -1)
+ break;
+ }
+
+ if (ii == *nfds) {
+ struct pollfd *tmp = (struct pollfd *)realloc(*ufds,
+ (*nfds+1)*sizeof(struct pollfd));
+ if (!tmp) {
+ syslog(LOG_ERR, "realloc failed for %d fds", *nfds+1);
+ return -1;
+ }
+
+ *ufds = tmp;
+ (*nfds)++;
+ }
+
+ (*ufds)[ii].fd = connfd;
+ (*ufds)[ii].events = POLLIN|POLLPRI;
+ (*ufds)[ii].revents = 0;
+
+ return 0;
+}
+
+static void
+adj_pollfds(struct pollfd **ufds, int *nfds)
+{
+ int ii, jj;
+
+ jj = 0;
+ for (ii = 0; ii < *nfds; ii++) {
+ if ((*ufds)[ii].fd != -1) {
+ if (jj < ii)
+ (*ufds)[jj] = (*ufds)[ii];
+ jj++;
+ }
+ }
+ *nfds = jj;
+}
+
+static int
+process_events(struct pollfd **ufds, int *nfds)
+{
+ int ii = 0;
+ int ret = 0;
+
+ for (ii = 0; ii < *nfds; ii++) {
+ short revents = (*ufds)[ii].revents;
+ int connfd = (*ufds)[ii].fd;
+
+ log_debug("Events returned for fd (%d) are (%x)",
+ connfd, revents);
+
+ if (revents & (POLLIN | POLLPRI)) {
+ if (connfd == sockfd) {
+
+ /* Probably received a connection */
+ if ((connfd = accept(sockfd, NULL, NULL)) < 0) {
+ syslog(LOG_ERR, "accept() failed: %m");
+ return -1;
+ }
+
+ log_debug("Accepted connection with fd (%d)",
+ connfd);
+
+ if (add_pollfd(ufds, nfds, connfd)) {
+ syslog(LOG_ERR, "Failed to add fd (%d) to poll list", connfd);
+ return -1;
+ }
+ } else {
+ ret = service_request(connfd);
+ if (ret) {
+ if (ret < 0) {
+ syslog(LOG_ERR, "Servicing of request failed "
+ "for fd (%d)", connfd);
+ }
+ /* Set the pollfd up for deletion later. */
+ (*ufds)[ii].fd = -1;
+ close(connfd);
+ }
+ }
+ revents = revents & ~(POLLIN | POLLPRI);
+ }
+ if (revents & POLLHUP) {
+ log_debug("The connection with fd (%d) hung up", connfd);
+
+ /* Set the pollfd up for deletion later. */
+ (*ufds)[ii].fd = -1;
+ close(connfd);
+
+ revents = revents & ~(POLLHUP);
+ }
+ if (revents) {
+ syslog(LOG_ERR, "Unknown/error events (%x) encountered"
+ " for fd (%d)", revents, connfd);
+
+ /* Set the pollfd up for deletion later. */
+ (*ufds)[ii].fd = -1;
+ close(connfd);
+ }
+
+ (*ufds)[ii].revents = 0;
+ }
+
+ /* Delete any invalidated ufds */
+ adj_pollfds(ufds, nfds);
+
+ return 0;
+}
+
+static void
+process_connections(void)
+{
+ int ret = 0;
+ struct pollfd *ufds;
+ int nfds;
+
+ ufds = (struct pollfd *)malloc(sizeof(struct pollfd));
+ if (!ufds) {
+ syslog(LOG_ERR, "Failed to allocate a pollfd");
+ cleanup_exit(1);
+ }
+ ufds[0].fd = sockfd;
+ ufds[0].events = POLLIN|POLLPRI;
+ ufds[0].revents = 0;
+ nfds = 1;
+
+ while (1) {
+ if (restart_daemon) {
+ (void)unlink(SETRANS_UNIX_SOCKET);
+ execl(SETRANSD_PATHNAME, SETRANSD_PATHNAME, (char *)NULL);
+ syslog(LOG_ERR, "Failed to restart");
+ cleanup_exit(1);
+ }
+
+ log_debug("About to poll for %d fds", nfds);
+ ret = poll(ufds, nfds, -1);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ syslog(LOG_ERR, "poll() failed: %m");
+ cleanup_exit(1);
+ }
+
+ ret = process_events(&ufds, &nfds);
+ if (ret) {
+ syslog(LOG_ERR, "Error processing events");
+ cleanup_exit(1);
+ }
+ }
+}
+
+static void
+sigterm_handler(int sig)
+{
+ cleanup_exit(0);
+}
+
+static void
+sighup_handler(int sig)
+{
+ restart_daemon = 1;
+}
+
+static void
+initialize(void)
+{
+ struct sigaction act;
+ struct sockaddr_un addr;
+
+ if (init_translations()) {
+ syslog(LOG_ERR, "Failed to initialize label translations");
+ cleanup_exit(1);
+ }
+
+ /* the socket will be unlinked when the daemon terminates */
+ act.sa_handler = sigterm_handler;
+ sigemptyset(&act.sa_mask);
+ sigaddset(&act.sa_mask, SIGINT);
+ sigaddset(&act.sa_mask, SIGQUIT);
+ sigaddset(&act.sa_mask, SIGTERM);
+ sigaddset(&act.sa_mask, SIGHUP);
+ act.sa_flags = 0;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGQUIT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+
+ /* restart the daemon on SIGHUP */
+ act.sa_handler = sighup_handler;
+ sigemptyset(&act.sa_mask);
+ sigaddset(&act.sa_mask, SIGINT);
+ sigaddset(&act.sa_mask, SIGQUIT);
+ sigaddset(&act.sa_mask, SIGTERM);
+ act.sa_flags = 0;
+ sigaction(SIGHUP, &act, NULL);
+
+ /* ignore SIGPIPE (in case a client terminates after sending request) */
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGPIPE, &act, NULL);
+
+ sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ syslog(LOG_ERR, "socket() failed: %m");
+ cleanup_exit(1);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path) - 1);
+
+ (void)unlink(SETRANS_UNIX_SOCKET);
+
+ if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ syslog(LOG_ERR, "bind() failed: %m");
+ cleanup_exit(1);
+ }
+
+ if (listen(sockfd, SOMAXCONN) < 0) {
+ syslog(LOG_ERR, "listen() failed: %m");
+ cleanup_exit(1);
+ }
+
+ if (chmod(SETRANS_UNIX_SOCKET, S_IRWXU | S_IRWXG | S_IRWXO)) {
+ syslog(LOG_ERR, "chmod() failed: %m");
+ cleanup_exit(1);
+ }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ openlog(SETRANSD_PROGNAME, 0, LOG_DAEMON);
+
+ /* run in the background as a daemon */
+ if (daemon(0, 0)) {
+ syslog(LOG_ERR, "daemon() failed: %m");
+ exit(1);
+ }
+
+ initialize();
+
+ process_connections();
+
+ /* we should never get here */
+ return 1;
+}
diff -Nur libsetrans-0.1.20.orig/src/setrans_internal.h libsetrans-0.1.20/src/setrans_internal.h
--- libsetrans-0.1.20.orig/src/setrans_internal.h 1970-01-01 00:00:00.000000000 +0000
+++ libsetrans-0.1.20/src/setrans_internal.h 2006-04-25 19:08:15.000000000 +0000
@@ -0,0 +1,8 @@
+/* Copyright (c) 2006 Trusted Computer Solutions, Inc. */
+
+#define SETRANS_UNIX_SOCKET "/var/.setrans-unix"
+
+#define SETRANS_INIT 1
+#define RAW_TO_TRANS_CONTEXT 2
+#define TRANS_TO_RAW_CONTEXT 3
+
-------------- next part --------------
--- rc.sysinit.orig 2006-03-14 22:50:20.000000000 +0000
+++ rc.sysinit 2006-04-24 16:40:58.000000000 +0000
@@ -419,6 +419,11 @@
# filesystems are NOT unmounted in single user mode.
action $"Mounting local filesystems: " mount -a -t nonfs,nfs4,smbfs,ncpfs,cifs,gfs -O no_netdev
+# Start the setransd if available
+if [ -x /sbin/setransd ]; then
+ action $"Starting setransd: " /sbin/setransd
+fi
+
if [ -x /sbin/quotaon ]; then
action $"Enabling local filesystem quotas: " /sbin/quotaon -aug
fi
-------------- next part --------------
diff -Nur serefpolicy-2.2.29.orig/policy/modules/kernel/domain.te serefpolicy-2.2.29/policy/modules/kernel/domain.te
--- serefpolicy-2.2.29.orig/policy/modules/kernel/domain.te 2006-03-31 16:11:34.000000000 +0000
+++ serefpolicy-2.2.29/policy/modules/kernel/domain.te 2006-04-25 18:43:30.000000000 +0000
@@ -87,6 +87,8 @@
# list the root directory
files_list_root(domain)
+setrans_translate_context(domain)
+
ifdef(`targeted_policy',`
# RBAC is disabled in the targeted policy,
# as only one role is used, system_r.
diff -Nur serefpolicy-2.2.29.orig/policy/modules/kernel/mls.te serefpolicy-2.2.29/policy/modules/kernel/mls.te
--- serefpolicy-2.2.29.orig/policy/modules/kernel/mls.te 2006-04-13 15:48:25.000000000 +0000
+++ serefpolicy-2.2.29/policy/modules/kernel/mls.te 2006-04-25 18:42:21.000000000 +0000
@@ -63,4 +63,5 @@
range_transition secadm_t auditctl_exec_t s15:c0.c255;
range_transition kernel_t init_exec_t s0 - s15:c0.c255;
range_transition kernel_t lvm_exec_t s0 - s15:c0.c255;
+range_transition initrc_t setrans_exec_t s15:c0.c255;
')
-------------- next part --------------
policy_module(setrans,1.0.0)
########################################
#
# Declarations
#
type setrans_t;
type setrans_exec_t;
init_daemon_domain(setrans_t, setrans_exec_t)
mls_file_read_up(setrans_t)
mls_file_write_down(setrans_t)
mls_net_receive_all_levels(setrans_t)
mls_rangetrans_target(setrans_t)
type setrans_unix_stream_t;
files_type(setrans_unix_stream_t)
mls_trusted_object(setrans_unix_stream_t)
########################################
#
# setrans local policy
#
init_use_fds(setrans_t)
kernel_read_kernel_sysctls(setrans_t)
kernel_read_proc_symlinks(setrans_t)
allow setrans_t self:process signal_perms;
libs_use_ld_so(setrans_t)
libs_use_shared_libs(setrans_t)
# create unix domain socket in /var
allow setrans_t var_t:dir rw_dir_perms;
allow setrans_t setrans_unix_stream_t:sock_file create_file_perms;
type_transition setrans_t var_t:sock_file setrans_unix_stream_t;
allow setrans_t self:unix_stream_socket create_stream_socket_perms;
allow setrans_t self:unix_dgram_socket create_socket_perms;
allow setrans_t self:netlink_selinux_socket create_socket_perms;
miscfiles_read_localization(setrans_t)
seutil_read_config(setrans_t)
selinux_compute_access_vector(setrans_t)
files_read_etc_runtime_files(setrans_t)
# allow performing getpidcon() on all processes
domain_read_all_domains_state(setrans_t)
#allow setrans_t domain:{ sock_file fifo_file } r_file_perms;
domain_getattr_all_domains(setrans_t)
domain_getsession_all_domains(setrans_t)
corecmd_search_sbin(setrans_t)
can_exec(setrans_t, setrans_exec_t)
logging_send_syslog_msg(setrans_t)
-------------- next part --------------
/sbin/setransd -- gen_context(system_u:object_r:setrans_exec_t,s0)
/var/.setrans-unix -- gen_context(system_u:object_r:setrans_unix_stream_t,s15:c0.c255)
-------------- next part --------------
## <summary>Policy for setrans.</summary>
#######################################
## <summary>
## Allow a domain to translate contexts.
## </summary>
## <param name="domain">
## <summary>
## The type of the process performing this action.
## </summary>
## </param>
#
interface(`setrans_translate_context',`
gen_require(`
type setrans_t, setrans_unix_stream_t;
')
allow $1 self:unix_stream_socket create_stream_socket_perms;
allow $1 setrans_t:unix_stream_socket connectto;
files_search_var($1)
allow $1 setrans_unix_stream_t:sock_file rw_file_perms;
allow $1 setrans_unix_stream_t:unix_stream_socket rw_socket_perms;
')
More information about the redhat-lspp
mailing list