components/openscap/patches/zone_file_fix_opt.c.patch
author Jacob Varughese <jacob.varughese@oracle.com>
Tue, 07 Oct 2014 16:44:00 -0700
branchs11-update
changeset 3373 9de01e7a073b
permissions -rw-r--r--
19262735 The file probe needs to be zone aware 19173594 oscap crashes when compliance is run 19559867 compliance fails when no network interface are defined

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);
 }