From c986c183818f7d2fb4f796be13b6d5b7c8cb2114 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Tue, 26 Mar 2013 13:01:53 -0400 Subject: [PATCH] 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 --- mcstrans-0.3.3-inotify.patch | 294 +++++++++++++++++++++++++++++++++++ mcstrans-0.3.3-man.patch | 197 +++++++++++++++++++++++ mcstrans.spec | 19 ++- 3 files changed, 507 insertions(+), 3 deletions(-) create mode 100644 mcstrans-0.3.3-inotify.patch create mode 100644 mcstrans-0.3.3-man.patch diff --git a/mcstrans-0.3.3-inotify.patch b/mcstrans-0.3.3-inotify.patch new file mode 100644 index 0000000..cf9122c --- /dev/null +++ b/mcstrans-0.3.3-inotify.patch @@ -0,0 +1,294 @@ +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 + #include + #include + #include +@@ -30,7 +33,7 @@ + #include + #include + #include +- ++#include + + #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); diff --git a/mcstrans-0.3.3-man.patch b/mcstrans-0.3.3-man.patch new file mode 100644 index 0000000..70c1631 --- /dev/null +++ b/mcstrans-0.3.3-man.patch @@ -0,0 +1,197 @@ +diff -up mcstrans-0.3.3/man/man8/mcstransd.8.man mcstrans-0.3.3/man/man8/mcstransd.8 +--- mcstrans-0.3.3/man/man8/mcstransd.8.man 2011-12-06 08:45:02.000000000 -0500 ++++ mcstrans-0.3.3/man/man8/mcstransd.8 2013-03-26 12:54:30.653747835 -0400 +@@ -11,7 +11,8 @@ This manual page describes the + .BR mcstransd + program. + .P +-This daemon reads /etc/selinux/{SELINUXTYPE}/setrans.conf configuration file, and communicates with libselinux via a socket in /var/run/setrans. ++This daemon reads /etc/selinux/{SELINUXTYPE}/setrans.conf and /etc/selinux/{SELINUXTYPE}/secolors.conf configuration files, and communicates with libselinux via a socket in /var/run/setrans. ++It also watches for files created in /var/run/setrans and uses the contents of these files to generate translations to the names. For example writing a file /var/run/setrans/mydomain with content of s0:c1,c2 will cause mcstrans to translate s0:c1,c2 to mydomain. + + .SH "AUTHOR" + This man page was written by Dan Walsh . +diff -up mcstrans-0.3.3/man/man8/secolor.conf.8.man mcstrans-0.3.3/man/man8/secolor.conf.8 +--- mcstrans-0.3.3/man/man8/secolor.conf.8.man 2013-03-26 12:51:30.505001415 -0400 ++++ mcstrans-0.3.3/man/man8/secolor.conf.8 2013-03-26 12:51:30.504001411 -0400 +@@ -0,0 +1,180 @@ ++.TH "secolor.conf" "8" "08 April 2011" "SELinux API documentation" ++.SH "NAME" ++secolor.conf \- The SELinux color configuration file ++. ++.SH "DESCRIPTION" ++The ++.I /etc/selinux/{SELINUXTYPE}/secolor.conf ++configuation file controls the color to be associated to the context components associated to the ++.I raw ++context passed by ++.BR selinux_raw_context_to_color "(3)," ++when context related information is to be displayed in color by an SELinux-aware application. ++.sp ++.BR selinux_raw_context_to_color "(3)" ++obtains this color information from the active policy ++.B secolor.conf ++file as returned by ++.BR selinux_colors_path "(3)." ++. ++.SH "FILE FORMAT" ++The file format is as follows: ++.RS ++.B color ++.I color_name ++.BI "= #"color_mask ++.br ++[...] ++.sp ++.I context_component string ++.B = ++.I fg_color_name bg_color_name ++.br ++[...] ++.sp ++.RE ++ ++Where: ++.br ++.B color ++.RS ++The color keyword. Each color entry is on a new line. ++.RE ++.I color_name ++.RS ++A single word name for the color (e.g. red). ++.RE ++.I color_mask ++.RS ++A color mask starting with a hash (#) that describes the hexadecimal RGB colors with black being #000000 and white being #ffffff. ++.RE ++.I context_component ++.RS ++The context component name that must be one of the following: ++.br ++.RS ++user, role, type or range ++.RE ++Each ++.IR context_component " " string " ..." ++entry is on a new line. ++.RE ++.I string ++.RS ++This is the ++.I context_component ++string that will be matched with the ++.I raw ++context component passed by ++.BR selinux_raw_context_to_color "(3)." ++.br ++A wildcard '*' may be used to match any undefined string for the user, role and type ++.I context_component ++entries only. ++.RE ++ ++.I fg_color_name ++.RS ++The color_name string that will be used as the foreground color. ++A ++.I color_mask ++may also be used. ++.RE ++.I bg_color_name ++.RS ++The color_name string that will be used as the background color. ++A ++.I color_mask ++may also be used. ++.RE ++. ++.SH "EXAMPLES" ++Example 1 entries are: ++.RS ++color black = #000000 ++.br ++color green = #008000 ++.br ++color yellow = #ffff00 ++.br ++color blue = #0000ff ++.br ++color white = #ffffff ++.br ++color red = #ff0000 ++.br ++color orange = #ffa500 ++.br ++color tan = #D2B48C ++.sp ++user * = black white ++.br ++role * = white black ++.br ++type * = tan orange ++.br ++range s0\-s0:c0.c1023 = black green ++.br ++range s1\-s1:c0.c1023 = white green ++.br ++range s3\-s3:c0.c1023 = black tan ++.br ++range s5\-s5:c0.c1023 = white blue ++.br ++range s7\-s7:c0.c1023 = black red ++.br ++range s9\-s9:c0.c1023 = black orange ++.br ++range s15:c0.c1023 = black yellow ++.RE ++ ++.sp ++Example 2 entries are: ++.RS ++color black = #000000 ++.br ++color green = #008000 ++.br ++color yellow = #ffff00 ++.br ++color blue = #0000ff ++.br ++color white = #ffffff ++.br ++color red = #ff0000 ++.br ++color orange = #ffa500 ++.br ++color tan = #d2b48c ++.sp ++user unconfined_u = #ff0000 green ++.br ++role unconfined_r = red #ffffff ++.br ++type unconfined_t = red orange ++.br ++user user_u = black green ++.br ++role user_r = white black ++.br ++type user_t = tan red ++.br ++user xguest_u = black yellow ++.br ++role xguest_r = black red ++.br ++type xguest_t = black green ++.br ++user sysadm_u = white black ++.br ++range s0:c0.c1023 = black white ++.br ++user * = black white ++.br ++role * = black white ++.br ++type * = black white ++.RE ++. ++.SH "SEE ALSO" ++.BR mcstransd "(8), " selinux_raw_context_to_color "(3), " selinux_colors_path "(3)" diff --git a/mcstrans.spec b/mcstrans.spec index bbde9f2..130d083 100644 --- a/mcstrans.spec +++ b/mcstrans.spec @@ -1,12 +1,15 @@ Summary: SELinux Translation Daemon Name: mcstrans Version: 0.3.3 -Release: 6%{?dist} +Release: 7%{?dist} License: GPL+ Group: System Environment/Daemons Source: http://fedora.redhat.com/projects/%{name}-%{version}.tgz Source1: mcstransd.service Patch: mcstrans-0.3.2-writepid.patch +Patch1: mcstrans-0.3.3-inotify.patch +Patch2: mcstrans-0.3.3-man.patch +Patch3: mcstrans-0.3.3-memory.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libselinux-devel >= 1.30.3-1 BuildRequires: libcap-devel pcre-devel libsepol-devel libsepol-static @@ -35,6 +38,9 @@ from internal representations to user defined representation. %prep %setup -q %patch -p1 -b .writepid +%patch1 -p1 -b .inotify +%patch2 -p1 -b .man +%patch3 -p1 -b .memory %build make clean @@ -81,6 +87,7 @@ fi %{_mandir}/man8/mcs.8.gz %{_mandir}/man8/mcstransd.8.gz %{_mandir}/man8/setrans.conf.8.gz +%{_mandir}/man8/secolor.conf.8.gz /sbin/mcstransd %{_unitdir}/mcstransd.service %dir %{_sysconfdir}/selinux/mls/setrans.d @@ -96,6 +103,12 @@ fi %{_usr}/share/mcstrans/util/* %changelog +* Tue Mar 26 2013 Dan Walsh - 0.3.3-7 +- 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 + * Thu Feb 14 2013 Fedora Release Engineering - 0.3.3-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild @@ -124,7 +137,7 @@ fi - Fix mixed raw and translated range bug - Moved todo comments to TODO file -* Thu Oct 16 2009 Dan Walsh 0.3.1-4 +* Fri Oct 16 2009 Dan Walsh 0.3.1-4 - Add mcstransd man page * Thu Sep 17 2009 Miroslav Grepl 0.3.1-3 @@ -155,7 +168,7 @@ fi * Tue Feb 12 2008 Dan Walsh 0.2.7-2 - Rebuild for gcc 4.3 -* Mon Oct 30 2007 Steve Conklin - 0.2.7-1 +* Tue Oct 30 2007 Steve Conklin - 0.2.7-1 - Folded current patches into tarball * Thu Oct 25 2007 Steve Conklin - 0.2.6-3