mcstrans/mcstrans-0.3.3-inotify.patch
Dan Walsh c986c18381 Add secolor.conf.5 man page
- Make mcstransd watch for content being written to /run/setrans for files names containing translations.
-- This will allow apps like libvirt to write content nameing randomly selected MCS labels
- Fix memory leak in mcstransd
2013-03-26 13:01:53 -04:00

295 lines
7.9 KiB
Diff

diff -up mcstrans-0.3.3/src/mcstrans.c.inotify mcstrans-0.3.3/src/mcstrans.c
--- mcstrans-0.3.3/src/mcstrans.c.inotify 2011-12-06 08:45:02.000000000 -0500
+++ mcstrans-0.3.3/src/mcstrans.c 2013-02-08 08:48:08.343787003 -0500
@@ -1,6 +1,8 @@
/* Copyright (c) 2008-2009 Nall Design Works
- Copyright 2006 Trusted Computer Solutions, Inc. */
+ Copyright 2006 Trusted Computer Solutions, Inc.
+ Copyright 2013 Red Hat, Inc.
+*/
/*
Exported Interface
@@ -12,6 +14,7 @@
*/
+#include <dirent.h>
#include <math.h>
#include <glob.h>
#include <values.h>
@@ -30,7 +33,7 @@
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
-
+#include <sys/inotify.h>
#include "mls_level.h"
#include "mcstrans.h"
@@ -166,6 +169,30 @@ err:
}
static int
+remove_from_hashtable(context_map_node_t **table, char *key) {
+ unsigned int bucket = hash(key) % N_BUCKETS;
+ context_map_node_t **n;
+ context_map_node_t **p = NULL;
+ context_map_node_t *next = NULL;
+ for (n = &table[bucket]; *n; n = &(*n)->next) {
+ if (!strcmp((*n)->key, key))
+ break;
+ p = n;
+ }
+ if (! *n)
+ return -1;
+
+ next = (*n)->next;
+ free(*n);
+ if (p)
+ (*p)->next = next;
+ else
+ table[bucket] = next;
+
+ return 0;
+}
+
+static int
numdigits(unsigned int n)
{
int count = 1;
@@ -665,6 +692,26 @@ find_in_table(context_map_node_t **table
return NULL;
}
+static void
+remove_cache(domain_t *domain, char *raw) {
+ context_map_t *map=find_in_table(domain->raw_to_trans, raw);
+ if (!map) {
+ log_error("Failed to remove_cache (%s) does not exist\n", raw);
+ return;
+ }
+ log_debug(" remove_cache (%s,%s)\n", raw, map->trans);
+ if (remove_from_hashtable(domain->trans_to_raw, map->trans) < 0) {
+ log_error(" Failed to remove %s from trans_to_raw\n", map->trans);
+ }
+
+ if (remove_from_hashtable(domain->raw_to_trans, raw) < 0) {
+ log_error(" Failed to remove %s from raw_to_trans\n", raw);
+ }
+ free(map->raw);
+ free(map->trans);
+ free(map);
+}
+
char *
trim(char *str, const char *whitespace) {
char *p = str + strlen(str);
@@ -1760,3 +1809,113 @@ finish_context_translations(void) {
}
}
+#define INOTIFY_WATCHDIR "/run/setrans"
+
+/* size of the event structure, not counting name */
+#define EVENT_SIZE (sizeof (struct inotify_event))
+/* reasonable guess as to size of 1024 events */
+#define BUF_LEN (1024 * (EVENT_SIZE + 16))
+static domain_t *inotify_domain;
+
+int add_inotify_cache(char *raw) {
+ char trans[BUF_LEN+1];
+ char path[PATH_MAX];
+ FILE *f;
+ size_t len;
+ domain_t *domain = domains;
+ for (;domain; domain = domain->next) {
+ context_map_t *map=find_in_table(domain->raw_to_trans, raw);
+ if (map) {
+ log_error("Failed to add translation %s to cache (%s,%s) already exists\n", raw, raw, map->trans);
+ return -1;
+ }
+ }
+ memset(trans,0, sizeof(trans));
+ memset(path,0, sizeof(path));
+ len = snprintf(path, sizeof(path), "%s/%s", INOTIFY_WATCHDIR, raw);
+ if (len >= sizeof(path)) {
+ log_error("Failed to open %s/%s, too large for buffer\n", INOTIFY_WATCHDIR, raw);
+ }
+ f = fopen(path, "r");
+ if(! f) {
+ log_error("Failed to open %s %s\n", path, strerror(errno));
+ return -1;
+ }
+ fread(trans, 1, BUF_LEN, f);
+ fclose(f);
+ return add_cache(inotify_domain, raw, trans);
+}
+
+int process_inotify(int inotifyfd) {
+ int i = 0;
+ char buf[BUF_LEN+1];
+ int len;
+ memset(buf,0, BUF_LEN);
+ len = read(inotifyfd, buf, BUF_LEN);
+ if (len < 0) {
+ return -1;
+ } else if (!len)
+ /* BUF_LEN too small? */
+ return -1;
+ while (i < len) {
+ struct inotify_event *event;
+ event = (struct inotify_event *)&buf[i];
+ if (event->mask & IN_DELETE) {
+ if (event->len && event->name[0] != '.') {
+ remove_cache(inotify_domain, event->name);
+ }
+ }
+ if (event->mask & IN_CREATE) {
+ if (event->len && event->name[0] != '.') {
+ (void) add_inotify_cache(event->name);
+ }
+ }
+
+ i += EVENT_SIZE + event->len;
+ }
+ return 0;
+}
+
+/* Watch INOTIFY_WATCHDIR for file creaton and deletion, then attempt to
+ add/remove the contents of these files to the cache. The name of the
+ file is the raw MLS/MCS label, while the contents are the Translation name.
+*/
+int init_inotify(void) {
+ DIR *dir;
+ struct dirent *entry;
+ int fd = inotify_init1(IN_CLOEXEC);
+ if (fd < 0) {
+ syslog(LOG_ERR, "socket() failed: %m");
+ return -1;
+ }
+
+ if (inotify_add_watch(fd, INOTIFY_WATCHDIR, IN_CREATE | IN_DELETE) < 0)
+ {
+ syslog(LOG_ERR, "inotify_add_watch( %s ) failed: %m", INOTIFY_WATCHDIR);
+ goto err;
+ }
+ inotify_domain = create_domain("inotify");
+ if (!inotify_domain) {
+ syslog(LOG_ERR, "create_domain(inotify) failed: %m");
+ goto err;
+ }
+
+ /* read all existing files in the INOTIFY_WATCHDIR and add them to the
+ cache.
+ */
+ if ((dir = opendir(INOTIFY_WATCHDIR)) == NULL) {
+ syslog(LOG_ERR, "opendirs(%s) failed: %m", INOTIFY_WATCHDIR);
+ goto err;
+ }
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_name[0] != '.')
+ (void) add_inotify_cache(entry->d_name);
+ }
+ closedir(dir);
+
+ return fd;
+
+err:
+ close(fd);
+ return -1;
+}
diff -up mcstrans-0.3.3/src/mcstransd.c.inotify mcstrans-0.3.3/src/mcstransd.c
--- mcstrans-0.3.3/src/mcstransd.c.inotify 2013-02-08 08:37:32.772422371 -0500
+++ mcstrans-0.3.3/src/mcstransd.c 2013-02-08 08:37:32.784422421 -0500
@@ -60,6 +60,7 @@ extern int raw_color(const security_cont
#define SETRANSD_PROGNAME "mcstransd"
static int sockfd = -1; /* socket we are listening on */
+static int inotifyfd = -1; /* inotify socket we are listening on */
static volatile int restart_daemon = 0;
static void cleanup_exit(int ret) __attribute__ ((noreturn));
@@ -354,19 +355,23 @@ process_events(struct pollfd **ufds, int
return -1;
}
} else {
- ret = service_request(connfd);
- if (ret) {
- if (ret < 0) {
- syslog(LOG_ERR,
- "Servicing of request "
- "failed for fd (%d)\n",
- connfd);
+ if (connfd == inotifyfd) {
+ process_inotify(inotifyfd);
+ } else {
+ ret = service_request(connfd);
+ if (ret) {
+ if (ret < 0) {
+ syslog(LOG_ERR,
+ "Servicing of request "
+ "failed for fd (%d)\n",
+ connfd);
+ }
+ /* Setup pollfd for deletion later. */
+ (*ufds)[ii].fd = -1;
+ close(connfd);
+ /* So we don't get bothered later */
+ revents = revents & ~(POLLHUP);
}
- /* Setup pollfd for deletion later. */
- (*ufds)[ii].fd = -1;
- close(connfd);
- /* So we don't get bothered later */
- revents = revents & ~(POLLHUP);
}
}
revents = revents & ~(POLLIN | POLLPRI);
@@ -406,9 +411,9 @@ static void
process_connections(void)
{
int ret = 0;
- int nfds = 1;
+ int nfds = 2;
- struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd));
+ struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd)*nfds);
if (!ufds) {
syslog(LOG_ERR, "Failed to allocate a pollfd");
cleanup_exit(1);
@@ -417,6 +422,10 @@ process_connections(void)
ufds[0].events = POLLIN|POLLPRI;
ufds[0].revents = 0;
+ ufds[1].fd = inotifyfd;
+ ufds[1].events = POLLIN|POLLPRI;
+ ufds[1].revents = 0;
+
while (1) {
if (restart_daemon) {
syslog(LOG_NOTICE, "Reload Translations");
@@ -516,6 +525,11 @@ initialize(void)
cleanup_exit(1);
}
+ inotifyfd = init_inotify();
+ if (inotifyfd < 0) {
+ 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);
diff -up mcstrans-0.3.3/src/mcstrans.h.inotify mcstrans-0.3.3/src/mcstrans.h
--- mcstrans-0.3.3/src/mcstrans.h.inotify 2011-12-06 08:45:02.000000000 -0500
+++ mcstrans-0.3.3/src/mcstrans.h 2013-02-08 08:37:32.784422421 -0500
@@ -6,4 +6,5 @@ extern int init_translations(void);
extern void finish_context_translations(void);
extern int trans_context(const security_context_t, security_context_t *);
extern int untrans_context(const security_context_t, security_context_t *);
-
+extern int init_inotify(void);
+extern int process_inotify(int inotifyfd);