[Open-scap] [PATCH] [probes] add selinuxsecuritycontext probe

Petr Lautrbach plautrba at redhat.com
Fri Jul 29 10:36:50 UTC 2011


---
notes:
it doesn't work with running mcstrans daemon right now - raw sensitivities
and categories are not recognized

mitre test fails on 2 issues:
* /etc/mtab is symlink in fedora 15 and it seems to be somehow ignored by
oval_fts_open() and oval_fts_read():
[I:probes/oval_fts.c:443:oval_fts_read] Only the target of a symlink gets reported; ignored.

* path element "/etc/profile.d/" from object definition is transformed to 
"/etc/profile.d" in item

 configure.ac                                       |    5 +-
 src/OVAL/oval_probe.c                              |    2 +
 src/OVAL/oval_probe_ext.c                          |    1 +
 src/OVAL/oval_probe_session.c                      |    1 +
 src/OVAL/probes/Makefile.am                        |    7 +-
 .../probes/unix/linux/selinuxsecuritycontext.c     |  322 ++++++++++++++++++++
 6 files changed, 335 insertions(+), 3 deletions(-)
 create mode 100644 src/OVAL/probes/unix/linux/selinuxsecuritycontext.c

diff --git a/configure.ac b/configure.ac
index c85a851..97610b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -347,7 +347,7 @@ AC_CHECK_LIB(
   [selinux_cflags=`pkg-config libselinux --cflags`
    selinux_libs=`pkg-config libselinux --libs`
    have_selinux=yes
-   AC_DEFINE([ENABLE_PROBE_SELINUXBOOLEAN], [1], [Define if SELinux is available])
+   AC_DEFINE([ENABLE_PROBES_SELINUX], [1], [Define if SELinux is available])
   ]
 )
 
@@ -729,7 +729,7 @@ AM_CONDITIONAL([WANT_BINDINGS], test "$bindings" = yes)
 AM_CONDITIONAL([ENABLE_VALGRIND_TESTS], test "$vgcheck" = yes)
 AM_CONDITIONAL([HAVE_ODBX], test "$have_odbx" = yes)
 AM_CONDITIONAL([ENABLE_PROBE_LDAP57], test "$probe_independent_ldap57" = yes)
-AM_CONDITIONAL(ENABLE_PROBE_SELINUXBOOLEAN, [test "$have_selinux" = "yes"])
+AM_CONDITIONAL(ENABLE_PROBES_SELINUX, [test "$have_selinux" = "yes"])
 
 AC_CONFIG_FILES([Makefile
                  lib/Makefile
@@ -834,6 +834,7 @@ echo "  rpminfo probe:               $have_librpm"
 echo "  rpmverify probe:             $have_librpm"
 echo "  partition probe:             $probes_linux"
 echo "  selinuxboolean probe:        $have_selinux"
+echo "  selinuxsecuritycontext probe: $have_selinux"
 echo ""
 
 echo "  === solaris probes ==="
diff --git a/src/OVAL/oval_probe.c b/src/OVAL/oval_probe.c
index 784f2ec..45a3308 100644
--- a/src/OVAL/oval_probe.c
+++ b/src/OVAL/oval_probe.c
@@ -68,6 +68,7 @@ oval_subtypedsc_t __s2n_tbl[] = {
         /*  9005 */ {OVAL_LINUX_PARTITION,                  "partition",          },
 	/*  9007 */ {OVAL_LINUX_RPMVERIFY,                  "rpmverify"           },
 	/*  9008 */ {OVAL_LINUX_SELINUXBOOLEAN,             "selinuxboolean"      },
+	/*  9009 */ {OVAL_LINUX_SELINUXSECURITYCONTEXT,     "selinuxsecuritycontext" },
 	/* 12001 */ {OVAL_SOLARIS_ISAINFO,                  "isainfo"             },
 	/* 13001 */ {OVAL_UNIX_FILE,                        "file"                },
 	/* 13003 */ {OVAL_UNIX_INTERFACE,                   "interface"           },
@@ -107,6 +108,7 @@ oval_subtypedsc_t __n2s_tbl[] = {
 	/*  9007 */ {OVAL_LINUX_RPMVERIFY,                  "rpmverify"           },
 	/* 13006 */ {OVAL_UNIX_RUNLEVEL,                    "runlevel"            },
 	/*  9008 */ {OVAL_LINUX_SELINUXBOOLEAN,             "selinuxboolean"      },
+	/*  9009 */ {OVAL_LINUX_SELINUXSECURITYCONTEXT,     "selinuxsecuritycontext" },
 	/* 13008 */ {OVAL_UNIX_SHADOW,                      "shadow"              },
 	/*  7005 */ {OVAL_INDEPENDENT_SQL,                  "sql"                 },
 	/*  7013 */ {OVAL_INDEPENDENT_SQL57,                "sql57"               },
diff --git a/src/OVAL/oval_probe_ext.c b/src/OVAL/oval_probe_ext.c
index 12b0254..ceb8ee8 100644
--- a/src/OVAL/oval_probe_ext.c
+++ b/src/OVAL/oval_probe_ext.c
@@ -70,6 +70,7 @@ const oval_pdsc_t OSCAP_GSYM(default_pdsc)[] = {
 	{OVAL_LINUX_RPMVERIFY,                  "rpmverify",         "probe_rpmverify"},
         {OVAL_LINUX_PARTITION,                  "partition",         "probe_partition"},
 	{OVAL_LINUX_SELINUXBOOLEAN,             "selinuxboolean",    "probe_selinuxboolean"},
+	{OVAL_LINUX_SELINUXSECURITYCONTEXT,     "selinuxsecuritycontext", "probe_selinuxsecuritycontext"},
 	{OVAL_SOLARIS_ISAINFO,                  "isainfo",           "probe_isainfo"},
 	{OVAL_UNIX_FILE,                        "file",              "probe_file"},
 	{OVAL_UNIX_INTERFACE,                   "interface",         "probe_interface"},
diff --git a/src/OVAL/oval_probe_session.c b/src/OVAL/oval_probe_session.c
index c478c65..fb7f142 100644
--- a/src/OVAL/oval_probe_session.c
+++ b/src/OVAL/oval_probe_session.c
@@ -130,6 +130,7 @@ oval_probe_session_t *oval_probe_session_new(struct oval_syschar_model *model)
         oval_probe_handler_set(sess->ph, OVAL_LINUX_RPMVERIFY, oval_probe_ext_handler, sess->pext);
         oval_probe_handler_set(sess->ph, OVAL_LINUX_PARTITION, oval_probe_ext_handler, sess->pext);
         oval_probe_handler_set(sess->ph, OVAL_LINUX_SELINUXBOOLEAN, oval_probe_ext_handler, sess->pext);
+        oval_probe_handler_set(sess->ph, OVAL_LINUX_SELINUXSECURITYCONTEXT, oval_probe_ext_handler, sess->pext);
         oval_probe_handler_set(sess->ph, OVAL_SOLARIS_ISAINFO, oval_probe_ext_handler, sess->pext);
         oval_probe_handler_set(sess->ph, OVAL_UNIX_FILE,       oval_probe_ext_handler, sess->pext);
         oval_probe_handler_set(sess->ph, OVAL_UNIX_INTERFACE,  oval_probe_ext_handler, sess->pext);
diff --git a/src/OVAL/probes/Makefile.am b/src/OVAL/probes/Makefile.am
index 2b3912f..00d99e6 100644
--- a/src/OVAL/probes/Makefile.am
+++ b/src/OVAL/probes/Makefile.am
@@ -160,11 +160,16 @@ probe_inetlisteningservers_SOURCES= unix/linux/inetlisteningservers.c
 probe_inetlisteningservers_CFLAGS=
 probe_inetlisteningservers_LDFLAGS=
 
-if ENABLE_PROBE_SELINUXBOOLEAN
+if ENABLE_PROBES_SELINUX
 pkglibexec_PROGRAMS += probe_selinuxboolean
 probe_selinuxboolean_SOURCES= unix/linux/selinuxboolean.c
 probe_selinuxboolean_CFLAGS= @selinux_cflags@
 probe_selinuxboolean_LDFLAGS= @selinux_libs@
+
+pkglibexec_PROGRAMS += probe_selinuxsecuritycontext
+probe_selinuxsecuritycontext_SOURCES= unix/linux/selinuxsecuritycontext.c
+probe_selinuxsecuritycontext_CFLAGS= @selinux_cflags@
+probe_selinuxsecuritycontext_LDFLAGS= @selinux_libs@
 endif
 
 if ENABLE_PROBE_RPMINFO
diff --git a/src/OVAL/probes/unix/linux/selinuxsecuritycontext.c b/src/OVAL/probes/unix/linux/selinuxsecuritycontext.c
new file mode 100644
index 0000000..16b176b
--- /dev/null
+++ b/src/OVAL/probes/unix/linux/selinuxsecuritycontext.c
@@ -0,0 +1,322 @@
+/**
+ * @file   selinuxsecuritycontext.c
+ * @brief  selinuxsecuritycontext probe
+ * @author "Petr Lautrbach" <plautrba at redhat.com>
+ *
+ * 2011/07/01 plautrba at redhat.com
+ *  This probe is able to process a selinuxsecuritycontext_object as defined in OVAL 5.9
+ *
+ */
+
+/*
+ * Copyright 2011 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors:
+ *      "Petr Lautrbach" <plautrba at redhat.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <seap.h>
+#include <probe-api.h>
+#include <probe/entcmp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+
+#include "oval_fts.h"
+#include "util.h"
+
+#define FILE_SEPARATOR '/'
+
+static void split_level(const char *level, char **sensitivity, char **category) {
+	char *level_split;
+
+	level_split = strchr(level, ':');
+	if (level_split == NULL) {
+		*sensitivity = strdup(level);
+		*category = NULL;
+	}
+	else {
+		*sensitivity = strndup(level, level_split - level);
+		*category = strdup(level_split + 1);
+	}
+}
+
+/* parse range according to
+ * http://selinuxproject.org/page/NB_MLS#MLS_.2F_MCS_Range_Format
+*/
+static void split_range(const char *range, char **l_s, char **l_c, char **h_s, char **h_c) {
+	char *level;
+	const char *range_split;
+
+	range_split = strchr(range, '-');
+	if (range_split == NULL) {
+		/* there is only 1 level */
+		split_level(range, l_s, l_c);
+		*h_s = NULL;
+		*h_c = NULL;
+	}
+	else {
+		/* low level */
+		level = strndup(range, range_split - range);
+		split_level(level, l_s, l_c);
+		free(level);
+
+		/* high level */
+		level = strdup(range_split + 1);
+		split_level(level, h_s, h_c);
+		free(level);
+	}
+}
+
+static int selinuxsecuritycontext_process_cb (SEXP_t *pid_ent, probe_ctx *ctx) {
+
+	SEXP_t *pid_sexp, *item;
+	security_context_t pid_context;
+	context_t context;
+	int pid_number;
+	DIR *proc;
+	struct dirent *dir_entry;
+	const char *user, *role, *type, *range;
+	char *l_sensitivity, *l_category, *h_sensitivity, *h_category;
+
+	if ((proc = opendir("/proc")) == NULL) {
+		dE("Can't open /proc dir: %s\n", strerror(errno));
+
+		probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR);
+		return errno;
+	}
+
+	while ((dir_entry = readdir(proc))) {
+		if (strspn(dir_entry->d_name, "0123456789") != strlen(dir_entry->d_name))
+			continue;
+
+		pid_number = atoi(dir_entry->d_name);
+		pid_sexp = SEXP_number_newi_32(pid_number);
+		if (probe_entobj_cmp(pid_ent, pid_sexp) == OVAL_RESULT_TRUE) {
+
+			if (getpidcon(pid_number, &pid_context) == -1) {
+				/* error getting pid selinux context */
+				dW("Can't get selinux context for process %d\n", pid_number);
+				SEXP_free(pid_sexp);
+				continue;
+			}
+
+			context = context_new(pid_context);
+
+			user = context_user_get(context);
+			role = context_role_get(context);
+			type = context_type_get(context);
+			range = context_range_get(context);
+
+			split_range(range, &l_sensitivity, &l_category, &h_sensitivity, &h_category);
+			item = probe_item_create(OVAL_LINUX_SELINUXSECURITYCONTEXT, NULL,
+				"pid",     OVAL_DATATYPE_INTEGER, pid_number,
+				"user",     OVAL_DATATYPE_STRING, user,
+				"role",     OVAL_DATATYPE_STRING, role,
+				"type",     OVAL_DATATYPE_STRING, type,
+				"low_sensitivity", OVAL_DATATYPE_STRING, l_sensitivity,
+				"low_category", OVAL_DATATYPE_STRING, l_category,
+				"high_sensitivity", OVAL_DATATYPE_STRING, h_sensitivity,
+				"high_category", OVAL_DATATYPE_STRING, h_category,
+
+				NULL);
+			probe_item_collect(ctx, item);
+
+			context_free(context);
+			freecon(pid_context);
+		}
+		SEXP_free(pid_sexp);
+	}
+	closedir(proc);
+
+	return 0;
+}
+
+
+static int selinuxsecuritycontext_file_cb (const char *p, const char *f, probe_ctx *ctx)
+{
+	SEXP_t *item;
+
+	char   pbuf[PATH_MAX+1];
+	size_t plen, flen;
+
+	security_context_t file_context;
+	int file_context_size;
+	context_t context;
+	const char *user, *role, *type, *range;
+	char *l_sensitivity, *l_category, *h_sensitivity, *h_category;
+	int err = 0;
+
+	/* directory */
+	if (f == NULL)
+		flen = 0;
+	else
+		flen = strlen (f);
+
+	/*
+	 * Prepare path
+	 */
+	plen = strlen (p);
+
+	if (plen + flen + 1 > PATH_MAX)
+		return (-1);
+
+	memcpy (pbuf, p, sizeof (char) * plen);
+
+	if (p[plen - 1] != FILE_SEPARATOR) {
+		pbuf[plen] = FILE_SEPARATOR;
+		++plen;
+	}
+
+	if (f != NULL)
+		memcpy (pbuf + plen, f, sizeof (char) * flen);
+
+	pbuf[plen+flen] = '\0';
+
+	file_context_size = getfilecon(pbuf, &file_context);
+	if (file_context_size == -1) {
+		SEXP_t *at, *r0, *r1;
+		dE("Can't get context for %s: %s\n", pbuf, strerror(errno));
+		strerror_r (errno, pbuf, PATH_MAX);
+		pbuf[PATH_MAX] = '\0';
+
+		at = probe_attr_creat ("status",  r0 = SEXP_number_newi_32 (OVAL_STATUS_ERROR),
+				       "message", r1 = SEXP_string_newf ("%s", pbuf),
+				       NULL);
+
+		SEXP_vfree (r0, r1, NULL);
+
+		item = probe_item_creat ("selinuxsecuritycontext_item", at, NULL);
+		SEXP_free(at);
+		err = errno;
+
+	}
+	else {
+		context = context_new(file_context);
+
+		user = context_user_get(context);
+		role = context_role_get(context);
+		type = context_type_get(context);
+		range = context_range_get(context);
+
+		split_range(range, &l_sensitivity, &l_category, &h_sensitivity, &h_category);
+
+		item = probe_item_create(OVAL_LINUX_SELINUXSECURITYCONTEXT, NULL,
+						"filepath", OVAL_DATATYPE_STRING, pbuf,
+						"path",     OVAL_DATATYPE_STRING, p,
+						"filename", OVAL_DATATYPE_STRING, f,
+						"user",     OVAL_DATATYPE_STRING, user,
+						"role",     OVAL_DATATYPE_STRING, role,
+						"type",     OVAL_DATATYPE_STRING, type,
+						"low_sensitivity", OVAL_DATATYPE_STRING, l_sensitivity,
+						"low_category", OVAL_DATATYPE_STRING, l_category,
+						"high_sensitivity", OVAL_DATATYPE_STRING, h_sensitivity,
+						"high_category", OVAL_DATATYPE_STRING, h_category,
+						"rawlow_sensitivity", OVAL_DATATYPE_STRING, l_sensitivity,
+						"rawlow_category", OVAL_DATATYPE_STRING, l_category,
+						"rawhigh_sensitivity", OVAL_DATATYPE_STRING, h_sensitivity,
+						"rawhigh_category", OVAL_DATATYPE_STRING, h_category,
+						NULL);
+		context_free(context);
+		freecon(file_context);
+	}
+	probe_item_collect(ctx, item);
+
+	return (err);
+}
+
+int probe_main(probe_ctx *ctx, void *arg)
+{
+	SEXP_t *probe_in;
+	SEXP_t *path, *filename, *filepath, *pid, *behaviors = NULL;
+	int process_pid;
+
+	OVAL_FTS    *ofts;
+	OVAL_FTSENT *ofts_ent;
+
+	if ( ! is_selinux_enabled()) {
+		probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_NOT_APPLICABLE);
+		return 0;
+	}
+
+	probe_in  = probe_ctx_getobject(ctx);
+
+	path      = probe_obj_getent (probe_in, "path",      1);
+	filename  = probe_obj_getent (probe_in, "filename",  1);
+	filepath  = probe_obj_getent (probe_in, "filepath", 1);
+	pid       = probe_obj_getent (probe_in, "pid", 1);
+
+	if (((path == NULL || filename == NULL) && filepath==NULL ) && pid == NULL) {
+		SEXP_free (path);
+		SEXP_free (filename);
+		SEXP_free (filepath);
+		SEXP_free (pid);
+
+		return (PROBE_ENOELM);
+	}
+
+	if (filepath || (path && filename)) {
+		probe_filebehaviors_canonicalize(&behaviors);
+
+		if ((ofts = oval_fts_open(path, filename, filepath, behaviors)) != NULL) {
+			while ((ofts_ent = oval_fts_read(ofts)) != NULL) {
+				selinuxsecuritycontext_file_cb(ofts_ent->path, ofts_ent->file, ctx);
+				oval_ftsent_free(ofts_ent);
+			}
+
+			oval_fts_close(ofts);
+		}
+		SEXP_free(behaviors);
+	}
+
+	if (pid != NULL) {
+		PROBE_ENT_I32VAL(pid, process_pid, return -1;);
+
+		if (process_pid == 0) {
+			SEXP_t *nref, *nval, *pid2;
+
+			nref = SEXP_list_first(probe_in);
+			nval = SEXP_number_newu_32(getpid());
+			pid2 = SEXP_list_new(nref, nval, NULL);
+			SEXP_vfree(pid, nref, nval, NULL);
+			pid = pid2;
+		}
+
+		selinuxsecuritycontext_process_cb(pid, ctx);
+	}
+
+	SEXP_free (path);
+	SEXP_free (filename);
+	SEXP_free (filepath);
+	SEXP_free (pid);
+
+	return 0;
+}
-- 
1.7.6




More information about the Open-scap-list mailing list