Merge "Make libselinux_bindgen visible to all Virtualization targets"
diff --git a/README.md b/README.md
index 529b7e4..c272ce8 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,9 @@
 # For Python and Ruby bindings
 dnf install \
     python3-devel \
+    python3-pip \
+    python3-setuptools \
+    python3-wheel \
     ruby-devel \
     swig
 ```
@@ -92,6 +95,9 @@
 # For Python and Ruby bindings
 apt-get install --no-install-recommends --no-install-suggests \
     python3-dev \
+    python3-pip \
+    python3-setuptools \
+    python3-wheel \
     ruby-dev \
     swig
 ```
@@ -102,7 +108,7 @@
 
     make DESTDIR=~/obj install install-rubywrap install-pywrap
 
-On Debian `PYTHON_SETUP_ARGS=--install-layout=deb` needs to be set when installing the python wrappers in order to create the correct python directory structure.
+On Debian `PYTHON_SETUP_ARGS='--install-option "--install-layout=deb"'` needs to be set when installing the python wrappers in order to create the correct python directory structure.
 
 To run tests with the built libraries and programs, several paths (relative to `$DESTDIR`) need to be added to variables `$LD_LIBRARY_PATH`, `$PATH` and `$PYTHONPATH`.
 This can be done using [./scripts/env_use_destdir](./scripts/env_use_destdir):
diff --git a/VERSION b/VERSION
index 2f4b607..0395819 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/checkpolicy/VERSION b/checkpolicy/VERSION
index 2f4b607..0395819 100644
--- a/checkpolicy/VERSION
+++ b/checkpolicy/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 926ce72..48c3126 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -1148,12 +1148,11 @@
 			FGETS(ans, sizeof(ans), stdin);
 			ans[strlen(ans) - 1] = 0;
 
-			name = malloc((strlen(ans) + 1) * sizeof(char));
+			name = strdup(ans);
 			if (name == NULL) {
-				fprintf(stderr, "couldn't malloc string.\n");
+				fprintf(stderr, "couldn't strdup string.\n");
 				break;
 			}
-			strcpy(name, ans);
 
 			printf("state? ");
 			FGETS(ans, sizeof(ans), stdin);
@@ -1296,12 +1295,11 @@
 			FGETS(ans, sizeof(ans), stdin);
 			ans[strlen(ans) - 1] = 0;
 
-			name = malloc((strlen(ans) + 1) * sizeof(char));
+			name = strdup(ans);
 			if (!name) {
-				fprintf(stderr, "couldn't malloc string.\n");
+				fprintf(stderr, "couldn't strdup string.\n");
 				break;
 			}
-			strcpy(name, ans);
 
 			printf("port? ");
 			FGETS(ans, sizeof(ans), stdin);
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 54bb304..c2ae7fe 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -117,12 +117,11 @@
 	char *newid = 0;
 	int error;
 
-	newid = (char *)malloc(strlen(id) + 1);
+	newid = strdup(id);
 	if (!newid) {
 		yyerror("out of memory");
 		return -1;
 	}
-	strcpy(newid, id);
 	if (push)
 		error = queue_push(id_queue, (queue_element_t) newid);
 	else
@@ -1417,7 +1416,7 @@
 	if (!type->bounds)
 		type->bounds = bounds->s.value;
 	else if (type->bounds != bounds->s.value) {
-		yyerror2("type %s has inconsistent master {%s,%s}",
+		yyerror2("type %s has inconsistent bounds %s/%s",
 			 type_id,
 			 policydbp->p_type_val_to_name[type->bounds - 1],
 			 policydbp->p_type_val_to_name[bounds->s.value - 1]);
@@ -2209,7 +2208,7 @@
 	xperms = calloc(1, sizeof(av_extended_perms_t));
 	if (!xperms) {
 		yyerror("out of memory");
-		return - 1;
+		return -1;
 	}
 
 	r = rangelist;
@@ -2246,7 +2245,7 @@
 	xperms = calloc(1, sizeof(av_extended_perms_t));
 	if (!xperms) {
 		yyerror("out of memory");
-		return - 1;
+		return -1;
 	}
 
 	r = rangelist;
@@ -2290,7 +2289,7 @@
 	xperms = calloc(1, sizeof(av_extended_perms_t));
 	if (!xperms) {
 		yyerror("out of memory");
-		return - 1;
+		return -1;
 	}
 
 	r = rangelist;
@@ -2353,11 +2352,11 @@
 	dest->flags = src->flags;
 	if (type_set_cpy(&dest->stypes, &src->stypes)) {
 		yyerror("out of memory");
-		return - 1;
+		return -1;
 	}
 	if (type_set_cpy(&dest->ttypes, &src->ttypes)) {
 		yyerror("out of memory");
-		return - 1;
+		return -1;
 	}
 	dest->line = src->line;
 	dest->source_filename = strdup(source_file);
diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c
index 8ddefb0..36a3362 100644
--- a/checkpolicy/test/dispol.c
+++ b/checkpolicy/test/dispol.c
@@ -486,12 +486,11 @@
 			}
 			ans[strlen(ans) - 1] = 0;
 
-			name = malloc((strlen(ans) + 1) * sizeof(char));
+			name = strdup(ans);
 			if (name == NULL) {
-				fprintf(stderr, "couldn't malloc string.\n");
+				fprintf(stderr, "couldn't strdup string.\n");
 				break;
 			}
-			strcpy(name, ans);
 
 			printf("state? ");
 			if (fgets(ans, sizeof(ans), stdin) == NULL) {
diff --git a/dbus/VERSION b/dbus/VERSION
index 2f4b607..0395819 100644
--- a/dbus/VERSION
+++ b/dbus/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/gui/VERSION b/gui/VERSION
index 2f4b607..0395819 100644
--- a/gui/VERSION
+++ b/gui/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/gui/polgengui.py b/gui/polgengui.py
index 7a3ecd5..16116ba 100644
--- a/gui/polgengui.py
+++ b/gui/polgengui.py
@@ -481,7 +481,7 @@
             my_policy = sepolicy.generate.policy(self.get_name(), self.get_type())
 
             iter = self.boolean_store.get_iter_first()
-            while(iter):
+            while iter:
                 my_policy.add_boolean(self.boolean_store.get_value(iter, 0), self.boolean_store.get_value(iter, 1))
                 iter = self.boolean_store.iter_next(iter)
 
@@ -527,7 +527,7 @@
             my_policy.set_out_udp(self.out_udp_all_checkbutton.get_active(), self.out_udp_entry.get_text())
 
             iter = self.store.get_iter_first()
-            while(iter):
+            while iter:
                 if self.store.get_value(iter, 1) == FILE:
                     my_policy.add_file(self.store.get_value(iter, 0))
                 else:
diff --git a/libselinux/VERSION b/libselinux/VERSION
index 2f4b607..0395819 100644
--- a/libselinux/VERSION
+++ b/libselinux/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index dc28483..70ba063 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -187,7 +187,7 @@
 	ln -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET)
 
 install-pywrap: pywrap
-	$(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` $(PYTHON_SETUP_ARGS)
+	$(PYTHON) -m pip install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR) --ignore-installed --no-deps` $(PYTHON_SETUP_ARGS) .
 	install -m 644 $(SWIGPYOUT) $(DESTDIR)$(PYTHONLIBDIR)/selinux/__init__.py
 	ln -sf --relative $(DESTDIR)$(PYTHONLIBDIR)/selinux/_selinux$(PYCEXT) $(DESTDIR)$(PYTHONLIBDIR)/_selinux$(PYCEXT)
 
diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c
index 44a9a34..ba1a66e 100644
--- a/libselinux/src/audit2why.c
+++ b/libselinux/src/audit2why.c
@@ -191,7 +191,7 @@
 
 static int __policy_init(const char *init_path)
 {
-	FILE *fp;
+	FILE *fp = NULL;
 	const char *curpolicy;
 	char errormsg[PATH_MAX+1024+20];
 	struct sepol_policy_file *pf = NULL;
@@ -235,18 +235,17 @@
 		snprintf(errormsg, sizeof(errormsg), 
 			 "policydb_init failed: %m\n");
 		PyErr_SetString( PyExc_RuntimeError, errormsg);
-		fclose(fp);
-		return 1;
+		goto err;
 	}
 	sepol_policy_file_set_fp(pf, fp);	
 	if (sepol_policydb_read(avc->policydb, pf)) {
 		snprintf(errormsg, sizeof(errormsg), 
 			 "invalid binary policy %s\n", curpolicy);
 		PyErr_SetString( PyExc_ValueError, errormsg);
-		fclose(fp);
-		return 1;
+		goto err;
 	}
 	fclose(fp);
+	fp = NULL;
 	sepol_set_policydb(&avc->policydb->p);
 	avc->handle = sepol_handle_create();
 	/* Turn off messages */
@@ -256,13 +255,13 @@
 			      avc->policydb, &cnt);
 	if (rc < 0) {
 		PyErr_SetString( PyExc_RuntimeError, "unable to get bool count\n");
-		return 1;
+		goto err;
 	}
 
 	boollist = calloc(cnt, sizeof(*boollist));
 	if (!boollist) {
 		PyErr_SetString( PyExc_MemoryError, "Out of memory\n");
-		return 1;
+		goto err;
 	}
 
 	sepol_bool_iterate(avc->handle, avc->policydb,
@@ -273,11 +272,26 @@
 	rc = sepol_sidtab_init(&sidtab);
 	if (rc < 0) {
 		PyErr_SetString( PyExc_RuntimeError, "unable to init sidtab\n");
-		free(boollist);
-		return 1;
+		goto err;
 	}
 	sepol_set_sidtab(&sidtab);
 	return 0;
+
+err:
+	if (boollist)
+		free(boollist);
+	if (avc){
+		if (avc->handle)
+			sepol_handle_destroy(avc->handle);
+		if (avc->policydb)
+			sepol_policydb_free(avc->policydb);
+		free(avc);
+	}
+	if (pf)
+		sepol_policy_file_free(pf);
+	if (fp)
+		fclose(fp);
+	return 1;
 }
 
 static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) {
diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c
index 71a1357..ffc663e 100644
--- a/libselinux/src/avc_internal.c
+++ b/libselinux/src/avc_internal.c
@@ -51,7 +51,6 @@
 int avc_running = 0;
 int avc_enforcing = 1;
 int avc_setenforce = 0;
-int avc_netlink_trouble = 0;
 
 /* process setenforce events for netlink and sestatus */
 int avc_process_setenforce(int enforcing)
@@ -295,7 +294,6 @@
 
 	close(fd);
 	fd = -1;
-	avc_netlink_trouble = 1;
 	avc_log(SELINUX_ERROR,
 		"%s:  netlink thread: errors encountered, terminating\n",
 		avc_prefix);
diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h
index a9a4aa0..54f0ce2 100644
--- a/libselinux/src/avc_internal.h
+++ b/libselinux/src/avc_internal.h
@@ -180,7 +180,4 @@
 			 security_class_t tclass, access_vector_t perms,
 			 uint32_t seqno, uint32_t enable) ;
 
-/* netlink kernel message code */
-extern int avc_netlink_trouble ;
-
 #endif				/* _SELINUX_AVC_INTERNAL_H_ */
diff --git a/libselinux/src/booleans.c b/libselinux/src/booleans.c
index ef1f64a..e34b39f 100644
--- a/libselinux/src/booleans.c
+++ b/libselinux/src/booleans.c
@@ -7,7 +7,6 @@
 
 #ifndef DISABLE_BOOL
 
-#include <assert.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -132,7 +131,8 @@
 			ptr++;
 		*ptr = '\0';
 
-		sub = strdup(dst);
+		if (!strchr(dst, '/'))
+			sub = strdup(dst);
 
 		break;
 	}
@@ -147,12 +147,12 @@
 static int bool_open(const char *name, int flag) {
 	char *fname = NULL;
 	char *alt_name = NULL;
-	int len;
+	size_t len;
 	int fd = -1;
 	int ret;
 	char *ptr;
 
-	if (!name) {
+	if (!name || strchr(name, '/')) {
 		errno = EINVAL;
 		return -1;
 	}
@@ -164,9 +164,8 @@
 		return -1;
 
 	ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name);
-	if (ret < 0)
+	if (ret < 0 || (size_t)ret >= len)
 		goto out;
-	assert(ret < len);
 
 	fd = open(fname, flag);
 	if (fd >= 0 || errno != ENOENT)
@@ -184,9 +183,8 @@
 	fname = ptr;
 
 	ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, alt_name);
-	if (ret < 0)
+	if (ret < 0 || (size_t)ret >= len)
 		goto out;
-	assert(ret < len);
 
 	fd = open(fname, flag);
 out:
diff --git a/libselinux/src/context.c b/libselinux/src/context.c
index 9dddbc5..33c48ef 100644
--- a/libselinux/src/context.c
+++ b/libselinux/src/context.c
@@ -68,11 +68,9 @@
 			for (p = tok; *p; p++) {	/* empty */
 			}
 		}
-		n->component[i] = (char *)malloc(p - tok + 1);
+		n->component[i] = strndup(tok, p - tok);
 		if (n->component[i] == 0)
 			goto err;
-		strncpy(n->component[i], tok, p - tok);
-		n->component[i][p - tok] = '\0';
 		tok = *p ? p + 1 : p;
 	}
 	return result;
@@ -149,19 +147,18 @@
 	char *t = NULL;
 	const char *p;
 	if (str) {
-		t = (char *)malloc(strlen(str) + 1);
-		if (!t) {
-			return -1;
-		}
 		for (p = str; *p; p++) {
 			if (*p == '\t' || *p == '\n' || *p == '\r' ||
 			    ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) {
-				free(t);
 				errno = EINVAL;
 				return -1;
 			}
 		}
-		strcpy(t, str);
+
+		t = strdup(str);
+		if (!t) {
+			return -1;
+		}
 	}
 	conditional_free(&n->component[idx]);
 	n->component[idx] = t;
diff --git a/libselinux/src/get_default_type.c b/libselinux/src/get_default_type.c
index dd7b5d7..766ea4b 100644
--- a/libselinux/src/get_default_type.c
+++ b/libselinux/src/get_default_type.c
@@ -62,10 +62,9 @@
 		return -1;
 	}
 
-	t = malloc(strlen(buf) - len);
+	t = strndup(ptr, strlen(buf) - len - 1);
 	if (!t)
 		return -1;
-	strcpy(t, ptr);
 	*type = t;
 	return 0;
 }
diff --git a/libselinux/src/get_initial_context.c b/libselinux/src/get_initial_context.c
index 97ae3dc..0f25ba3 100644
--- a/libselinux/src/get_initial_context.c
+++ b/libselinux/src/get_initial_context.c
@@ -23,8 +23,17 @@
 		return -1;
 	}
 
-	snprintf(path, sizeof path, "%s%s%s", 
-		 selinux_mnt, SELINUX_INITCON_DIR, name);
+	if (strchr(name, '/')) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	ret = snprintf(path, sizeof path, "%s%s%s", selinux_mnt, SELINUX_INITCON_DIR, name);
+	if (ret < 0 || (size_t)ret >= sizeof path) {
+		errno = EOVERFLOW;
+		return -1;
+	}
+
 	fd = open(path, O_RDONLY | O_CLOEXEC);
 	if (fd < 0)
 		return -1;
diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c
index 94c05c6..3f80303 100644
--- a/libselinux/src/label_db.c
+++ b/libselinux/src/label_db.c
@@ -31,7 +31,7 @@
  * For example:
  * ----------------------------------------
  * #
- * # It is an example specfile for database obejcts
+ * # It is an example specfile for database objects
  * #
  * db_database  template1           system_u:object_r:sepgsql_db_t:s0
  *
@@ -293,6 +293,11 @@
 		return NULL;
 	}
 	rec->spec_file = strdup(path);
+	if (!rec->spec_file) {
+                free(catalog);
+                fclose(filp);
+                return NULL;
+	}
 
 	/*
 	 * Parse for each lines
@@ -322,18 +327,19 @@
 		if (process_line(path, line_buf, ++line_num, catalog) < 0)
 			goto out_error;
 	}
-	free(line_buf);
 
 	if (digest_add_specfile(rec->digest, filp, NULL, sb.st_size, path) < 0)
 		goto out_error;
 
 	digest_gen_hash(rec->digest);
 
+	free(line_buf);
 	fclose(filp);
 
 	return catalog;
 
 out_error:
+	free(line_buf);
 	for (i = 0; i < catalog->nspec; i++) {
 		spec_t	       *spec = &catalog->specs[i];
 
diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
index ea78a23..bf2da08 100644
--- a/libselinux/src/matchpathcon.c
+++ b/libselinux/src/matchpathcon.c
@@ -215,10 +215,9 @@
 			if (ret < 0 || sb.st_ino != ino) {
 				fl->specind = specind;
 				free(fl->file);
-				fl->file = malloc(strlen(file) + 1);
+				fl->file = strdup(file);
 				if (!fl->file)
 					goto oom;
-				strcpy(fl->file, file);
 				return fl->specind;
 
 			}
@@ -232,10 +231,9 @@
 			     __FUNCTION__, file, fl->file,
 			     con_array[fl->specind]);
 			free(fl->file);
-			fl->file = malloc(strlen(file) + 1);
+			fl->file = strdup(file);
 			if (!fl->file)
 				goto oom;
-			strcpy(fl->file, file);
 			return fl->specind;
 		}
 
@@ -248,10 +246,9 @@
 		goto oom;
 	fl->ino = ino;
 	fl->specind = specind;
-	fl->file = malloc(strlen(file) + 1);
+	fl->file = strdup(file);
 	if (!fl->file)
 		goto oom_freefl;
-	strcpy(fl->file, file);
 	fl->next = prevfl->next;
 	prevfl->next = fl;
 	return fl->specind;
diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c
index 73987d9..16df679 100644
--- a/libselinux/src/regex.c
+++ b/libselinux/src/regex.c
@@ -60,11 +60,13 @@
 
 struct regex_data {
 	pcre2_code *regex; /* compiled regular expression */
+#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
 	/*
 	 * match data block required for the compiled
 	 * pattern in pcre2
 	 */
 	pcre2_match_data *match_data;
+#endif
 	pthread_mutex_t match_mutex;
 };
 
@@ -84,11 +86,13 @@
 		goto err;
 	}
 
+#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
 	(*regex)->match_data =
 	    pcre2_match_data_create_from_pattern((*regex)->regex, NULL);
 	if (!(*regex)->match_data) {
 		goto err;
 	}
+#endif
 	return 0;
 
 err:
@@ -138,10 +142,12 @@
 		if (rc != 1)
 			goto err;
 
+#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
 		(*regex)->match_data =
 		    pcre2_match_data_create_from_pattern((*regex)->regex, NULL);
 		if (!(*regex)->match_data)
 			goto err;
+#endif
 
 		*regex_compiled = true;
 	}
@@ -167,7 +173,7 @@
 	PCRE2_UCHAR *bytes = NULL;
 
 	if (do_write_precompregex) {
-		/* encode the patter for serialization */
+		/* encode the pattern for serialization */
 		rc = pcre2_serialize_encode((const pcre2_code **)&regex->regex,
 					    1, &bytes, &serialized_size, NULL);
 		if (rc != 1) {
@@ -203,8 +209,12 @@
 	if (regex) {
 		if (regex->regex)
 			pcre2_code_free(regex->regex);
+
+#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
 		if (regex->match_data)
 			pcre2_match_data_free(regex->match_data);
+#endif
+
 		__pthread_mutex_destroy(&regex->match_mutex);
 		free(regex);
 	}
@@ -213,10 +223,30 @@
 int regex_match(struct regex_data *regex, char const *subject, int partial)
 {
 	int rc;
+	pcre2_match_data *match_data;
 	__pthread_mutex_lock(&regex->match_mutex);
+
+#ifdef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
+	match_data = pcre2_match_data_create_from_pattern(
+	    regex->regex, NULL);
+	if (match_data == NULL) {
+		__pthread_mutex_unlock(&regex->match_mutex);
+		return REGEX_ERROR;
+	}
+#else
+	match_data = regex->match_data;
+#endif
+
 	rc = pcre2_match(
 	    regex->regex, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0,
-	    partial ? PCRE2_PARTIAL_SOFT : 0, regex->match_data, NULL);
+	    partial ? PCRE2_PARTIAL_SOFT : 0, match_data, NULL);
+
+#ifdef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
+	// pcre2_match allocates heap and it won't be freed until
+	// pcre2_match_data_free, resulting in heap overhead.
+	pcre2_match_data_free(match_data);
+#endif
+
 	__pthread_mutex_unlock(&regex->match_mutex);
 	if (rc > 0)
 		return REGEX_MATCH;
@@ -257,6 +287,9 @@
 {
 	struct regex_data *regex_data =
 		(struct regex_data *)calloc(1, sizeof(struct regex_data));
+	if (!regex_data)
+		return NULL;
+
 	__pthread_mutex_init(&regex_data->match_mutex, NULL);
 	return regex_data;
 }
diff --git a/libselinux/src/sestatus.c b/libselinux/src/sestatus.c
index 89c1f62..fbe6430 100644
--- a/libselinux/src/sestatus.c
+++ b/libselinux/src/sestatus.c
@@ -343,7 +343,6 @@
 		if (avc_using_threads)
 		{
 			fallback_netlink_thread = avc_create_thread(&avc_netlink_loop);
-			avc_netlink_trouble = 0;
 		}
 
 		fallback_sequence = 0;
diff --git a/libselinux/src/setup.py b/libselinux/src/setup.py
index 6cbe3a0..5594d5f 100644
--- a/libselinux/src/setup.py
+++ b/libselinux/src/setup.py
@@ -4,7 +4,7 @@
 
 setup(
     name="selinux",
-    version="3.4",
+    version="3.5-rc2",
     description="SELinux python 3 bindings",
     author="SELinux Project",
     author_email="[email protected]",
diff --git a/libselinux/src/sha1.c b/libselinux/src/sha1.c
index a848467..9d51e04 100644
--- a/libselinux/src/sha1.c
+++ b/libselinux/src/sha1.c
@@ -11,7 +11,7 @@
 //  Modified to:
 //    - stop symbols being exported for libselinux shared library - October 2015
 //								       Richard Haines <[email protected]>
-//    - Not cast the workspace from a byte array to a CHAR64LONG16 due to alignment isses.
+//    - Not cast the workspace from a byte array to a CHAR64LONG16 due to alignment issues.
 //      Fixes:
 //        sha1.c:73:33: error: cast from 'uint8_t *' (aka 'unsigned char *') to 'CHAR64LONG16 *' increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 //             CHAR64LONG16*       block = (CHAR64LONG16*) workspace;
diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c
index 592410e..d2237d1 100644
--- a/libselinux/src/stringrep.c
+++ b/libselinux/src/stringrep.c
@@ -82,7 +82,10 @@
 		goto err2;
 
 	/* load up class index */
-	snprintf(path, sizeof path, "%s/class/%s/index", selinux_mnt,s);
+	ret = snprintf(path, sizeof path, "%s/class/%s/index", selinux_mnt,s);
+	if (ret < 0 || (size_t)ret >= sizeof path)
+		goto err3;
+
 	fd = open(path, O_RDONLY | O_CLOEXEC);
 	if (fd < 0)
 		goto err3;
@@ -97,7 +100,10 @@
 		goto err3;
 
 	/* load up permission indices */
-	snprintf(path, sizeof path, "%s/class/%s/perms",selinux_mnt,s);
+	ret = snprintf(path, sizeof path, "%s/class/%s/perms",selinux_mnt,s);
+	if (ret < 0 || (size_t)ret >= sizeof path)
+		goto err3;
+
 	dir = opendir(path);
 	if (dir == NULL)
 		goto err3;
@@ -107,7 +113,10 @@
 		unsigned int value;
 		struct stat m;
 
-		snprintf(path, sizeof path, "%s/class/%s/perms/%s", selinux_mnt,s,dentry->d_name);
+		ret = snprintf(path, sizeof path, "%s/class/%s/perms/%s", selinux_mnt,s,dentry->d_name);
+		if (ret < 0 || (size_t)ret >= sizeof path)
+			goto err4;
+
 		fd = open(path, O_RDONLY | O_CLOEXEC);
 		if (fd < 0)
 			goto err4;
diff --git a/libselinux/utils/selabel_lookup_best_match.c b/libselinux/utils/selabel_lookup_best_match.c
index a4af067..e816c04 100644
--- a/libselinux/utils/selabel_lookup_best_match.c
+++ b/libselinux/utils/selabel_lookup_best_match.c
@@ -30,7 +30,7 @@
 	exit(1);
 }
 
-static mode_t string_to_mode(char *s)
+static mode_t string_to_mode(const char *s)
 {
 	switch (s[0]) {
 	case 'b':
@@ -53,7 +53,7 @@
 
 int main(int argc, char **argv)
 {
-	int raw = 0, mode = 0, rc, opt, i, num_links, string_len;
+	int raw = 0, mode = 0, rc, opt, i, num_links;
 	char *validate = NULL, *path = NULL, *context = NULL, *file = NULL;
 	char **links = NULL;
 
@@ -101,13 +101,11 @@
 		}
 
 		for (i = optind, num_links = 0; i < argc; i++, num_links++) {
-			string_len = strlen(argv[i]) + 1;
-			links[num_links] = malloc(string_len);
+			links[num_links] = strdup(argv[i]);
 			if (!links[num_links]) {
-				fprintf(stderr, "ERROR: malloc failed.\n");
+				fprintf(stderr, "ERROR: strdup failed.\n");
 				exit(1);
 			}
-			strcpy(links[num_links], argv[i]);
 		}
 	}
 
diff --git a/libsemanage/VERSION b/libsemanage/VERSION
index 2f4b607..0395819 100644
--- a/libsemanage/VERSION
+++ b/libsemanage/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 14a0957..27c5d34 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -2400,7 +2400,7 @@
 
 /* Sorts file contexts from least specific to most specific.
  * A bucket linked list is passed in.  Upon completion,
- * there is only one bucket (pointed to by master) that 
+ * there is only one bucket (pointed to by "main") that
  * contains a linked list of all the file contexts in sorted order.
  * Explanation of the algorithm:
  *  This is a stable implementation of an iterative merge sort.
@@ -2411,15 +2411,15 @@
  *  Buckets are merged until there is only one bucket left, 
  *   containing the list of file contexts, sorted.
  */
-static void semanage_fc_merge_sort(semanage_file_context_bucket_t * master)
+static void semanage_fc_merge_sort(semanage_file_context_bucket_t * main)
 {
 	semanage_file_context_bucket_t *current;
 	semanage_file_context_bucket_t *temp;
 
-	/* Loop until master is the only bucket left.
-	 * When we stop master contains the sorted list. */
-	while (master->next) {
-		current = master;
+	/* Loop until "main" is the only bucket left.
+	 * When we stop "main" contains the sorted list. */
+	while (main->next) {
+		current = main;
 
 		/* Merge buckets two-by-two. 
 		 * If there is an odd number of buckets, the last 
@@ -2547,7 +2547,7 @@
 	semanage_file_context_node_t *temp;
 	semanage_file_context_node_t *head;
 	semanage_file_context_node_t *current;
-	semanage_file_context_bucket_t *master;
+	semanage_file_context_bucket_t *main;
 	semanage_file_context_bucket_t *bcurrent;
 
 	i = 0;
@@ -2746,9 +2746,9 @@
 
 	/* Create the bucket linked list from the node linked list. */
 	current = head->next;
-	bcurrent = master = (semanage_file_context_bucket_t *)
+	bcurrent = main = (semanage_file_context_bucket_t *)
 	    calloc(1, sizeof(semanage_file_context_bucket_t));
-	if (!master) {
+	if (!main) {
 		ERR(sh, "Failure allocating memory.");
 		semanage_fc_node_list_destroy(head);
 		return -1;
@@ -2772,7 +2772,7 @@
 			    calloc(1, sizeof(semanage_file_context_bucket_t));
 			if (!(bcurrent->next)) {
 				ERR(sh, "Failure allocating memory.");
-				semanage_fc_bucket_list_destroy(master);
+				semanage_fc_bucket_list_destroy(main);
 				return -1;
 			}
 
@@ -2781,14 +2781,14 @@
 	}
 
 	/* Sort the bucket list. */
-	semanage_fc_merge_sort(master);
+	semanage_fc_merge_sort(main);
 
 	/* First, calculate how much space we'll need for 
 	 * the newly sorted block of data.  (We don't just
 	 * use buf_len for this because we have extracted
 	 * comments and whitespace.) */
 	i = 0;
-	current = master->data;
+	current = main->data;
 	while (current) {
 		i += current->path_len + 1;	/* +1 for a tab */
 		if (current->file_type) {
@@ -2803,14 +2803,14 @@
 	*sorted_buf = calloc(i, sizeof(char));
 	if (!*sorted_buf) {
 		ERR(sh, "Failure allocating memory.");
-		semanage_fc_bucket_list_destroy(master);
+		semanage_fc_bucket_list_destroy(main);
 		return -1;
 	}
 	*sorted_buf_len = i;
 
 	/* Output the sorted semanage_file_context linked list to the char buffer. */
 	sorted_buf_pos = *sorted_buf;
-	current = master->data;
+	current = main->data;
 	while (current) {
 		/* Output the path. */
 		i = current->path_len + 1;	/* +1 for tab */
@@ -2834,7 +2834,7 @@
 	}
 
 	/* Clean up. */
-	semanage_fc_bucket_list_destroy(master);
+	semanage_fc_bucket_list_destroy(main);
 
 	/* Sanity check. */
 	sorted_buf_pos++;
diff --git a/libsepol/VERSION b/libsepol/VERSION
index 2f4b607..0395819 100644
--- a/libsepol/VERSION
+++ b/libsepol/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
index 11e572e..a7c66ea 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -1193,7 +1193,7 @@
 	struct cil_cat *c2 = (struct cil_cat *)d2;
 
 	if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) {
-		cil_log(CIL_ERR, "Category sets cannont be used in a category range\n");
+		cil_log(CIL_ERR, "Category sets cannot be used in a category range\n");
 		goto exit;
 	}
 
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index f5e22c9..d2bfdc8 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -778,7 +778,7 @@
 	class = (struct cil_class *)class_datum;
 	common = (struct cil_class *)common_datum;
 	if (class->common != NULL) {
-		cil_log(CIL_ERR, "class cannot be associeated with more than one common\n");
+		cil_log(CIL_ERR, "class cannot be associated with more than one common\n");
 		rc = SEPOL_ERR;
 		goto exit;
 	}
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index 63dffd9..73b72b5 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -591,16 +591,21 @@
 		class = pdb->class_val_to_struct[i];
 		if (!class) continue;
 		name = pdb->p_class_val_to_name[i];
-		sepol_printf(out, "class %s", name);
-		if (class->comkey) {
-			sepol_printf(out, " inherits %s", class->comkey);
-		}
 		perms = class_or_common_perms_to_str(&class->permissions);
-		if (perms) {
-			sepol_printf(out, " { %s }", perms);
-			free(perms);
+		/* Do not write empty classes, their declaration was alreedy
+		 * printed in write_class_decl_rules_to_conf() */
+		if (perms || class->comkey) {
+			sepol_printf(out, "class %s", name);
+			if (class->comkey) {
+				sepol_printf(out, " inherits %s", class->comkey);
+			}
+
+			if (perms) {
+				sepol_printf(out, " { %s }", perms);
+				free(perms);
+			}
+			sepol_printf(out, "\n");
 		}
-		sepol_printf(out, "\n");
 	}
 
 exit:
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index b900290..2b24d33 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -2330,7 +2330,7 @@
 	}
 
 	if (block->flags & AVRULE_OPTIONAL) {
-		// sensitivites in user statements in optionals do not have the
+		// sensitivities in user statements in optionals do not have the
 		// standard -1 offset
 		sens_offset = 0;
 	}
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 8a65df0..b79c19b 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -776,12 +776,11 @@
 		rc = -ENOMEM;
 		goto out;
 	}
-	key = malloc(strlen(OBJECT_R) + 1);
+	key = strdup(OBJECT_R);
 	if (!key) {
 		rc = -ENOMEM;
 		goto out_free_role;
 	}
-	strcpy(key, OBJECT_R);
 	rc = symtab_insert(p, SYM_ROLES, key, role,
 			   (p->policy_type ==
 			    POLICY_MOD ? SCOPE_REQ : SCOPE_DECL), 1,
diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c
index 521ea4f..469c14f 100644
--- a/libsepol/src/policydb_validate.c
+++ b/libsepol/src/policydb_validate.c
@@ -770,12 +770,20 @@
  * Functions to validate a kernel policydb
  */
 
-static int validate_avtab_key(const avtab_key_t *key, int conditional, validate_t flavors[])
+static int validate_avtab_key(const avtab_key_t *key, int conditional, const policydb_t *p, validate_t flavors[])
 {
-	if (validate_value(key->source_type, &flavors[SYM_TYPES]))
-		goto bad;
-	if (validate_value(key->target_type, &flavors[SYM_TYPES]))
-		goto bad;
+	if (p->policy_type == POLICY_KERN && key->specified & AVTAB_TYPE) {
+		if (validate_simpletype(key->source_type, p, flavors))
+			goto bad;
+		if (validate_simpletype(key->target_type, p, flavors))
+			goto bad;
+	} else {
+		if (validate_value(key->source_type, &flavors[SYM_TYPES]))
+			goto bad;
+		if (validate_value(key->target_type, &flavors[SYM_TYPES]))
+			goto bad;
+	}
+
 	if (validate_value(key->target_class, &flavors[SYM_CLASSES]))
 		goto bad;
 	switch (0xFFF & key->specified) {
@@ -821,7 +829,7 @@
 {
 	map_arg_t *margs = args;
 
-	if (validate_avtab_key(k, 0, margs->flavors))
+	if (validate_avtab_key(k, 0, margs->policy, margs->flavors))
 		return -1;
 
 	if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors))
@@ -845,13 +853,13 @@
 	return 0;
 }
 
-static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *cond_av, validate_t flavors[])
+static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *cond_av, const policydb_t *p, validate_t flavors[])
 {
 	const struct avtab_node *avtab_ptr;
 
 	for (; cond_av; cond_av = cond_av->next) {
 		for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) {
-			if (validate_avtab_key(&avtab_ptr->key, 1, flavors)) {
+			if (validate_avtab_key(&avtab_ptr->key, 1, p, flavors)) {
 				ERR(handle, "Invalid cond av list");
 				return -1;
 			}
@@ -996,9 +1004,9 @@
 	for (; cond; cond = cond->next) {
 		if (validate_cond_expr(handle, cond->expr, &flavors[SYM_BOOLS]))
 			goto bad;
-		if (validate_cond_av_list(handle, cond->true_list, flavors))
+		if (validate_cond_av_list(handle, cond->true_list, p, flavors))
 			goto bad;
-		if (validate_cond_av_list(handle, cond->false_list, flavors))
+		if (validate_cond_av_list(handle, cond->false_list, p, flavors))
 			goto bad;
 		if (validate_avrules(handle, cond->avtrue_list, 1, p, flavors))
 			goto bad;
diff --git a/libsepol/tests/Makefile b/libsepol/tests/Makefile
index a72c327..273373b 100644
--- a/libsepol/tests/Makefile
+++ b/libsepol/tests/Makefile
@@ -1,9 +1,24 @@
 ENV ?= env
-M4 ?= m4
+M4 ?= m4 -E -E
 MKDIR ?= mkdir
 EXE ?= libsepol-tests
 
-CFLAGS += -g3 -gdwarf-2 -O0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter -Werror
+CFLAGS += -g3 -gdwarf-2 -O0 \
+	-Werror -Wall -Wextra \
+	-Wfloat-equal \
+	-Wformat=2 \
+	-Winit-self \
+	-Wmissing-format-attribute \
+	-Wmissing-noreturn \
+	-Wmissing-prototypes \
+	-Wnull-dereference \
+	-Wpointer-arith \
+	-Wshadow \
+	-Wstrict-prototypes \
+	-Wundef \
+	-Wunused \
+	-Wwrite-strings \
+	-fno-common
 
 # Statically link libsepol on the assumption that we are going to
 # be testing internal functions.
diff --git a/libsepol/tests/libsepol-tests.c b/libsepol/tests/libsepol-tests.c
index 5ae6bed..968e3cc 100644
--- a/libsepol/tests/libsepol-tests.c
+++ b/libsepol/tests/libsepol-tests.c
@@ -24,6 +24,7 @@
 #include "test-expander.h"
 #include "test-deps.h"
 #include "test-downgrade.h"
+#include "test-neverallow.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -71,6 +72,7 @@
 	DECLARE_SUITE(expander);
 	DECLARE_SUITE(deps);
 	DECLARE_SUITE(downgrade);
+	DECLARE_SUITE(neverallow);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsepol/tests/policies/test-deps/base-metreq.conf b/libsepol/tests/policies/test-deps/base-metreq.conf
index b7528dd..d8e1f40 100644
--- a/libsepol/tests/policies/test-deps/base-metreq.conf
+++ b/libsepol/tests/policies/test-deps/base-metreq.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-deps/base-notmetreq.conf b/libsepol/tests/policies/test-deps/base-notmetreq.conf
index eee36dc..ecd92f6 100644
--- a/libsepol/tests/policies/test-deps/base-notmetreq.conf
+++ b/libsepol/tests/policies/test-deps/base-notmetreq.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class msg
 class msgq
 class shm
diff --git a/libsepol/tests/policies/test-deps/small-base.conf b/libsepol/tests/policies/test-deps/small-base.conf
index 98f49c2..848d174 100644
--- a/libsepol/tests/policies/test-deps/small-base.conf
+++ b/libsepol/tests/policies/test-deps/small-base.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-expander/alias-base.conf b/libsepol/tests/policies/test-expander/alias-base.conf
index b950039..3495592 100644
--- a/libsepol/tests/policies/test-expander/alias-base.conf
+++ b/libsepol/tests/policies/test-expander/alias-base.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-expander/role-base.conf b/libsepol/tests/policies/test-expander/role-base.conf
index 8e88b4b..a387c8c 100644
--- a/libsepol/tests/policies/test-expander/role-base.conf
+++ b/libsepol/tests/policies/test-expander/role-base.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-expander/small-base.conf b/libsepol/tests/policies/test-expander/small-base.conf
index 055ea05..ac180f3 100644
--- a/libsepol/tests/policies/test-expander/small-base.conf
+++ b/libsepol/tests/policies/test-expander/small-base.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-expander/user-base.conf b/libsepol/tests/policies/test-expander/user-base.conf
index b31ee8c..789a59a 100644
--- a/libsepol/tests/policies/test-expander/user-base.conf
+++ b/libsepol/tests/policies/test-expander/user-base.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-hooks/cmp_policy.conf b/libsepol/tests/policies/test-hooks/cmp_policy.conf
index 9082b33..3c510bc 100644
--- a/libsepol/tests/policies/test-hooks/cmp_policy.conf
+++ b/libsepol/tests/policies/test-hooks/cmp_policy.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-hooks/small-base.conf b/libsepol/tests/policies/test-hooks/small-base.conf
index 9082b33..3c510bc 100644
--- a/libsepol/tests/policies/test-hooks/small-base.conf
+++ b/libsepol/tests/policies/test-hooks/small-base.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-linker/small-base.conf b/libsepol/tests/policies/test-linker/small-base.conf
index 890ebbe..15ced45 100644
--- a/libsepol/tests/policies/test-linker/small-base.conf
+++ b/libsepol/tests/policies/test-linker/small-base.conf
@@ -33,7 +33,7 @@
 class unix_stream_socket
 class unix_dgram_socket
 
-# sysv-ipc-related clases
+# sysv-ipc-related classes
 class sem
 class msg
 class msgq
diff --git a/libsepol/tests/policies/test-neverallow/policy.conf b/libsepol/tests/policies/test-neverallow/policy.conf
new file mode 100644
index 0000000..67a1637
--- /dev/null
+++ b/libsepol/tests/policies/test-neverallow/policy.conf
@@ -0,0 +1,298 @@
+class process
+class blk_file
+class chr_file
+class dir
+class fifo_file
+class file
+class lnk_file
+class sock_file
+
+sid kernel
+sid security
+sid unlabeled
+sid file
+sid port
+sid netif
+sid netmsg
+sid node
+sid devnull
+
+class process { dyntransition transition }
+class file { getattr ioctl open read write }
+
+ifdef(`enable_mls',`
+sensitivity s0;
+dominance { s0 }
+category c0; category c1; category c2; category c3;
+category c4; category c5; category c6; category c7;
+category c8; category c9; category c10; category c11;
+category c12; category c13; category c14; category c15;
+category c16; category c17; category c18; category c19;
+category c20; category c21; category c22; category c23;
+
+level s0:c0.c23;
+
+mlsconstrain file { write } ( h1 dom h2 );
+')
+
+
+########################################
+#
+# Test start
+#
+########################################
+
+
+## Test 1 (basic)
+
+type test1_t;
+allow      test1_t test1_t : file { read write };
+neverallow test1_t test1_t : file read;
+
+
+## Test 2 (wildcard permission)
+
+type test2_t;
+allow      test2_t test2_t : file { read write };
+neverallow test2_t test2_t : file *;
+
+
+## Test 3 (complement permission)
+
+type test3_t;
+allow      test3_t test3_t : file { read write };
+neverallow test3_t test3_t : file ~{ write };
+
+
+## Test 4 (wildcard source)
+
+type test4_t;
+allow      test4_t test4_t : file { read write };
+neverallow *       test4_t : file read;
+
+
+## Test 5 (wildcard target)
+
+type test5_t;
+allow      test5_t test5_t : file { read write };
+neverallow test5_t *       : file read;
+
+
+## Test 6 (complement source)
+
+type test6_1_t;
+type test6_2_t;
+allow      { test6_1_t test6_2_t } { test6_1_t test6_2_t } : file { read write };
+neverallow ~{ test6_2_t }          test6_1_t               : file read;
+
+
+## Test 7 (complement target)
+
+type test7_1_t;
+type test7_2_t;
+allow      { test7_1_t test7_2_t } { test7_1_t test7_2_t } : file { read write };
+neverallow test7_1_t               ~{ test7_2_t }          : file read;
+
+
+## Test 8 (source attribute)
+
+attribute test8_a;
+type test8_t, test8_a;
+allow      test8_a test8_a : file read;
+allow      test8_t test8_t : file write;
+neverallow test8_a test8_t : file { read write };
+
+
+## Test 9 (target attribute)
+
+attribute test9_a;
+type test9_t, test9_a;
+allow      test9_a test9_a : file read;
+allow      test9_t test9_t : file write;
+neverallow test9_t test9_a : file { read write };
+
+
+## Test 10 (self)
+
+attribute test10_a;
+type test10_1_t, test10_a;
+type test10_2_t;
+allow      { test10_1_t test10_2_t } { test10_1_t test10_2_t } : file read;
+neverallow test10_a                  self                      : file *;
+
+
+## Test 11 (wildcard)
+
+type test11_t;
+allow      test11_t self : process *;
+neverallow *        *    : process *;
+
+
+## Test 12 (complement attributes)
+
+attribute test12_1_a;
+attribute test12_2_a;
+attribute test12_3_a;
+type test12_1_t, test12_1_a;
+type test12_2_t, test12_2_a;
+type test12_3_t, test12_3_a;
+allow     { test12_1_a test12_2_a test12_3_a } { test12_1_a test12_2_a test12_3_a } : file *;
+neverallow ~{ test12_1_a test12_2_t }          ~{ test12_3_a }                      : file getattr;
+neverallow ~{ test12_1_a }                     ~{ test12_2_a test12_3_t }           : file open;
+
+
+## Test 13 (excludes)
+
+attribute test13_1_a;
+attribute test13_2_a;
+attribute test13_3_a;
+type test13_1_t, test13_1_a;
+type test13_2_t, test13_2_a;
+type test13_3_t, test13_3_a;
+allow      { test13_1_a test13_2_a test13_3_a }                         { test13_1_a test13_2_a test13_3_a }                         : file { read write };
+neverallow { test13_1_a test13_2_a test13_3_a -test13_2_a -test13_3_t } { test13_1_a test13_2_a test13_3_a -test13_2_t -test13_3_a } : file read;
+
+
+## Test 14 (misc avrules)
+
+type test14_t;
+auditallow      test14_t test14_t : file read;
+dontaudit       test14_t test14_t : file write;
+neverallow      test14_t test14_t : file { read write };
+type_transition test14_t test14_t : file test14_t;
+type_transition test14_t test14_t : file test14_t "objname";
+neverallow      test14_t test14_t : file *;  # nofail
+
+
+## Test 15 (extended permissions - standard allow)
+
+type test15_t;
+allow           test15_t self : file ioctl;
+neverallowxperm test15_t self : file ioctl 0x1111;
+
+
+## Test 16 (extended permissions - allowxperm)
+
+type test16_t;
+allow           test16_t self : file ioctl;
+allowxperm      test16_t self : file ioctl 0x1111;
+neverallowxperm test16_t self : file ioctl 0x1111;
+
+
+## Test 17 (extended permissions - allowxperm mismatch)
+
+type test17_t;
+allow           test17_t self : file ioctl;
+allowxperm      test17_t self : file ioctl 0x1111;
+neverallowxperm test17_t self : file ioctl 0x2222;  # nofail
+
+
+## Test 18 (extended permissions - allowxperm range I)
+
+type test18_t;
+allow           test18_t self : file ioctl;
+allowxperm      test18_t self : file ioctl { 0x1100-0x1300 };
+neverallowxperm test18_t self : file ioctl 0x1111;
+
+
+## Test 19 (extended permissions - allowxperm range II)
+
+type test19_t;
+allow           test19_t self : file ioctl;
+allowxperm      test19_t self : file ioctl 0x1111;
+neverallowxperm test19_t self : file ioctl { 0x1100-0x1300 };
+
+
+## Test 20 (extended permissions - misc targets I)
+
+attribute test20_a;
+type test20_t, test20_a;
+
+allow           test20_a test20_a : file ioctl;
+allowxperm      test20_a test20_a : file ioctl 0x1111;
+neverallowxperm test20_a self     : file ioctl 0x1111;
+
+
+## Test 21 (extended permissions - misc targets II)
+
+attribute test21_1_a;
+attribute test21_2_a;
+type test21_t, test21_1_a, test21_2_a;
+
+allow           test21_1_a test21_1_a : file ioctl;
+allowxperm      test21_1_a test21_2_a : file ioctl 0x1111;
+neverallowxperm test21_1_a self       : file ioctl 0x1111;
+
+
+## Test 22 (extended permissions - misc targets III)
+
+attribute test22_a;
+type test22_t, test22_a;
+
+allow           test22_a test22_a : file ioctl;
+allowxperm      test22_t self     : file ioctl 0x1111;
+neverallowxperm test22_a self     : file ioctl 0x1111;
+
+
+## Test 23 (extended permissions - misc targets IV)
+
+attribute test23_a;
+type test23_t, test23_a;
+
+allow           test23_a test23_a : file ioctl;
+allowxperm      test23_t test23_t : file ioctl 0x1111;
+neverallowxperm test23_a self     : file ioctl 0x1111;
+
+
+## Test 24 (extended permissions - misc targets V)
+
+attribute test24_a;
+type test24_t, test24_a;
+
+allow           test24_a test24_a : file ioctl;
+allowxperm      test24_t test24_a : file ioctl 0x1111;
+neverallowxperm test24_a self     : file ioctl 0x1111;
+
+
+## Test 25 (extended permissions - misc targets VI)
+
+attribute test25_a;
+type test25_t, test25_a;
+
+allow           test25_a test25_a : file ioctl;
+allowxperm      test25_a self     : file ioctl 0x1111;
+neverallowxperm test25_a self     : file ioctl 0x1111;
+
+
+## Test 26 (extended permissions - assert twice)
+
+attribute test26_a;
+type test26_1_t, test26_a;
+type test26_2_t, test26_a;
+allow           test26_a   test26_a : file ioctl;
+allowxperm      test26_a   test26_a : file ioctl 0x1111;
+neverallowxperm test26_1_t test26_a : file ioctl 0x1111;
+
+
+########################################
+#
+# Test End
+#
+########################################
+
+
+type sys_isid;
+role sys_role;
+role sys_role types sys_isid;
+gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
+sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
+sid security gen_context(sys_user:sys_role:sys_isid, s0)
+sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
+sid file gen_context(sys_user:sys_role:sys_isid, s0)
+sid port gen_context(sys_user:sys_role:sys_isid, s0)
+sid netif gen_context(sys_user:sys_role:sys_isid, s0)
+sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
+sid node gen_context(sys_user:sys_role:sys_isid, s0)
+sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
+fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
+fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
diff --git a/libsepol/tests/test-linker-roles.c b/libsepol/tests/test-linker-roles.c
index 2b17dff..b35bdbe 100644
--- a/libsepol/tests/test-linker-roles.c
+++ b/libsepol/tests/test-linker-roles.c
@@ -53,7 +53,7 @@
 
 /* this simply tests whether the passed in role only has its own 
  * value in its dominates ebitmap */
-static void only_dominates_self(policydb_t * p, role_datum_t * role)
+static void only_dominates_self(policydb_t * p __attribute__ ((unused)), role_datum_t * role)
 {
 	ebitmap_node_t *tnode;
 	unsigned int i;
diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c
new file mode 100644
index 0000000..d973a0e
--- /dev/null
+++ b/libsepol/tests/test-neverallow.c
@@ -0,0 +1,172 @@
+#define _GNU_SOURCE  /* vasprintf(3) */
+
+#include "test-neverallow.h"
+
+#include "helpers.h"
+#include "test-common.h"
+
+#include <sepol/debug.h>
+#include <sepol/policydb/link.h>
+#include <sepol/policydb/expand.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern int mls;
+
+int neverallow_test_init(void)
+{
+	return 0;
+}
+
+int neverallow_test_cleanup(void)
+{
+	return 0;
+}
+
+static struct msg_list {
+	char *msg;
+	struct msg_list *next;
+} *messages;
+
+static void messages_clean(void)
+{
+	while (messages) {
+		struct msg_list *n = messages->next;
+		free(messages->msg);
+		free(messages);
+		messages = n;
+	}
+}
+
+static void messages_check(unsigned count, const char *const expected[count])
+{
+	unsigned i;
+	const struct msg_list *m = messages;
+
+	for (i = 0; i < count; i++, m = m->next) {
+		if (!m) {
+			CU_FAIL("less messages than expected");
+			fprintf(stderr, "\n<expected %u, got %u>\n", count, i);
+			return;
+		}
+
+		if (strcmp(expected[i], m->msg) != 0) {
+			CU_FAIL("messages differ from expected");
+			fprintf(stderr, "\n<expected: '''%s''', got: '''%s'''>\n", expected[i], m->msg);
+		}
+	}
+
+	if (m) {
+		CU_FAIL("more messages than expected");
+		fprintf(stderr, "\n<expected %u; next message: '''%s'''>\n", count, m->msg);
+	}
+}
+
+__attribute__ ((format(printf, 3, 4)))
+static void msg_handler(void *varg __attribute__ ((unused)),
+			sepol_handle_t * handle __attribute__ ((unused)),
+			const char *fmt, ...)
+{
+	char *msg;
+	va_list ap;
+	int r;
+
+	va_start(ap, fmt);
+	r = vasprintf(&msg, fmt, ap);
+	if (r < 0)
+		CU_FAIL_FATAL("oom");
+	va_end(ap);
+
+	struct msg_list *new = malloc(sizeof(*new));
+	if (!new)
+		CU_FAIL_FATAL("oom");
+	new->msg = msg;
+	new->next = messages;
+	messages = new;
+}
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
+
+static void test_neverallow_basic(void)
+{
+	policydb_t basemod, base_expanded;
+	sepol_handle_t *handle;
+	static const char *const expected_messages[] = {
+		"30 neverallow failures occurred",
+		"neverallow on line 53 of policies/test-neverallow/policy.conf.std (or line 53 of policies/test-neverallow/policy.conf.std) violated by allow test1_t test1_t:file { read };",
+		"neverallow on line 60 of policies/test-neverallow/policy.conf.std (or line 60 of policies/test-neverallow/policy.conf.std) violated by allow test2_t test2_t:file { read write };",
+		"neverallow on line 67 of policies/test-neverallow/policy.conf.std (or line 67 of policies/test-neverallow/policy.conf.std) violated by allow test3_t test3_t:file { read };",
+		"neverallow on line 74 of policies/test-neverallow/policy.conf.std (or line 74 of policies/test-neverallow/policy.conf.std) violated by allow test4_t test4_t:file { read };",
+		"neverallow on line 81 of policies/test-neverallow/policy.conf.std (or line 81 of policies/test-neverallow/policy.conf.std) violated by allow test5_t test5_t:file { read };",
+		"neverallow on line 89 of policies/test-neverallow/policy.conf.std (or line 89 of policies/test-neverallow/policy.conf.std) violated by allow test6_1_t test6_1_t:file { read };",
+		"neverallow on line 97 of policies/test-neverallow/policy.conf.std (or line 97 of policies/test-neverallow/policy.conf.std) violated by allow test7_1_t test7_1_t:file { read };",
+		"neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { write };",
+		"neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { read };",
+		"neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { read };",
+		"neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { write };",
+		"neverallow on line 124 of policies/test-neverallow/policy.conf.std (or line 124 of policies/test-neverallow/policy.conf.std) violated by allow test10_1_t test10_1_t:file { read };",
+		"neverallow on line 131 of policies/test-neverallow/policy.conf.std (or line 131 of policies/test-neverallow/policy.conf.std) violated by allow test11_t test11_t:process { dyntransition transition };",
+		"neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { getattr };",
+		"neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_2_t:file { getattr };",
+		"neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { open };",
+		"neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_2_t test12_1_t:file { open };",
+		"neverallow on line 156 of policies/test-neverallow/policy.conf.std (or line 156 of policies/test-neverallow/policy.conf.std) violated by allow test13_1_t test13_1_t:file { read };",
+		"neverallowxperm on line 174 of policies/test-neverallow/policy.conf.std (or line 174 of policies/test-neverallow/policy.conf.std) violated by\nallow test15_t test15_t:file { ioctl };",
+		"neverallowxperm on line 182 of policies/test-neverallow/policy.conf.std (or line 182 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test16_t test16_t:file ioctl { 0x1111 };",
+		"neverallowxperm on line 198 of policies/test-neverallow/policy.conf.std (or line 198 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test18_t test18_t:file ioctl { 0x1111 };",
+		"neverallowxperm on line 206 of policies/test-neverallow/policy.conf.std (or line 206 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test19_t test19_t:file ioctl { 0x1111 };",
+		"neverallowxperm on line 216 of policies/test-neverallow/policy.conf.std (or line 216 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test20_a test20_a:file ioctl { 0x1111 };",
+		"neverallowxperm on line 227 of policies/test-neverallow/policy.conf.std (or line 227 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test21_1_a test21_2_a:file ioctl { 0x1111 };",
+		"neverallowxperm on line 237 of policies/test-neverallow/policy.conf.std (or line 237 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test22_t test22_t:file ioctl { 0x1111 };",
+		"neverallowxperm on line 247 of policies/test-neverallow/policy.conf.std (or line 247 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test23_t test23_t:file ioctl { 0x1111 };",
+		"neverallowxperm on line 257 of policies/test-neverallow/policy.conf.std (or line 257 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test24_t test24_a:file ioctl { 0x1111 };",
+		"neverallowxperm on line 267 of policies/test-neverallow/policy.conf.std (or line 267 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test25_t test25_t:file ioctl { 0x1111 };",
+		"neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test26_a test26_a:file ioctl { 0x1111 };",
+		"neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test26_a test26_a:file ioctl { 0x1111 };",
+	};
+
+	if (policydb_init(&base_expanded))
+		CU_FAIL_FATAL("Failed to initialize policy");
+
+	if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy.conf"))
+		CU_FAIL_FATAL("Failed to load policy");
+
+	if (link_modules(NULL, &basemod, NULL, 0, 0))
+		CU_FAIL_FATAL("Failed to link base module");
+
+	if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
+		CU_FAIL_FATAL("Failed to expand policy");
+
+	if ((handle = sepol_handle_create()) == NULL)
+		CU_FAIL_FATAL("Failed to initialize handle");
+
+	sepol_msg_set_callback(handle, msg_handler, NULL);
+
+	if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1)
+		CU_FAIL("Assertions did not trigger");
+
+	messages_check(ARRAY_SIZE(expected_messages), expected_messages);
+
+	sepol_handle_destroy(handle);
+	messages_clean();
+	policydb_destroy(&basemod);
+	policydb_destroy(&base_expanded);
+}
+
+int neverallow_add_tests(CU_pSuite suite)
+{
+	/*
+	 * neverallow rules operate only on types and are unaffected by MLS
+	 * (avoid adjusting the messages for std and mls)
+	 */
+	if (mls)
+		return 0;
+
+	if (NULL == CU_add_test(suite, "neverallow_basic", test_neverallow_basic)) {
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+	return 0;
+}
diff --git a/libsepol/tests/test-neverallow.h b/libsepol/tests/test-neverallow.h
new file mode 100644
index 0000000..d3c2a74
--- /dev/null
+++ b/libsepol/tests/test-neverallow.h
@@ -0,0 +1,10 @@
+#ifndef TEST_NEVERALLOW_H__
+#define TEST_NEVERALLOW_H__
+
+#include <CUnit/Basic.h>
+
+int neverallow_test_init(void);
+int neverallow_test_cleanup(void);
+int neverallow_add_tests(CU_pSuite suite);
+
+#endif  /* TEST_NEVERALLOW_H__ */
diff --git a/mcstrans/VERSION b/mcstrans/VERSION
index 2f4b607..0395819 100644
--- a/mcstrans/VERSION
+++ b/mcstrans/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/policycoreutils/VERSION b/policycoreutils/VERSION
index 2f4b607..0395819 100644
--- a/policycoreutils/VERSION
+++ b/policycoreutils/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/policycoreutils/newrole/newrole.c b/policycoreutils/newrole/newrole.c
index c2afa37..d9efa68 100644
--- a/policycoreutils/newrole/newrole.c
+++ b/policycoreutils/newrole/newrole.c
@@ -1289,7 +1289,7 @@
 	/*
 	 * Step 5:  Execute a new shell with the new context in `new_context'. 
 	 *
-	 * Establish context, namesapce and any options for the new shell
+	 * Establish context, namespace and any options for the new shell
 	 */
 	if (optind < 1)
 		optind = 1;
diff --git a/policycoreutils/scripts/fixfiles b/policycoreutils/scripts/fixfiles
index c72ca0e..166af6f 100755
--- a/policycoreutils/scripts/fixfiles
+++ b/policycoreutils/scripts/fixfiles
@@ -207,6 +207,25 @@
 [ ${PIPESTATUS[0]} != 0 ] && echo "$1 not found" >/dev/stderr
 }
 
+# unmount tmp bind mount before exit
+umount_TMP_MOUNT() {
+	if [ -n "$TMP_MOUNT" ]; then
+	     umount "${TMP_MOUNT}${m}" || exit 130
+	     rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
+	fi
+	exit 130
+}
+
+fix_labels_on_mountpoint() {
+	test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
+	mkdir -p "${TMP_MOUNT}${m}" || exit 1
+	mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
+	${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
+	umount "${TMP_MOUNT}${m}" || exit 1
+	rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
+}
+export -f fix_labels_on_mountpoint
+
 #
 # restore
 # if called with -n will only check file context
@@ -252,14 +271,15 @@
 	        # we bind mount so we can fix the labels of files that have already been
 	        # mounted over
 	        for m in `echo $FILESYSTEMSRW`; do
-	            TMP_MOUNT="$(mktemp -d)"
-	            test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
-
-	            mkdir -p "${TMP_MOUNT}${m}" || exit 1
-	            mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
-	            ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
-	            umount "${TMP_MOUNT}${m}" || exit 1
-	            rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
+	            TMP_MOUNT="$(mktemp -p /run -d fixfiles.XXXXXXXXXX)"
+	            export SETFILES VERBOSE EXCLUDEDIRS FORCEFLAG THREADS FC TMP_MOUNT m
+	            if type unshare &> /dev/null; then
+	                unshare -m bash -c "fix_labels_on_mountpoint $*" || exit $?
+	            else
+	                trap umount_TMP_MOUNT EXIT
+	                fix_labels_on_mountpoint $*
+	                trap EXIT
+	            fi
 	        done;
 	    fi
 	else
diff --git a/policycoreutils/sestatus/sestatus.c b/policycoreutils/sestatus/sestatus.c
index 7dcc994..6c95828 100644
--- a/policycoreutils/sestatus/sestatus.c
+++ b/policycoreutils/sestatus/sestatus.c
@@ -140,6 +140,8 @@
 					pc[*npc] =
 					    (char *)malloc((buf_len) *
 							   sizeof(char));
+					if (!pc[*npc])
+						break;
 					memcpy(pc[*npc], bufp, buf_len);
 					(*npc)++;
 					bufp = NULL;
@@ -150,6 +152,8 @@
 					fc[*nfc] =
 					    (char *)malloc((buf_len) *
 							   sizeof(char));
+					if (!fc[*nfc])
+						break;
 					memcpy(fc[*nfc], bufp, buf_len);
 					(*nfc)++;
 					bufp = NULL;
diff --git a/python/VERSION b/python/VERSION
index 2f4b607..0395819 100644
--- a/python/VERSION
+++ b/python/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/python/audit2allow/audit2allow.1 b/python/audit2allow/audit2allow.1
index c61067b..04ec323 100644
--- a/python/audit2allow/audit2allow.1
+++ b/python/audit2allow/audit2allow.1
@@ -151,7 +151,7 @@
 gen_require(`
         type myapp_t;
         type etc_t;
- };
+\[aq])
 
 files_read_etc_files(myapp_t)
 <review local.te and customize as desired>
diff --git a/python/semanage/semanage b/python/semanage/semanage
index b21d148..e0bd98a 100644
--- a/python/semanage/semanage
+++ b/python/semanage/semanage
@@ -130,7 +130,7 @@
                 sys.exit(1)
         setattr(namespace, self.dest, values)
 
-# define dictionary for seobject OBEJCTS
+# define dictionary for seobject OBJECTS
 object_dict = {
     'login': seobject.loginRecords,
     'user': seobject.seluserRecords,
diff --git a/python/sepolgen/VERSION b/python/sepolgen/VERSION
index 2f4b607..0395819 100644
--- a/python/sepolgen/VERSION
+++ b/python/sepolgen/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/python/sepolgen/src/sepolgen/policygen.py b/python/sepolgen/src/sepolgen/policygen.py
index 8f0ce26..183b41a 100644
--- a/python/sepolgen/src/sepolgen/policygen.py
+++ b/python/sepolgen/src/sepolgen/policygen.py
@@ -324,9 +324,9 @@
             ifcall.args.append(av.obj_class)
         else:
             print(params[i].type)
-            assert(0)
+            assert 0
 
-    assert(len(ifcall.args) > 0)
+    assert len(ifcall.args) > 0
 
     return ifcall
 
diff --git a/python/sepolicy/Makefile b/python/sepolicy/Makefile
index d983e40..4e9e93d 100644
--- a/python/sepolicy/Makefile
+++ b/python/sepolicy/Makefile
@@ -27,7 +27,7 @@
 	@$(PYTHON) test_sepolicy.py -v
 
 install:
-	$(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` $(PYTHON_SETUP_ARGS)
+	$(PYTHON) -m pip install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR) --ignore-installed --no-deps` $(PYTHON_SETUP_ARGS) .
 	[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
 	install -m 755 sepolicy.py $(DESTDIR)$(BINDIR)/sepolicy
 	(cd $(DESTDIR)$(BINDIR); ln -sf sepolicy sepolgen)
diff --git a/python/sepolicy/sepolicy.py b/python/sepolicy/sepolicy.py
index 733d404..82ff6af 100755
--- a/python/sepolicy/sepolicy.py
+++ b/python/sepolicy/sepolicy.py
@@ -332,9 +332,10 @@
     from sepolicy.manpage import ManPage
     m = ManPage(domain, path, root, source_files, web)
     print(m.get_man_page_path())
+    return (m.manpage_domains, m.manpage_roles)
 
 def manpage(args):
-    from sepolicy.manpage import HTMLManPages, manpage_domains, manpage_roles, gen_domains
+    from sepolicy.manpage import HTMLManPages, gen_domains
 
     path = args.path
     if not args.policy and args.root != "/":
@@ -347,9 +348,17 @@
     else:
         test_domains = args.domain
 
+    manpage_domains = set()
+    manpage_roles = set()
     p = Pool()
+    async_results = []
     for domain in test_domains:
-        p.apply_async(manpage_work, [domain, path, args.root, args.source_files, args.web])
+        async_results.append(p.apply_async(manpage_work, [domain, path, args.root, args.source_files, args.web]))
+    for result in async_results:
+        domains, roles = result.get()
+        manpage_domains.update(domains)
+        manpage_roles.update(roles)
+
     p.close()
     p.join()
 
diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
index 9c3caa0..e2d5c11 100644
--- a/python/sepolicy/sepolicy/__init__.py
+++ b/python/sepolicy/sepolicy/__init__.py
@@ -335,7 +335,12 @@
         pass
 
     try:
-        d['boolean'] = [(str(rule.conditional), enabled)]
+        d['booleans'] = [(str(b), b.state) for b in rule.conditional.booleans]
+    except AttributeError:
+        pass
+
+    try:
+        d['conditional'] = str(rule.conditional)
     except AttributeError:
         pass
 
@@ -440,29 +445,29 @@
                 x['source'] in src_list and
                 x['target'] in dest_list and
                 set(perm).issubset(x[PERMS]) and
-                'boolean' in x,
+                'conditional' in x,
                 get_all_allow_rules()))
 
     try:
         for i in allows:
-            tdict.update({'source': i['source'], 'boolean': i['boolean']})
+            tdict.update({'source': i['source'], 'conditional': (i['conditional'], i['enabled'])})
             if tdict not in tlist:
                 tlist.append(tdict)
                 tdict = {}
     except KeyError:
-        return(tlist)
+        return tlist
 
-    return (tlist)
+    return tlist
 
 
 def get_conditionals_format_text(cond):
 
     enabled = False
     for x in cond:
-        if x['boolean'][0][1]:
+        if x['conditional'][1]:
             enabled = True
             break
-    return _("-- Allowed %s [ %s ]") % (enabled, " || ".join(set(map(lambda x: "%s=%d" % (x['boolean'][0][0], x['boolean'][0][1]), cond))))
+    return _("-- Allowed %s [ %s ]") % (enabled, " || ".join(set(map(lambda x: "%s=%d" % (x['conditional'][0], x['conditional'][1]), cond))))
 
 
 def get_types_from_attribute(attribute):
@@ -716,9 +721,9 @@
     boollist = []
     permlist = search([ALLOW], {'source': setype})
     for p in permlist:
-        if "boolean" in p:
+        if "booleans" in p:
             try:
-                for b in p["boolean"]:
+                for b in p["booleans"]:
                     if boolean in b:
                         boollist.append(p)
             except:
@@ -1141,7 +1146,7 @@
     bools = []
     domainbools = []
     domainname, short_name = gen_short_name(setype)
-    for i in map(lambda x: x['boolean'], filter(lambda x: 'boolean' in x and x['source'] == setype, get_all_allow_rules())):
+    for i in map(lambda x: x['booleans'], filter(lambda x: 'booleans' in x and x['source'] == setype, search([ALLOW, DONTAUDIT]))):
         for b in i:
             if not isinstance(b, tuple):
                 continue
@@ -1222,31 +1227,18 @@
         return _(booleans_dict[boolean][2])
     else:
         desc = boolean.split("_")
-        return "Allow %s to %s" % (desc[0], " ".join(desc[1:]))
+        return _("Allow {subject} to {rest}").format(subject=desc[0], rest=" ".join(desc[1:]))
 
 
 def get_os_version():
-    os_version = ""
-    pkg_name = "selinux-policy"
+    system_release = ""
     try:
-        try:
-            from commands import getstatusoutput
-        except ImportError:
-            from subprocess import getstatusoutput
-        rc, output = getstatusoutput("rpm -q '%s'" % pkg_name)
-        if rc == 0:
-            os_version = output.split(".")[-2]
-    except:
-        os_version = ""
+        import distro
+        system_release = distro.name(pretty=True)
+    except IOError:
+        system_release = "Misc"
 
-    if os_version[0:2] == "fc":
-        os_version = "Fedora" + os_version[2:]
-    elif os_version[0:2] == "el":
-        os_version = "RHEL" + os_version[2:]
-    else:
-        os_version = ""
-
-    return os_version
+    return system_release
 
 
 def reinit():
diff --git a/python/sepolicy/sepolicy/generate.py b/python/sepolicy/sepolicy/generate.py
index 3717d5d..b6df3e9 100644
--- a/python/sepolicy/sepolicy/generate.py
+++ b/python/sepolicy/sepolicy/generate.py
@@ -1346,9 +1346,9 @@
             if len(temp_dirs) != 0:
                 for i in temp_dirs:
                     if i in self.dirs.keys():
-                        del(self.dirs[i])
+                        del self.dirs[i]
                     elif i in self.files.keys():
-                        del(self.files[i])
+                        del self.files[i]
                     else:
                         continue
 
diff --git a/python/sepolicy/sepolicy/gui.py b/python/sepolicy/sepolicy/gui.py
index 335be58..0420804 100644
--- a/python/sepolicy/sepolicy/gui.py
+++ b/python/sepolicy/sepolicy/gui.py
@@ -130,14 +130,13 @@
         self.application = app
         self.filter_txt = ""
         builder = Gtk.Builder()  # BUILDER OBJ
-        self.code_path = sysconfig.get_python_lib(plat_specific=False) + "/sepolicy/"
+        self.code_path = sysconfig.get_path('purelib', vars={'base': "/usr"}) + "/sepolicy/"
         glade_file = self.code_path + "sepolicy.glade"
         builder.add_from_file(glade_file)
         self.outer_notebook = builder.get_object("outer_notebook")
         self.window = builder.get_object("SELinux_window")
-        self.main_selection_window = builder.get_object("Main_selection_menu")
+        self.main_selection_popover = builder.get_object("Main_selection_menu")
         self.main_advanced_label = builder.get_object("main_advanced_label")
-        self.popup = 0
         self.applications_selection_button = builder.get_object("applications_selection_button")
         self.revert_button = builder.get_object("Revert_button")
         self.busy_cursor = Gdk.Cursor(Gdk.CursorType.WATCH)
@@ -531,7 +530,6 @@
         dic = {
             "on_combo_button_clicked": self.open_combo_menu,
             "on_disable_ptrace_toggled": self.on_disable_ptrace,
-            "on_SELinux_window_configure_event": self.hide_combo_menu,
             "on_entrycompletion_obj_match_selected": self.set_application_label,
             "on_filter_changed": self.get_filter_data,
             "on_save_changes_file_equiv_clicked": self.update_to_file_equiv,
@@ -635,7 +633,7 @@
         for k in self.cur_dict:
             for j in self.cur_dict[k]:
                 if i == ctr:
-                    del(self.cur_dict[k][j])
+                    del self.cur_dict[k][j]
                     return
                 i += 1
 
@@ -808,18 +806,8 @@
         return self.help_show_page()
 
     def open_combo_menu(self, *args):
-        if self.popup == 0:
-            self.popup = 1
-            location = self.window.get_position()
-            self.main_selection_window.move(location[0] + 2, location[1] + 65)
-            self.main_selection_window.show()
-        else:
-            self.main_selection_window.hide()
-            self.popup = 0
-
-    def hide_combo_menu(self, *args):
-        self.main_selection_window.hide()
-        self.popup = 0
+        self.main_selection_popover.set_relative_to(self.applications_selection_button)
+        self.main_selection_popover.popup()
 
     def set_application_label(self, *args):
         self.set_application_label = True
@@ -860,7 +848,7 @@
                     if val is True or val is False or val is None:
                         continue
                     # Returns true if filter_txt exists within the val
-                    if(val.find(self.filter_txt) != -1 or val.lower().find(self.filter_txt) != -1):
+                    if val.find(self.filter_txt) != -1 or val.lower().find(self.filter_txt) != -1:
                         return True
                 except (AttributeError, TypeError):
                     pass
@@ -2174,7 +2162,7 @@
         model.set_value(iter, 0, not model.get_value(iter, 0))
         active = model.get_value(iter, 0)
         if name in self.cur_dict["boolean"]:
-            del(self.cur_dict["boolean"][name])
+            del self.cur_dict["boolean"][name]
         else:
             self.cur_dict["boolean"][name] = {"active": active}
         self.new_updates()
@@ -2335,7 +2323,7 @@
             self.active_button = self.network_radio_button
 
     def clearbuttons(self, clear=True):
-        self.main_selection_window.hide()
+        self.main_selection_popover.hide()
         self.boolean_radio_button.set_visible(False)
         self.files_radio_button.set_visible(False)
         self.network_radio_button.set_visible(False)
diff --git a/python/sepolicy/sepolicy/manpage.py b/python/sepolicy/sepolicy/manpage.py
index 3e61e33..a488dcb 100755
--- a/python/sepolicy/sepolicy/manpage.py
+++ b/python/sepolicy/sepolicy/manpage.py
@@ -21,7 +21,7 @@
 #                                        02111-1307  USA
 #
 #
-__all__ = ['ManPage', 'HTMLManPages', 'manpage_domains', 'manpage_roles', 'gen_domains']
+__all__ = ['ManPage', 'HTMLManPages', 'gen_domains']
 
 import string
 import selinux
@@ -147,13 +147,6 @@
 def prettyprint(f, trim):
     return " ".join(f[:-len(trim)].split("_"))
 
-# for HTML man pages
-manpage_domains = []
-manpage_roles = []
-
-fedora_releases = ["Fedora17", "Fedora18"]
-rhel_releases = ["RHEL6", "RHEL7"]
-
 
 def get_alphabet_manpages(manpage_list):
     alphabet_manpages = dict.fromkeys(string.ascii_letters, [])
@@ -184,7 +177,7 @@
 class HTMLManPages:
 
     """
-            Generate a HHTML Manpages on an given SELinux domains
+            Generate a HTML Manpages on an given SELinux domains
     """
 
     def __init__(self, manpage_roles, manpage_domains, path, os_version):
@@ -192,18 +185,12 @@
         self.manpage_domains = get_alphabet_manpages(manpage_domains)
         self.os_version = os_version
         self.old_path = path + "/"
-        self.new_path = self.old_path + self.os_version + "/"
-
-        if self.os_version in fedora_releases or self.os_version in rhel_releases:
-            self.__gen_html_manpages()
-        else:
-            print("SELinux HTML man pages can not be generated for this %s" % os_version)
-            exit(1)
+        self.new_path = self.old_path
+        self.__gen_html_manpages()
 
     def __gen_html_manpages(self):
         self._write_html_manpage()
         self._gen_index()
-        self._gen_body()
         self._gen_css()
 
     def _write_html_manpage(self):
@@ -221,67 +208,21 @@
                     convert_manpage_to_html((self.new_path + r.rsplit("_selinux", 1)[0] + ".html"), self.old_path + r)
 
     def _gen_index(self):
-        index = self.old_path + "index.html"
-        fd = open(index, 'w')
-        fd.write("""
-<html>
-<head>
-    <link rel=stylesheet type="text/css" href="style.css" title="style">
-    <title>SELinux man pages online</title>
-</head>
-<body>
-<h1>SELinux man pages</h1>
-<br></br>
-Fedora or Red Hat Enterprise Linux Man Pages.</h2>
-<br></br>
-<hr>
-<h3>Fedora</h3>
-<table><tr>
-<td valign="middle">
-</td>
-</tr></table>
-<pre>
-""")
-        for f in fedora_releases:
-            fd.write("""
-<a href=%s/%s.html>%s</a> - SELinux man pages for %s """ % (f, f, f, f))
-
-        fd.write("""
-</pre>
-<hr>
-<h3>RHEL</h3>
-<table><tr>
-<td valign="middle">
-</td>
-</tr></table>
-<pre>
-""")
-        for r in rhel_releases:
-            fd.write("""
-<a href=%s/%s.html>%s</a> - SELinux man pages for %s """ % (r, r, r, r))
-
-        fd.write("""
-</pre>
-	""")
-        fd.close()
-        print("%s has been created" % index)
-
-    def _gen_body(self):
-        html = self.new_path + self.os_version + ".html"
+        html = self.new_path + "index.html"
         fd = open(html, 'w')
         fd.write("""
 <html>
 <head>
-	<link rel=stylesheet type="text/css" href="../style.css" title="style">
-	<title>Linux man-pages online for Fedora18</title>
+	<link rel=stylesheet type="text/css" href="style.css" title="style">
+	<title>SELinux man pages</title>
 </head>
 <body>
-<h1>SELinux man pages for Fedora18</h1>
+<h1>SELinux man pages for %s</h1>
 <hr>
 <table><tr>
 <td valign="middle">
 <h3>SELinux roles</h3>
-""")
+""" % self.os_version)
         for letter in self.manpage_roles:
             if len(self.manpage_roles[letter]):
                 fd.write("""
@@ -408,6 +349,8 @@
     """
     modules_dict = None
     enabled_str = ["Disabled", "Enabled"]
+    manpage_domains = []
+    manpage_roles = []
 
     def __init__(self, domainname, path="/tmp", root="/", source_files=False, html=False):
         self.html = html
@@ -433,8 +376,7 @@
 
         self.fcdict = sepolicy.get_fcdict(self.fcpath)
 
-        if not os.path.exists(path):
-            os.makedirs(path)
+        os.makedirs(path, exist_ok=True)
 
         self.path = path
 
@@ -453,10 +395,10 @@
         if self.domainname + "_r" in self.all_roles:
             self.__gen_user_man_page()
             if self.html:
-                manpage_roles.append(self.man_page_path)
+                self.manpage_roles.append(self.man_page_path)
         else:
             if self.html:
-                manpage_domains.append(self.man_page_path)
+                self.manpage_domains.append(self.man_page_path)
             self.__gen_man_page()
         self.fd.close()
 
@@ -797,7 +739,7 @@
 .B STANDARD FILE CONTEXT
 
 SELinux defines the file context types for the %(domainname)s, if you wanted to
-store files with these types in a diffent paths, you need to execute the semanage command to specify alternate labeling and then use restorecon to put the labels on disk.
+store files with these types in a different paths, you need to execute the semanage command to specify alternate labeling and then use restorecon to put the labels on disk.
 
 .B semanage fcontext -a -t %(type)s '/srv/%(domainname)s/content(/.*)?'
 .br
diff --git a/python/sepolicy/sepolicy/sepolicy.glade b/python/sepolicy/sepolicy/sepolicy.glade
index 0724d6c..30e7b03 100644
--- a/python/sepolicy/sepolicy/sepolicy.glade
+++ b/python/sepolicy/sepolicy/sepolicy.glade
@@ -10,11 +10,8 @@
       <column type="gchararray"/>
     </columns>
   </object>
-  <object class="GtkWindow" id="Main_selection_menu">
+  <object class="GtkPopover" id="Main_selection_menu">
     <property name="can_focus">False</property>
-    <property name="default_width">265</property>
-    <property name="default_height">100</property>
-    <property name="decorated">False</property>
     <child>
       <object class="GtkBox" id="vbox2">
         <property name="visible">True</property>
@@ -53,7 +50,6 @@
                 <property name="primary_icon_stock">gtk-find</property>
                 <property name="primary_icon_activatable">False</property>
                 <property name="secondary_icon_activatable">False</property>
-                <signal name="activate" handler="on_SELinux_window_configure_event" swapped="no"/>
                 <signal name="changed" handler="on_completion_entry_changed" swapped="no"/>
               </object>
               <packing>
@@ -306,7 +302,6 @@
     </columns>
   </object>
   <object class="GtkEntryCompletion" id="entrycompletion_obj">
-    <signal name="match-selected" handler="on_SELinux_window_configure_event" swapped="no"/>
     <signal name="match-selected" handler="on_completion_entry_changed" swapped="no"/>
     <signal name="match-selected" handler="on_entrycompletion_obj_match_selected" swapped="no"/>
   </object>
@@ -1707,9 +1702,7 @@
     <property name="window_position">center-always</property>
     <property name="default_width">650</property>
     <property name="default_height">420</property>
-    <signal name="configure-event" handler="on_SELinux_window_configure_event" swapped="no"/>
     <signal name="delete-event" handler="on_confirmation_close" swapped="no"/>
-    <signal name="focus-in-event" handler="on_SELinux_window_configure_event" swapped="no"/>
     <child>
       <object class="GtkBox" id="vbox1">
         <property name="visible">True</property>
diff --git a/python/sepolicy/sepolicy/templates/script.py b/python/sepolicy/sepolicy/templates/script.py
index c79738b..564a6b3 100644
--- a/python/sepolicy/sepolicy/templates/script.py
+++ b/python/sepolicy/sepolicy/templates/script.py
@@ -75,7 +75,7 @@
 """
 
 manpage="""\
-# Generate a man page off the installed module
+# Generate a man page of the installed module
 sepolicy manpage -p . -d DOMAINTYPE_t
 """
 
diff --git a/python/sepolicy/setup.py b/python/sepolicy/setup.py
index c822066..2284f15 100644
--- a/python/sepolicy/setup.py
+++ b/python/sepolicy/setup.py
@@ -6,7 +6,7 @@
 
 setup(
     name="sepolicy",
-    version="3.4",
+    version="3.5-rc2",
     description="Python SELinux Policy Analyses bindings",
     author="Daniel Walsh",
     author_email="[email protected]",
diff --git a/restorecond/VERSION b/restorecond/VERSION
index 2f4b607..0395819 100644
--- a/restorecond/VERSION
+++ b/restorecond/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/sandbox/VERSION b/sandbox/VERSION
index 2f4b607..0395819 100644
--- a/sandbox/VERSION
+++ b/sandbox/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/sandbox/sandbox b/sandbox/sandbox
index 7708073..a2762a7 100644
--- a/sandbox/sandbox
+++ b/sandbox/sandbox
@@ -111,7 +111,7 @@
 
 def savefile(new, orig, X_ind):
     copy = False
-    if(X_ind):
+    if X_ind:
         import gi
         gi.require_version('Gtk', '3.0')
         from gi.repository import Gtk
@@ -131,9 +131,9 @@
         except NameError:
             pass
         ans = input(_("Do you want to save changes to '%s' (y/N): ") % orig)
-        if(re.match(_("[yY]"), ans)):
+        if re.match(_("[yY]"), ans):
             copy = True
-    if(copy):
+    if copy:
         shutil.copy2(new, orig)
 
 
diff --git a/secilc/VERSION b/secilc/VERSION
index 2f4b607..0395819 100644
--- a/secilc/VERSION
+++ b/secilc/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2
diff --git a/semodule-utils/VERSION b/semodule-utils/VERSION
index 2f4b607..0395819 100644
--- a/semodule-utils/VERSION
+++ b/semodule-utils/VERSION
@@ -1 +1 @@
-3.4
+3.5-rc2