components/openscap/patches/zone_file_fix_opt.c.patch
author Petr Nyc <Petr.Nyc@Oracle.COM>
Wed, 03 Jun 2015 01:43:21 -0700
branchs11u2-sru
changeset 4397 e26fa37faea0
parent 3380 ab1cb904871a
permissions -rw-r--r--
Added tag 0.175.2.12.0.1.0, S11.2SRU12.1 for changeset 8a9e2a2ea8c6

This patch fixes an issue with file probe on solaris. The file probe currently
 is not zone aware and so descends into non-global zones from the global-zone.
Fix prevents file probe traversal into non-global zones  from the global zone,
 when local is specified for recursion.

This patch has not been contributed upstream, but is planned to be submitted by
 2014-Oct-15.
--- openscap-1.0.0/src/OVAL/probes/oval_fts.c.~2~	2014-07-24 10:53:15.269589073 -0700
+++ openscap-1.0.0/src/OVAL/probes/oval_fts.c	2014-07-24 11:02:30.267608422 -0700
@@ -45,6 +45,8 @@
 #if defined(__SVR4) && defined(__sun)
 #include "fts_sun.h"
 #include <sys/mntent.h>
+#include <libzonecfg.h>
+#include <sys/avl.h>
 #else
 #include <fts.h>
 #endif
@@ -138,6 +140,13 @@
 #define MNTTYPE_PROC	"proc"
 #endif
 
+typedef struct zone_path {
+	avl_node_t avl_link_next;
+	char zpath[MAXPATHLEN];
+} zone_path_t;
+static avl_tree_t avl_tree_list;
+
+
 static bool valid_remote_fs(char *fstype)
 {
 	if (strcmp(fstype, MNTTYPE_NFS) == 0 ||
@@ -160,6 +169,85 @@
 		return (false);
 	return (true);
 }
+
+/* function to compare two avl nodes in the avl tree */
+static int compare_zoneroot(const void *entry1, const void *entry2)
+{
+	zone_path_t *t1, *t2;
+	int comp;
+
+	t1 = (zone_path_t *)entry1;
+	t2 = (zone_path_t *)entry2;
+	if ((comp = strcmp(t1->zpath, t2->zpath)) == 0) {
+		return (0);
+	}
+	return (comp > 0 ? 1 : -1);
+}
+
+int load_zones_path_list()
+{
+	FILE *cookie;
+	char *name;
+	zone_state_t state_num;
+	zone_path_t *temp = NULL;
+	avl_index_t where;
+	char rpath[MAXPATHLEN];
+
+	cookie = setzoneent();
+	if (getzoneid() != GLOBAL_ZONEID)
+		return (0);
+	avl_create(&avl_tree_list, compare_zoneroot,
+	    sizeof(zone_path_t), offsetof(zone_path_t, avl_link_next));
+	while ((name = getzoneent(cookie)) != NULL) {
+		if (strcmp(name, "global") == 0)
+			continue;
+		if (zone_get_state(name, &state_num) != Z_OK) {
+			dE("Could not get zone state for %s\n", name);
+			continue;
+		} else if (state_num > ZONE_STATE_CONFIGURED) {
+			temp = malloc(sizeof(zone_path_t));
+			if (temp == NULL) {
+				dE("Memory alloc failed\n");
+				return(1);
+			}
+			if (zone_get_zonepath(name, rpath,
+			    sizeof(rpath)) != Z_OK) {
+				dE("Could not get zone path for %s\n",
+				    name);
+				continue;
+			}
+			if (realpath(rpath, temp->zpath) != NULL)
+				avl_add(&avl_tree_list, temp);
+		}
+	}
+	endzoneent(cookie);
+	return (0);
+}
+
+static void free_zones_path_list()
+{
+	zone_path_t *temp;
+	void* cookie = NULL;
+
+	while ((temp = avl_destroy_nodes(&avl_tree_list, &cookie)) != NULL) {
+		free(temp);
+	}
+	avl_destroy(&avl_tree_list);
+}
+
+static bool valid_local_zone(char *path)
+{
+	zone_path_t temp;
+	avl_index_t where;
+	
+	strlcpy(temp.zpath, path, sizeof(temp.zpath));
+	if (avl_find(&avl_tree_list, &temp, &where) != NULL)
+		return (true);
+
+	return (false);
+}
+
+
 #endif
 
 static bool OVAL_FTS_localp(OVAL_FTS *ofts, const char *path, void *id)
@@ -168,9 +256,11 @@
 	if (id != NULL && (*(char*)id) != '\0') {
 		/* if not a valid local fs skip */
 		if (valid_local_fs((char*)id)) {
-			/* if recurse is local , skip remote fs */
+			/* if recurse is local , skip remote fs 
+			   and non-global zones */
 			if (ofts->filesystem == OVAL_RECURSE_FS_LOCAL) {
-				return (!valid_remote_fs((char*)id));
+				return (!(valid_remote_fs((char*)id) ||
+				    valid_local_zone(path)));
 			}
 			return (true);
 		}
@@ -179,9 +269,11 @@
 		/* id was not set, because fts_read failed to stat the node */
 		struct stat sb;
 		if ((stat(path, &sb) == 0) && (valid_local_fs(sb.st_fstype))) {
-			/* if recurse is local , skip remote fs */
+			/* if recurse is local , skip remote fs
+			   and non-global zones */
 			if (ofts->filesystem == OVAL_RECURSE_FS_LOCAL) {
-				return (!valid_remote_fs(sb.st_fstype));
+				return (!(valid_remote_fs(sb.st_fstype) ||
+				    valid_local_zone(path)));
 			}
 			return (true);
 		}
@@ -793,6 +884,12 @@
 		ofts->ofts_sfilepath = SEXP_ref(filepath);
 	}
 
+#if defined(__SVR4) && defined(__sun)
+	if (load_zones_path_list() != 0) {
+		dE("Failed to load zones path info. Recursing non-global zones.");
+		free_zones_path_list();
+	}
+#endif
 	return (ofts);
 }
 
@@ -1249,6 +1346,9 @@
 	fsdev_free(ofts->localdevs);
 
 	OVAL_FTS_free(ofts);
+#if defined(__SVR4) && defined(__sun)
+	free_zones_path_list();
+#endif
 
 	return (0);
 }