Merge remote-tracking branch 'aosp/upstream-master' into mymerge

Bug: 63861738
Test: Builds 'n' boots
Change-Id: Idfb333d4cc1568dd2273f74731f12d52a413c07b
diff --git a/.travis.yml b/.travis.yml
index fa25d1b..1b76149 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,25 +11,35 @@
 env:
   matrix:
     # Test the last version of Python and Ruby together, with some linkers
-    - PYVER=python3.5 RUBYLIBVER=2.3
-    - PYVER=python3.5 RUBYLIBVER=2.3 LINKER=gold
-    - PYVER=python3.5 RUBYLIBVER=2.3 LINKER=bfd
+    - PYVER=python3.6 RUBYLIBVER=2.4
+    - PYVER=python3.6 RUBYLIBVER=2.4 TEST_FLAGS_OVERRIDE=1
+    - PYVER=python3.6 RUBYLIBVER=2.4 LINKER=gold
+    - PYVER=python3.6 RUBYLIBVER=2.4 LINKER=bfd
 
     # Test several Python versions
-    - PYVER=python2.7 RUBYLIBVER=2.3
-    - PYVER=python3.3 RUBYLIBVER=2.3
-    - PYVER=python3.4 RUBYLIBVER=2.3
-    - PYVER=pypy RUBYLIBVER=2.3
+    - PYVER=python2.7 RUBYLIBVER=2.4
+    - PYVER=python3.3 RUBYLIBVER=2.4
+    - PYVER=python3.4 RUBYLIBVER=2.4
+    - PYVER=python3.5 RUBYLIBVER=2.4
+    - PYVER=pypy2 RUBYLIBVER=2.4
     #- PYVER=pypy3 RUBYLIBVER=2.3 # PyPy3 5.5.0 provides the Python2 form of some structures, which makes it incompatible with SWIG
 
     # Test several Ruby versions
-    - PYVER=python3.5 RUBYLIBVER=2.0
-    - PYVER=python3.5 RUBYLIBVER=2.1
-    - PYVER=python3.5 RUBYLIBVER=2.2
+    - PYVER=python3.6 RUBYLIBVER=2.1
+    - PYVER=python3.6 RUBYLIBVER=2.2
+    - PYVER=python3.6 RUBYLIBVER=2.3
 
-# Use Travis-CI Ubuntu 14.04 Trusty infrastructure
+matrix:
+  exclude:
+    - compiler: clang
+      env: PYVER=python3.6 RUBYLIBVER=2.4 LINKER=gold
+    - compiler: clang
+      env: PYVER=python3.6 RUBYLIBVER=2.4 LINKER=bfd
+
+# Use Travis-CI Ubuntu 14.04 Trusty infrastructure, "full image" variant
 sudo: required
 dist: trusty
+group: sugilite
 
 # Install SELinux userspace utilities dependencies
 addons:
@@ -95,14 +105,17 @@
   - echo "$PYTHON" ; $PYTHON --version
   - echo "$RUBY" ; $RUBY --version
 
+  # If TEST_FLAGS_OVERRIDE is defined, test that overriding CFLAGS, LDFLAGS and other variables works fine
+  - if [ -n "$TEST_FLAGS_OVERRIDE" ]; then EXPLICIT_MAKE_VARS="CFLAGS=-I$DESTDIR/usr/include LDFLAGS=-L$DESTDIR/usr/lib LDLIBS= CPPFLAGS=" ; fi
+
 script:
   # Start by installing everything into $DESTDIR
-  - make install -k
-  - make install-pywrap -k
-  - make install-rubywrap -k
+  - make install $EXPLICIT_MAKE_VARS -k
+  - make install-pywrap $EXPLICIT_MAKE_VARS -k
+  - make install-rubywrap $EXPLICIT_MAKE_VARS -k
 
   # Now that everything is installed, run "make all" to build everything which may have not been built
-  - make all -k
+  - make all $EXPLICIT_MAKE_VARS -k
 
   # Set up environment variables for the tests
   - export LD_LIBRARY_PATH="$DESTDIR/usr/lib:$DESTDIR/lib"
@@ -117,7 +130,7 @@
   - echo "$RUBYLIB"
 
   # Run tests
-  - make test
+  - make test $EXPLICIT_MAKE_VARS
 
   # Test Python and Ruby wrappers
   - $PYTHON -c 'import selinux;import selinux.audit2why;import semanage;print(selinux.is_selinux_enabled())'
@@ -131,7 +144,7 @@
     git status --short | sed -n 's/^??/error: missing .gitignore entry for/p' | (! grep '^')
 
   # Clean up everything and show which file would be added to "make clean"
-  - make clean distclean
+  - make clean distclean $EXPLICIT_MAKE_VARS
   - |-
     git ls-files --ignored --others --exclude-standard | sed 's/^/error: "make clean distclean" did not remove /' | (! grep '^')
 
diff --git a/checkpolicy/VERSION b/checkpolicy/VERSION
index 5154b3f..1effb00 100644
--- a/checkpolicy/VERSION
+++ b/checkpolicy/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 534fc22..b75f2af 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -22,6 +22,7 @@
  *
  *	Policy Module support.
  *
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2005 Tresys Technology, LLC
  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
@@ -699,6 +700,8 @@
 	printf("h)  change a boolean value\n");
 	printf("i)  display constraint expressions\n");
 	printf("j)  display validatetrans expressions\n");
+	printf("k)  Call ibpkey_sid\n");
+	printf("l)  Call ibendport_sid\n");
 #ifdef EQUIVTYPES
 	printf("z)  Show equivalent types\n");
 #endif
@@ -1220,6 +1223,50 @@
 				    "\nNo validatetrans expressions found.\n");
 			}
 			break;
+		case 'k':
+			{
+				char *p;
+				struct in6_addr addr6;
+				uint64_t subnet_prefix;
+				unsigned int pkey;
+
+				printf("subnet prefix?  ");
+				FGETS(ans, sizeof(ans), stdin);
+				ans[strlen(ans) - 1] = 0;
+				p = (char *)&addr6;
+
+				if (inet_pton(AF_INET6, ans, p) < 1) {
+					printf("error parsing subnet prefix\n");
+					break;
+				}
+
+				memcpy(&subnet_prefix, p, sizeof(subnet_prefix));
+				printf("pkey? ");
+				FGETS(ans, sizeof(ans), stdin);
+				pkey = atoi(ans);
+				sepol_ibpkey_sid(subnet_prefix, pkey, &ssid);
+				printf("sid %d\n", ssid);
+			}
+			break;
+		case 'l':
+			printf("device name (eg. mlx4_0)?  ");
+			FGETS(ans, sizeof(ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+
+			name = malloc((strlen(ans) + 1) * sizeof(char));
+			if (!name) {
+				fprintf(stderr, "couldn't malloc string.\n");
+				break;
+			}
+			strcpy(name, ans);
+
+			printf("port? ");
+			FGETS(ans, sizeof(ans), stdin);
+			port = atoi(ans);
+			sepol_ibendport_sid(name, port, &ssid);
+			printf("sid %d\n", ssid);
+			free(name);
+			break;
 #ifdef EQUIVTYPES
 		case 'z':
 			identify_equiv_types();
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 8fab214..f12ebdb 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -20,6 +20,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2008 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2017 Mellanox Techonologies Inc.
  *	This program is free software; you can redistribute it and/or modify
  *  	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation, version 2.
@@ -5057,6 +5058,192 @@
 	return -1;
 }
 
+int define_ibpkey_context(unsigned int low, unsigned int high)
+{
+	ocontext_t *newc, *c, *l, *head;
+	struct in6_addr subnet_prefix;
+	char *id;
+	int rc = 0;
+
+	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+		yyerror("ibpkeycon not supported for target");
+		return -1;
+	}
+
+	if (pass == 1) {
+		id = (char *)queue_remove(id_queue);
+		free(id);
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	newc = malloc(sizeof(*newc));
+	if (!newc) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(newc, 0, sizeof(*newc));
+
+	id = queue_remove(id_queue);
+	if (!id) {
+		yyerror("failed to read the subnet prefix");
+		rc = -1;
+		goto out;
+	}
+
+	rc = inet_pton(AF_INET6, id, &subnet_prefix);
+	free(id);
+	if (rc < 1) {
+		yyerror("failed to parse the subnet prefix");
+		if (rc == 0)
+			rc = -1;
+		goto out;
+	}
+
+	if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) {
+		yyerror("subnet prefix should be 0's in the low order 64 bits.");
+		rc = -1;
+		goto out;
+	}
+
+	if (low > 0xffff || high > 0xffff) {
+		yyerror("pkey value too large, pkeys are 16 bits.");
+		rc = -1;
+		goto out;
+	}
+
+	memcpy(&newc->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0],
+	       sizeof(newc->u.ibpkey.subnet_prefix));
+
+	newc->u.ibpkey.low_pkey = low;
+	newc->u.ibpkey.high_pkey = high;
+
+	if (low > high) {
+		yyerror2("low pkey %d exceeds high pkey %d", low, high);
+		rc = -1;
+		goto out;
+	}
+
+	rc = parse_security_context(&newc->context[0]);
+	if (rc)
+		goto out;
+
+	/* Preserve the matching order specified in the configuration. */
+	head = policydbp->ocontexts[OCON_IBPKEY];
+	for (l = NULL, c = head; c; l = c, c = c->next) {
+		unsigned int low2, high2;
+
+		low2 = c->u.ibpkey.low_pkey;
+		high2 = c->u.ibpkey.high_pkey;
+
+		if (low == low2 && high == high2 &&
+		    c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
+			yyerror2("duplicate ibpkeycon entry for %d-%d ",
+				 low, high);
+			rc = -1;
+			goto out;
+		}
+		if (low2 <= low && high2 >= high &&
+		    c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
+			yyerror2("ibpkeycon entry for %d-%d hidden by earlier entry for %d-%d",
+				 low, high, low2, high2);
+			rc = -1;
+			goto out;
+		}
+	}
+
+	if (l)
+		l->next = newc;
+	else
+		policydbp->ocontexts[OCON_IBPKEY] = newc;
+
+	return 0;
+
+out:
+	free(newc);
+	return rc;
+}
+
+int define_ibendport_context(unsigned int port)
+{
+	ocontext_t *newc, *c, *l, *head;
+	char *id;
+	int rc = 0;
+
+	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+		yyerror("ibendportcon not supported for target");
+		return -1;
+	}
+
+	if (pass == 1) {
+		id = (char *)queue_remove(id_queue);
+		free(id);
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	if (port > 0xff || port == 0) {
+		yyerror("Invalid ibendport port number, should be 0 < port < 256");
+		return -1;
+	}
+
+	newc = malloc(sizeof(*newc));
+	if (!newc) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(newc, 0, sizeof(*newc));
+
+	newc->u.ibendport.dev_name = queue_remove(id_queue);
+	if (!newc->u.ibendport.dev_name) {
+		yyerror("failed to read infiniband device name.");
+		rc = -1;
+		goto out;
+	}
+
+	if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) {
+		yyerror("infiniband device name exceeds max length of 63.");
+		rc = -1;
+		goto out;
+	}
+
+	newc->u.ibendport.port = port;
+
+	if (parse_security_context(&newc->context[0])) {
+		free(newc);
+		return -1;
+	}
+
+	/* Preserve the matching order specified in the configuration. */
+	head = policydbp->ocontexts[OCON_IBENDPORT];
+	for (l = NULL, c = head; c; l = c, c = c->next) {
+		unsigned int port2;
+
+		port2 = c->u.ibendport.port;
+
+		if (port == port2 &&
+		    !strcmp(c->u.ibendport.dev_name,
+			     newc->u.ibendport.dev_name)) {
+			yyerror2("duplicate ibendportcon entry for %s port %u",
+				 newc->u.ibendport.dev_name, port);
+			rc = -1;
+			goto out;
+		}
+	}
+
+	if (l)
+		l->next = newc;
+	else
+		policydbp->ocontexts[OCON_IBENDPORT] = newc;
+
+	return 0;
+
+out:
+	free(newc->u.ibendport.dev_name);
+	free(newc);
+	return rc;
+}
+
 int define_netif_context(void)
 {
 	ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 9f4b6d0..50a7ba7 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -43,6 +43,8 @@
 int define_netif_context(void);
 int define_permissive(void);
 int define_polcap(void);
+int define_ibpkey_context(unsigned int low, unsigned int high);
+int define_ibendport_context(unsigned int port);
 int define_port_context(unsigned int low, unsigned int high);
 int define_pirq_context(unsigned int pirq);
 int define_iomem_context(uint64_t low, uint64_t high);
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index 1ac1c96..6b406c8 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -21,6 +21,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2008 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  *	This program is free software; you can redistribute it and/or modify
  *  	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation, version 2.
@@ -135,6 +136,8 @@
 %token TARGET
 %token SAMEUSER
 %token FSCON PORTCON NETIFCON NODECON 
+%token IBPKEYCON
+%token IBENDPORTCON
 %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
 %token FSUSEXATTR FSUSETASK FSUSETRANS
 %token GENFSCON
@@ -170,7 +173,7 @@
 			  opt_default_rules opt_mls te_rbac users opt_constraints 
                          { if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;}
 			   else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1;}}
-			  initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts
+			  initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts opt_ibendport_contexts
 			;
 classes			: class_def 
 			| classes class_def
@@ -700,7 +703,7 @@
 fs_context_def		: FSCON number number security_context_def security_context_def
 			{if (define_fs_context($2,$3)) return -1;}
 			;
-net_contexts		: opt_port_contexts opt_netif_contexts opt_node_contexts 
+net_contexts		: opt_port_contexts opt_netif_contexts opt_node_contexts
 			;
 opt_port_contexts       : port_contexts
                         |
@@ -713,6 +716,26 @@
 			| PORTCON identifier number '-' number security_context_def
 			{if (define_port_context($3,$5)) return -1;}
 			;
+opt_ibpkey_contexts     : ibpkey_contexts
+                        |
+                        ;
+ibpkey_contexts		: ibpkey_context_def
+			| ibpkey_contexts ibpkey_context_def
+			;
+ibpkey_context_def	: IBPKEYCON ipv6_addr number security_context_def
+			{if (define_ibpkey_context($3,$3)) return -1;}
+			| IBPKEYCON ipv6_addr number '-' number security_context_def
+			{if (define_ibpkey_context($3,$5)) return -1;}
+			;
+opt_ibendport_contexts	: ibendport_contexts
+			|
+			;
+ibendport_contexts	: ibendport_context_def
+                        | ibendport_contexts ibendport_context_def
+                        ;
+ibendport_context_def	: IBENDPORTCON identifier number security_context_def
+                        {if (define_ibendport_context($3)) return -1;}
+                        ;
 opt_netif_contexts      : netif_contexts 
                         |
                         ;
diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
index 028bd25..e6c4898 100644
--- a/checkpolicy/policy_scan.l
+++ b/checkpolicy/policy_scan.l
@@ -12,6 +12,7 @@
  *	Added support for binary policy modules
  *
  * Copyright (C) 2003-5 Tresys Technology, LLC
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  *	This program is free software; you can redistribute it and/or modify
  *  	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation, version 2.
@@ -183,6 +184,10 @@
 incomp				{ return(INCOMP);}
 fscon |
 FSCON                           { return(FSCON);}
+ibpkeycon |
+IBPKEYCON			{ return(IBPKEYCON);}
+ibendportcon |
+IBENDPORTCON			{ return(IBENDPORTCON);}
 portcon |
 PORTCON				{ return(PORTCON);}
 netifcon |                     
diff --git a/checkpolicy/test/Makefile b/checkpolicy/test/Makefile
index 0a31c5e..59fa446 100644
--- a/checkpolicy/test/Makefile
+++ b/checkpolicy/test/Makefile
@@ -2,7 +2,7 @@
 # Makefile for building the dispol program
 #
 PREFIX ?= $(DESTDIR)/usr
-BINDIR=$(PREFIX)/bin
+BINDIR ?= $(PREFIX)/bin
 LIBDIR ?= $(PREFIX)/lib
 INCLUDEDIR ?= $(PREFIX)/include
 LIBSEPOLA ?= $(LIBDIR)/libsepol.a
diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
index aac13e1..d5c7eea 100644
--- a/checkpolicy/test/dismod.c
+++ b/checkpolicy/test/dismod.c
@@ -243,6 +243,13 @@
 		}
 	} else if (avrule->specified & AVRULE_NEVERALLOW) {
 		fprintf(fp, "  neverallow");
+	} else if (avrule->specified & AVRULE_XPERMS) {
+		if (avrule->specified & AVRULE_XPERMS_ALLOWED)
+			fprintf(fp, "allowxperm ");
+		else if (avrule->specified & AVRULE_XPERMS_AUDITALLOW)
+			fprintf(fp, "auditallowxperm ");
+		else if (avrule->specified & AVRULE_XPERMS_DONTAUDIT)
+			fprintf(fp, "dontauditxperm ");
 	} else {
 		fprintf(fp, "     ERROR: no valid rule type specified\n");
 		return -1;
@@ -282,6 +289,24 @@
 				   policy, fp);
 	} else if (avrule->specified & AVRULE_TYPE) {
 		display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
+	} else if (avrule->specified & AVRULE_XPERMS) {
+		avtab_extended_perms_t xperms;
+		int i;
+
+		if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLFUNCTION)
+			xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION;
+		else if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLDRIVER)
+			xperms.specified = AVTAB_XPERMS_IOCTLDRIVER;
+		else {
+			fprintf(fp, "     ERROR: no valid xperms specified\n");
+			return -1;
+		}
+
+		xperms.driver = avrule->xperms->driver;
+		for (i = 0; i < EXTENDED_PERMS_LEN; i++)
+			xperms.perms[i] = avrule->xperms->perms[i];
+
+		fprintf(fp, "%s", sepol_extended_perms_to_string(&xperms));
 	}
 
 	fprintf(fp, ";\n");
diff --git a/dbus/VERSION b/dbus/VERSION
index 5154b3f..1effb00 100644
--- a/dbus/VERSION
+++ b/dbus/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/gui/Makefile b/gui/Makefile
index d49a7ce..4fc2c1a 100644
--- a/gui/Makefile
+++ b/gui/Makefile
@@ -1,6 +1,5 @@
 # Installation directories.
 PREFIX ?= ${DESTDIR}/usr
-SYSCONFDIR ?= ${DESTDIR}/etc
 BINDIR ?= $(PREFIX)/bin
 SHAREDIR ?= $(PREFIX)/share/system-config-selinux
 DATADIR ?= $(PREFIX)/share
@@ -30,7 +29,6 @@
 	-mkdir -p $(BINDIR)
 	-mkdir -p $(DATADIR)/pixmaps
 	-mkdir -p $(DATADIR)/icons/hicolor/24x24/apps
-	-mkdir -p $(SYSCONFDIR)
 	-mkdir -p $(DATADIR)/polkit-1/actions/
 	install -m 755 system-config-selinux.py $(SHAREDIR)
 	install -m 755 system-config-selinux $(BINDIR)
diff --git a/gui/VERSION b/gui/VERSION
index 5154b3f..1effb00 100644
--- a/gui/VERSION
+++ b/gui/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/libselinux/VERSION b/libselinux/VERSION
index 5154b3f..1effb00 100644
--- a/libselinux/VERSION
+++ b/libselinux/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index 4306dd0..2408fae 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -17,7 +17,7 @@
 PYSITEDIR ?= $(DESTDIR)$(shell $(PYTHON) -c 'import site; print(site.getsitepackages()[0])')
 PYCEXT ?= $(shell $(PYTHON) -c 'import imp;print([s for s,m,t in imp.get_suffixes() if t == imp.C_EXTENSION][0])')
 RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]')
-RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -lruby"')
+RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]')
 RUBYINSTALL ?= $(DESTDIR)$(shell $(RUBY) -e 'puts RbConfig::CONFIG["vendorarchdir"]')
 LIBBASE ?= $(shell basename $(LIBDIR))
 LIBSEPOLA ?= $(LIBDIR)/libsepol.a
@@ -59,7 +59,7 @@
 EXTRA_CFLAGS = -fipa-pure-const -Wlogical-op -Wpacked-bitfield-compat -Wsync-nand \
 	-Wcoverage-mismatch -Wcpp -Wformat-contains-nul -Wnormalized=nfc -Wsuggest-attribute=const \
 	-Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wtrampolines -Wjump-misses-init \
-	-Wno-suggest-attribute=pure -Wno-suggest-attribute=const -Wp,-D_FORTIFY_SOURCE=2
+	-Wno-suggest-attribute=pure -Wno-suggest-attribute=const -Wp,-D_FORTIFY_SOURCE
 else
 EXTRA_CFLAGS = -Wunused-command-line-argument
 endif
diff --git a/libselinux/src/label.c b/libselinux/src/label.c
index 8e0a862..c051e9f 100644
--- a/libselinux/src/label.c
+++ b/libselinux/src/label.c
@@ -60,113 +60,6 @@
 	CONFIG_ANDROID_BACKEND(selabel_service_init),
 };
 
-static void selabel_subs_fini(struct selabel_sub *ptr)
-{
-	struct selabel_sub *next;
-
-	while (ptr) {
-		next = ptr->next;
-		free(ptr->src);
-		free(ptr->dst);
-		free(ptr);
-		ptr = next;
-	}
-}
-
-static char *selabel_sub(struct selabel_sub *ptr, const char *src)
-{
-	char *dst = NULL;
-	int len;
-
-	while (ptr) {
-		if (strncmp(src, ptr->src, ptr->slen) == 0 ) {
-			if (src[ptr->slen] == '/' || 
-			    src[ptr->slen] == 0) {
-				if ((src[ptr->slen] == '/') &&
-				    (strcmp(ptr->dst, "/") == 0))
-					len = ptr->slen + 1;
-				else
-					len = ptr->slen;
-				if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0)
-					return NULL;
-				return dst;
-			}
-		}
-		ptr = ptr->next;
-	}
-	return NULL;
-}
-
-struct selabel_sub *selabel_subs_init(const char *path,
-					    struct selabel_sub *list,
-					    struct selabel_digest *digest)
-{
-	char buf[1024];
-	FILE *cfg = fopen(path, "re");
-	struct selabel_sub *sub = NULL;
-	struct stat sb;
-
-	if (!cfg)
-		return list;
-
-	if (fstat(fileno(cfg), &sb) < 0)
-		return list;
-
-	while (fgets_unlocked(buf, sizeof(buf) - 1, cfg)) {
-		char *ptr = NULL;
-		char *src = buf;
-		char *dst = NULL;
-
-		while (*src && isspace(*src))
-			src++;
-		if (src[0] == '#') continue;
-		ptr = src;
-		while (*ptr && ! isspace(*ptr))
-			ptr++;
-		*ptr++ = '\0';
-		if (! *src) continue;
-
-		dst = ptr;
-		while (*dst && isspace(*dst))
-			dst++;
-		ptr=dst;
-		while (*ptr && ! isspace(*ptr))
-			ptr++;
-		*ptr='\0';
-		if (! *dst)
-			continue;
-
-		sub = malloc(sizeof(*sub));
-		if (! sub)
-			goto err;
-		memset(sub, 0, sizeof(*sub));
-
-		sub->src=strdup(src);
-		if (! sub->src)
-			goto err;
-
-		sub->dst=strdup(dst);
-		if (! sub->dst)
-			goto err;
-
-		sub->slen = strlen(src);
-		sub->next = list;
-		list = sub;
-	}
-
-	if (digest_add_specfile(digest, cfg, NULL, sb.st_size, path) < 0)
-		goto err;
-
-out:
-	fclose(cfg);
-	return list;
-err:
-	if (sub)
-		free(sub->src);
-	free(sub);
-	goto out;
-}
-
 static inline struct selabel_digest *selabel_is_digest_set
 				    (const struct selinux_opt *opts,
 				    unsigned n,
@@ -252,27 +145,6 @@
 }
 
 /* Public API helpers */
-static char *selabel_sub_key(struct selabel_handle *rec, const char *key)
-{
-	char *ptr = NULL;
-	char *dptr = NULL;
-
-	ptr = selabel_sub(rec->subs, key);
-	if (ptr) {
-		dptr = selabel_sub(rec->dist_subs, ptr);
-		if (dptr) {
-			free(ptr);
-			ptr = dptr;
-		}
-	} else {
-		ptr = selabel_sub(rec->dist_subs, key);
-	}
-	if (ptr)
-		return ptr;
-
-	return NULL;
-}
-
 static int selabel_fini(struct selabel_handle *rec,
 			    struct selabel_lookup_rec *lr,
 			    int translating)
@@ -296,20 +168,13 @@
 		      const char *key, int type)
 {
 	struct selabel_lookup_rec *lr;
-	char *ptr = NULL;
 
 	if (key == NULL) {
 		errno = EINVAL;
 		return NULL;
 	}
 
-	ptr = selabel_sub_key(rec, key);
-	if (ptr) {
-		lr = rec->func_lookup(rec, ptr, type);
-		free(ptr);
-	} else {
-		lr = rec->func_lookup(rec, key, type);
-	}
+	lr = rec->func_lookup(rec, key, type);
 	if (!lr)
 		return NULL;
 
@@ -324,20 +189,13 @@
 		      const char *key, int type, const char **aliases)
 {
 	struct selabel_lookup_rec *lr;
-	char *ptr = NULL;
 
 	if (key == NULL) {
 		errno = EINVAL;
 		return NULL;
 	}
 
-	ptr = selabel_sub_key(rec, key);
-	if (ptr) {
-		lr = rec->func_lookup_best_match(rec, ptr, aliases, type);
-		free(ptr);
-	} else {
-		lr = rec->func_lookup_best_match(rec, key, aliases, type);
-	}
+	lr = rec->func_lookup_best_match(rec, key, aliases, type);
 	if (!lr)
 		return NULL;
 
@@ -375,8 +233,6 @@
 	rec->backend = backend;
 	rec->validating = selabel_is_validate_set(opts, nopts);
 
-	rec->subs = NULL;
-	rec->dist_subs = NULL;
 	rec->digest = selabel_is_digest_set(opts, nopts, rec->digest);
 
 	if ((*initfuncs[backend])(rec, opts, nopts)) {
@@ -415,9 +271,6 @@
 
 bool selabel_partial_match(struct selabel_handle *rec, const char *key)
 {
-	char *ptr;
-	bool ret;
-
 	if (!rec->func_partial_match) {
 		/*
 		 * If the label backend does not support partial matching,
@@ -426,15 +279,7 @@
 		return true;
 	}
 
-	ptr = selabel_sub_key(rec, key);
-	if (ptr) {
-		ret = rec->func_partial_match(rec, ptr);
-		free(ptr);
-	} else {
-		ret = rec->func_partial_match(rec, key);
-	}
-
-	return ret;
+	return rec->func_partial_match(rec, key);
 }
 
 int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
@@ -501,8 +346,7 @@
 void selabel_close(struct selabel_handle *rec)
 {
 	size_t i;
-	selabel_subs_fini(rec->subs);
-	selabel_subs_fini(rec->dist_subs);
+
 	if (rec->spec_files) {
 		for (i = 0; i < rec->spec_files_len; i++)
 			free(rec->spec_files[i]);
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 70f6838..b3b36bc 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -389,10 +389,12 @@
 			spec->prefix_len = prefix_len;
 		}
 
-		rc = regex_load_mmap(mmap_area, &spec->regex, reg_arch_matches);
+		rc = regex_load_mmap(mmap_area, &spec->regex, reg_arch_matches,
+				     &spec->regex_compiled);
 		if (rc < 0)
 			goto out;
 
+		__pthread_mutex_init(&spec->regex_lock, NULL);
 		data->nspec++;
 	}
 
@@ -559,6 +561,148 @@
 	return -1;
 }
 
+static void selabel_subs_fini(struct selabel_sub *ptr)
+{
+	struct selabel_sub *next;
+
+	while (ptr) {
+		next = ptr->next;
+		free(ptr->src);
+		free(ptr->dst);
+		free(ptr);
+		ptr = next;
+	}
+}
+
+static char *selabel_sub(struct selabel_sub *ptr, const char *src)
+{
+	char *dst = NULL;
+	int len;
+
+	while (ptr) {
+		if (strncmp(src, ptr->src, ptr->slen) == 0 ) {
+			if (src[ptr->slen] == '/' ||
+			    src[ptr->slen] == 0) {
+				if ((src[ptr->slen] == '/') &&
+				    (strcmp(ptr->dst, "/") == 0))
+					len = ptr->slen + 1;
+				else
+					len = ptr->slen;
+				if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0)
+					return NULL;
+				return dst;
+			}
+		}
+		ptr = ptr->next;
+	}
+	return NULL;
+}
+
+static int selabel_subs_init(const char *path, struct selabel_digest *digest,
+		       struct selabel_sub **out_subs)
+{
+	char buf[1024];
+	FILE *cfg = fopen(path, "re");
+	struct selabel_sub *list = NULL, *sub = NULL;
+	struct stat sb;
+	int status = -1;
+
+	*out_subs = NULL;
+	if (!cfg) {
+		/* If the file does not exist, it is not fatal */
+		return (errno == ENOENT) ? 0 : -1;
+	}
+
+	if (fstat(fileno(cfg), &sb) < 0)
+		goto out;
+
+	while (fgets_unlocked(buf, sizeof(buf) - 1, cfg)) {
+		char *ptr = NULL;
+		char *src = buf;
+		char *dst = NULL;
+
+		while (*src && isspace(*src))
+			src++;
+		if (src[0] == '#') continue;
+		ptr = src;
+		while (*ptr && ! isspace(*ptr))
+			ptr++;
+		*ptr++ = '\0';
+		if (! *src) continue;
+
+		dst = ptr;
+		while (*dst && isspace(*dst))
+			dst++;
+		ptr=dst;
+		while (*ptr && ! isspace(*ptr))
+			ptr++;
+		*ptr='\0';
+		if (! *dst)
+			continue;
+
+		sub = malloc(sizeof(*sub));
+		if (! sub)
+			goto err;
+		memset(sub, 0, sizeof(*sub));
+
+		sub->src=strdup(src);
+		if (! sub->src)
+			goto err;
+
+		sub->dst=strdup(dst);
+		if (! sub->dst)
+			goto err;
+
+		sub->slen = strlen(src);
+		sub->next = list;
+		list = sub;
+		sub = NULL;
+	}
+
+	if (digest_add_specfile(digest, cfg, NULL, sb.st_size, path) < 0)
+		goto err;
+
+	*out_subs = list;
+	status = 0;
+
+out:
+	fclose(cfg);
+	return status;
+err:
+	if (sub)
+		free(sub->src);
+	free(sub);
+	while (list) {
+		sub = list->next;
+		free(list->src);
+		free(list->dst);
+		free(list);
+		list = sub;
+	}
+	goto out;
+}
+
+static char *selabel_sub_key(struct saved_data *data, const char *key)
+{
+	char *ptr = NULL;
+	char *dptr = NULL;
+
+	ptr = selabel_sub(data->subs, key);
+	if (ptr) {
+		dptr = selabel_sub(data->dist_subs, ptr);
+		if (dptr) {
+			free(ptr);
+			ptr = dptr;
+		}
+	} else {
+		ptr = selabel_sub(data->dist_subs, key);
+	}
+	if (ptr)
+		return ptr;
+
+	return NULL;
+}
+
 static void closef(struct selabel_handle *rec);
 
 static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
@@ -620,20 +764,30 @@
 	char subs_file[PATH_MAX + 1];
 	/* Process local and distribution substitution files */
 	if (!path_provided) {
-		rec->dist_subs =
-		    selabel_subs_init(selinux_file_context_subs_dist_path(),
-		    rec->dist_subs, rec->digest);
-		rec->subs = selabel_subs_init(selinux_file_context_subs_path(),
-		    rec->subs, rec->digest);
+		status = selabel_subs_init(
+			selinux_file_context_subs_dist_path(),
+			rec->digest, &data->dist_subs);
+		if (status)
+			goto finish;
+		status = selabel_subs_init(selinux_file_context_subs_path(),
+			rec->digest, &data->subs);
+		if (status)
+			goto finish;
 		rec->spec_files[0] = strdup(selinux_file_context_path());
 		if (rec->spec_files[0] == NULL)
 			goto finish;
 	} else {
 		for (i = 0; i < num_paths; i++) {
 			snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", rec->spec_files[i]);
-			rec->dist_subs = selabel_subs_init(subs_file, rec->dist_subs, rec->digest);
+			status = selabel_subs_init(subs_file, rec->digest,
+					   &data->dist_subs);
+			if (status)
+				goto finish;
 			snprintf(subs_file, sizeof(subs_file), "%s.subs", rec->spec_files[i]);
-			rec->subs = selabel_subs_init(subs_file, rec->subs, rec->digest);
+			status = selabel_subs_init(subs_file, rec->digest,
+					   &data->subs);
+			if (status)
+				goto finish;
 		}
 	}
 #else
@@ -698,11 +852,15 @@
 	/* make sure successive ->func_close() calls are harmless */
 	rec->data = NULL;
 
+	selabel_subs_fini(data->subs);
+	selabel_subs_fini(data->dist_subs);
+
 	for (i = 0; i < data->nspec; i++) {
 		spec = &data->spec_arr[i];
 		free(spec->lr.ctx_trans);
 		free(spec->lr.ctx_raw);
 		regex_data_free(spec->regex);
+		__pthread_mutex_destroy(&spec->regex_lock);
 		if (spec->from_mmap)
 			continue;
 		free(spec->regex_str);
@@ -745,6 +903,7 @@
 	char *clean_key = NULL;
 	const char *prev_slash, *next_slash;
 	unsigned int sofar = 0;
+	char *sub = NULL;
 
 	if (!data->nspec) {
 		errno = ENOENT;
@@ -767,6 +926,10 @@
 		key = clean_key;
 	}
 
+	sub = selabel_sub_key(data, key);
+	if (sub)
+		key = sub;
+
 	buf = key;
 	file_stem = find_stem_from_file(data, &buf);
 	mode &= S_IFMT;
@@ -815,6 +978,7 @@
 
 finish:
 	free(clean_key);
+	free(sub);
 	return ret;
 }
 
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 4ac64d5..aa576d8 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -2,6 +2,7 @@
 #define _SELABEL_FILE_H_
 
 #include <errno.h>
+#include <pthread.h>
 #include <string.h>
 
 #include <sys/stat.h>
@@ -16,6 +17,7 @@
 
 #include "callbacks.h"
 #include "label_internal.h"
+#include "selinux_internal.h"
 
 #define SELINUX_MAGIC_COMPILED_FCONTEXT	0xf97cff8a
 
@@ -29,12 +31,21 @@
 #define SELINUX_COMPILED_FCONTEXT_MAX_VERS \
 	SELINUX_COMPILED_FCONTEXT_REGEX_ARCH
 
+struct selabel_sub {
+	char *src;
+	int slen;
+	char *dst;
+	struct selabel_sub *next;
+};
+
 /* A file security context specification. */
 struct spec {
 	struct selabel_lookup_rec lr;	/* holds contexts for lookup result */
 	char *regex_str;	/* regular expession string for diagnostics */
 	char *type_str;		/* type string for diagnostic messages */
 	struct regex_data * regex; /* backend dependent regular expression data */
+	bool regex_compiled; /* bool to indicate if the regex is compiled */
+	pthread_mutex_t regex_lock; /* lock for lazy compilation of regex */
 	mode_t mode;		/* mode format value */
 	int matches;		/* number of matching pathnames */
 	int stem_id;		/* indicates which stem-compression item */
@@ -76,6 +87,10 @@
 	int num_stems;
 	int alloc_stems;
 	struct mmap_area *mmap_areas;
+
+	/* substitution support */
+	struct selabel_sub *dist_subs;
+	struct selabel_sub *subs;
 };
 
 static inline mode_t string_to_mode(char *mode)
@@ -328,9 +343,27 @@
 	struct stem *stem_arr = data->stem_arr;
 	size_t len;
 	int rc;
+	bool regex_compiled;
 
-	if (spec->regex)
+	/* We really want pthread_once() here, but since its
+	 * init_routine does not take a parameter, it's not possible
+	 * to use, so we generate the same effect with atomics and a
+	 * mutex */
+	regex_compiled =
+		__atomic_load_n(&spec->regex_compiled, __ATOMIC_ACQUIRE);
+	if (regex_compiled) {
 		return 0; /* already done */
+	}
+
+	__pthread_mutex_lock(&spec->regex_lock);
+	/* Check if another thread compiled the regex while we waited
+	 * on the mutex */
+	regex_compiled =
+		__atomic_load_n(&spec->regex_compiled, __ATOMIC_ACQUIRE);
+	if (regex_compiled) {
+		__pthread_mutex_unlock(&spec->regex_lock);
+		return 0;
+	}
 
 	/* Skip the fixed stem. */
 	reg_buf = spec->regex_str;
@@ -343,6 +376,7 @@
 	if (!anchored_regex) {
 		if (errbuf)
 			*errbuf = "out of memory";
+		__pthread_mutex_unlock(&spec->regex_lock);
 		return -1;
 	}
 
@@ -363,10 +397,13 @@
 					sizeof(regex_error_format_buffer));
 			*errbuf = &regex_error_format_buffer[0];
 		}
+		__pthread_mutex_unlock(&spec->regex_lock);
 		return -1;
 	}
 
 	/* Done. */
+	__atomic_store_n(&spec->regex_compiled, true, __ATOMIC_RELEASE);
+	__pthread_mutex_unlock(&spec->regex_lock);
 	return 0;
 }
 
@@ -428,6 +465,8 @@
 	/* process and store the specification in spec. */
 	spec_arr[nspec].stem_id = find_stem_from_spec(data, regex);
 	spec_arr[nspec].regex_str = regex;
+	__pthread_mutex_init(&spec_arr[nspec].regex_lock, NULL);
+	spec_arr[nspec].regex_compiled = false;
 
 	spec_arr[nspec].type_str = type;
 	spec_arr[nspec].mode = 0;
diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h
index 62c1720..6810018 100644
--- a/libselinux/src/label_internal.h
+++ b/libselinux/src/label_internal.h
@@ -46,12 +46,6 @@
 /*
  * Labeling internal structures
  */
-struct selabel_sub {
-	char *src;
-	int slen;
-	char *dst;
-	struct selabel_sub *next;
-};
 
 /*
  * Calculate an SHA1 hash of all the files used to build the specs.
@@ -75,10 +69,6 @@
 						    const char *path);
 extern void digest_gen_hash(struct selabel_digest *digest);
 
-extern struct selabel_sub *selabel_subs_init(const char *path,
-				    struct selabel_sub *list,
-				    struct selabel_digest *digest);
-
 struct selabel_lookup_rec {
 	char * ctx_raw;
 	char * ctx_trans;
@@ -115,9 +105,6 @@
 	char **spec_files;
 
 
-	/* substitution support */
-	struct selabel_sub *dist_subs;
-	struct selabel_sub *subs;
 	/* ptr to SHA1 hash information if SELABEL_OPT_DIGEST set */
 	struct selabel_digest *digest;
 };
diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c
index 7f08311..e9f1264 100644
--- a/libselinux/src/load_policy.c
+++ b/libselinux/src/load_policy.c
@@ -449,8 +449,11 @@
 		}
 	}
 
-	if (seconfig == -1)
+	if (seconfig == -1) {
+		umount(selinux_mnt);
+		fini_selinuxmnt();
 		goto noload;
+	}
 
 	/* Load the policy. */
 	return selinux_mkload_policy(0);
diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c
index 0c5ad27..dfc15d6 100644
--- a/libselinux/src/regex.c
+++ b/libselinux/src/regex.c
@@ -1,10 +1,12 @@
 #include <assert.h>
+#include <pthread.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
 
 #include "regex.h"
 #include "label_file.h"
+#include "selinux_internal.h"
 
 #ifdef USE_PCRE2
 #define REGEX_ARCH_SIZE_T PCRE2_SIZE
@@ -63,6 +65,7 @@
 	 * pattern in pcre2
 	 */
 	pcre2_match_data *match_data;
+	pthread_mutex_t match_mutex;
 };
 
 int regex_prepare_data(struct regex_data **regex, char const *pattern_string,
@@ -106,11 +109,12 @@
 }
 
 int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex,
-		    int do_load_precompregex)
+		    int do_load_precompregex, bool *regex_compiled)
 {
 	int rc;
 	uint32_t entry_len;
 
+	*regex_compiled = false;
 	rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
 	if (rc < 0)
 		return -1;
@@ -138,6 +142,8 @@
 		    pcre2_match_data_create_from_pattern((*regex)->regex, NULL);
 		if (!(*regex)->match_data)
 			goto err;
+
+		*regex_compiled = true;
 	}
 
 	/* and skip the decoded bit */
@@ -199,6 +205,7 @@
 			pcre2_code_free(regex->regex);
 		if (regex->match_data)
 			pcre2_match_data_free(regex->match_data);
+		__pthread_mutex_destroy(&regex->match_mutex);
 		free(regex);
 	}
 }
@@ -206,9 +213,11 @@
 int regex_match(struct regex_data *regex, char const *subject, int partial)
 {
 	int rc;
+	__pthread_mutex_lock(&regex->match_mutex);
 	rc = pcre2_match(
 	    regex->regex, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0,
 	    partial ? PCRE2_PARTIAL_SOFT : 0, regex->match_data, NULL);
+	__pthread_mutex_unlock(&regex->match_mutex);
 	if (rc > 0)
 		return REGEX_MATCH;
 	switch (rc) {
@@ -244,6 +253,14 @@
 	return SELABEL_EQUAL;
 }
 
+struct regex_data *regex_data_create(void)
+{
+	struct regex_data *regex_data =
+		(struct regex_data *)calloc(1, sizeof(struct regex_data));
+	__pthread_mutex_init(&regex_data->match_mutex, NULL);
+	return regex_data;
+}
+
 #else // !USE_PCRE2
 char const *regex_arch_string(void)
 {
@@ -302,7 +319,7 @@
 }
 
 int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex,
-		    int unused __attribute__((unused)))
+		    int unused __attribute__((unused)), bool *regex_compiled)
 {
 	int rc;
 	uint32_t entry_len;
@@ -347,6 +364,8 @@
 		if (rc < 0 || info_len != entry_len)
 			goto err;
 	}
+
+	*regex_compiled = true;
 	return 0;
 
 err:
@@ -472,13 +491,13 @@
 	return SELABEL_EQUAL;
 }
 
-#endif
-
 struct regex_data *regex_data_create(void)
 {
 	return (struct regex_data *)calloc(1, sizeof(struct regex_data));
 }
 
+#endif
+
 void regex_format_error(struct regex_error_data const *error_data, char *buffer,
 			size_t buf_size)
 {
@@ -539,12 +558,16 @@
 	/* no break statements, fall-through is intended */
 	case 4:
 		*ptr++ = '.';
+		/* FALLTHRU */
 	case 3:
 		*ptr++ = '.';
+		/* FALLTHRU */
 	case 2:
 		*ptr++ = '.';
+		/* FALLTHRU */
 	case 1:
 		*ptr++ = '\0';
+		/* FALLTHRU */
 	default:
 		break;
 	}
diff --git a/libselinux/src/regex.h b/libselinux/src/regex.h
index 186c5ec..eb8ca50 100644
--- a/libselinux/src/regex.h
+++ b/libselinux/src/regex.h
@@ -1,6 +1,7 @@
 #ifndef SRC_REGEX_H_
 #define SRC_REGEX_H_
 
+#include <stdbool.h>
 #include <stdio.h>
 
 #ifdef USE_PCRE2
@@ -98,13 +99,17 @@
  *            with regex_data_create and must be freed with regex_data_free.
  * @arg do_load_precompregex If non-zero precompiled patterns get loaded from
  *			     the mmap region (ignored by PCRE1 back-end).
+ * @arg regex_compiled Set to true if a precompiled pattern was loaded
+ * 		       into regex, otherwise set to false to indicate later
+ *		       compilation must occur
  *
  * @retval 0 on success
  * @retval -1 on error
  */
 int regex_load_mmap(struct mmap_area *map_area,
 		    struct regex_data **regex,
-		    int do_load_precompregex) hidden;
+		    int do_load_precompregex,
+		    bool *regex_compiled) hidden;
 /**
  * This function stores a precompiled regular expression to a file.
  * In the case of PCRE, it just dumps the binary representation of the
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
index 54949c1..dfc421c 100644
--- a/libselinux/src/selinux_internal.h
+++ b/libselinux/src/selinux_internal.h
@@ -144,6 +144,38 @@
 			pthread_setspecific(KEY, VALUE);	\
 	} while (0)
 
+/* selabel_lookup() is only thread safe if we're compiled with pthreads */
+
+#pragma weak pthread_mutex_init
+#pragma weak pthread_mutex_destroy
+#pragma weak pthread_mutex_lock
+#pragma weak pthread_mutex_unlock
+
+#define __pthread_mutex_init(LOCK, ATTR) 			\
+	do {							\
+		if (pthread_mutex_init != NULL)			\
+			pthread_mutex_init(LOCK, ATTR);		\
+	} while (0)
+
+#define __pthread_mutex_destroy(LOCK) 				\
+	do {							\
+		if (pthread_mutex_destroy != NULL)		\
+			pthread_mutex_destroy(LOCK);		\
+	} while (0)
+
+#define __pthread_mutex_lock(LOCK) 				\
+	do {							\
+		if (pthread_mutex_lock != NULL)			\
+			pthread_mutex_lock(LOCK);		\
+	} while (0)
+
+#define __pthread_mutex_unlock(LOCK) 				\
+	do {							\
+		if (pthread_mutex_unlock != NULL)		\
+			pthread_mutex_unlock(LOCK);		\
+	} while (0)
+
+
 #define SELINUXDIR "/etc/selinux/"
 #define SELINUXCONFIG SELINUXDIR "config"
 
diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile
index 14f94bd..eb4851a 100644
--- a/libselinux/utils/Makefile
+++ b/libselinux/utils/Makefile
@@ -1,7 +1,7 @@
 # Installation directories.
 PREFIX ?= $(DESTDIR)/usr
 LIBDIR ?= $(PREFIX)/lib
-USRSBINDIR ?= $(PREFIX)/sbin
+SBINDIR ?= $(PREFIX)/sbin
 INCLUDEDIR ?= $(PREFIX)/include
 
 OS ?= $(shell uname)
@@ -32,7 +32,7 @@
           -Wformat-extra-args -Wformat-zero-length -Wformat=2 -Wmultichar \
           -Woverflow -Wpointer-to-int-cast -Wpragmas \
           -Wno-missing-field-initializers -Wno-sign-compare \
-          -Wno-format-nonliteral -Wframe-larger-than=$(MAX_STACK_SIZE) -Wp,-D_FORTIFY_SOURCE=2 \
+          -Wno-format-nonliteral -Wframe-larger-than=$(MAX_STACK_SIZE) -Wp,-D_FORTIFY_SOURCE \
           -fstack-protector-all --param=ssp-buffer-size=4 -fexceptions \
           -fasynchronous-unwind-tables -fdiagnostics-show-option -funit-at-a-time \
           -Werror -Wno-aggregate-return -Wno-redundant-decls \
@@ -46,14 +46,14 @@
 endif
 
 override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS)
-LDFLAGS += -L../src
-LDLIBS += -lselinux
+override LDFLAGS += -L../src
+override LDLIBS += -lselinux
 PCRE_LDLIBS ?= -lpcre
 
 ifeq ($(ANDROID_HOST),y)
 TARGETS=sefcontext_compile
 else
-TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c)))
 endif
 
 sefcontext_compile: LDLIBS += $(PCRE_LDLIBS) ../src/libselinux.a -lsepol
@@ -63,8 +63,8 @@
 all: $(TARGETS)
 
 install: all
-	-mkdir -p $(USRSBINDIR)
-	install -m 755 $(TARGETS) $(USRSBINDIR)
+	-mkdir -p $(SBINDIR)
+	install -m 755 $(TARGETS) $(SBINDIR)
 
 clean:
 	rm -f $(TARGETS) *.o *~
diff --git a/libsemanage/VERSION b/libsemanage/VERSION
index 5154b3f..1effb00 100644
--- a/libsemanage/VERSION
+++ b/libsemanage/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/libsemanage/include/semanage/ibendport_record.h b/libsemanage/include/semanage/ibendport_record.h
new file mode 100644
index 0000000..153eea0
--- /dev/null
+++ b/libsemanage/include/semanage/ibendport_record.h
@@ -0,0 +1,62 @@
+/*Copyright (C) 2005 Red Hat, Inc. */
+
+#ifndef _SEMANAGE_IBENDPORT_RECORD_H_
+#define _SEMANAGE_IBENDPORT_RECORD_H_
+
+#include <semanage/context_record.h>
+#include <semanage/handle.h>
+#include <stddef.h>
+
+#ifndef _SEMANAGE_IBENDPORT_DEFINED_
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport semanage_ibendport_t;
+typedef struct semanage_ibendport_key semanage_ibendport_key_t;
+#define _SEMANAGE_IBENDPORT_DEFINED_
+#endif
+
+extern int semanage_ibendport_compare(const semanage_ibendport_t *ibendport,
+				      const semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport,
+				       const semanage_ibendport_t *ibendport2);
+
+extern int semanage_ibendport_key_create(semanage_handle_t *handle,
+					 const char *ibdev_name,
+					 int port,
+					 semanage_ibendport_key_t **key_ptr);
+
+extern int semanage_ibendport_key_extract(semanage_handle_t *handle,
+					  const semanage_ibendport_t *ibendport,
+					  semanage_ibendport_key_t **key_ptr);
+
+extern void semanage_ibendport_key_free(semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle,
+					     const semanage_ibendport_t *ibendport,
+					     char **ibdev_name_ptr);
+
+extern int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle,
+					     semanage_ibendport_t *ibendport,
+					     const char *ibdev_name);
+
+extern int semanage_ibendport_get_port(const semanage_ibendport_t *ibendport);
+
+extern void semanage_ibendport_set_port(semanage_ibendport_t *ibendport, int port);
+
+extern semanage_context_t *semanage_ibendport_get_con(const semanage_ibendport_t *ibendport);
+
+extern int semanage_ibendport_set_con(semanage_handle_t *handle,
+				      semanage_ibendport_t *ibendport,
+				      semanage_context_t *con);
+
+extern int semanage_ibendport_create(semanage_handle_t *handle,
+				     semanage_ibendport_t **ibendport_ptr);
+
+extern int semanage_ibendport_clone(semanage_handle_t *handle,
+				    const semanage_ibendport_t *ibendport,
+				    semanage_ibendport_t **ibendport_ptr);
+
+extern void semanage_ibendport_free(semanage_ibendport_t *ibendport);
+
+#endif
diff --git a/libsemanage/include/semanage/ibendports_local.h b/libsemanage/include/semanage/ibendports_local.h
new file mode 100644
index 0000000..641dd35
--- /dev/null
+++ b/libsemanage/include/semanage/ibendports_local.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+#ifndef _SEMANAGE_IBENDPORTS_LOCAL_H_
+#define _SEMANAGE_IBENDPORTS_LOCAL_H_
+
+#include <semanage/ibendport_record.h>
+#include <semanage/handle.h>
+
+extern int semanage_ibendport_modify_local(semanage_handle_t *handle,
+					   const semanage_ibendport_key_t *key,
+					   const semanage_ibendport_t *data);
+
+extern int semanage_ibendport_del_local(semanage_handle_t *handle,
+					const semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_query_local(semanage_handle_t *handle,
+					  const semanage_ibendport_key_t *key,
+					  semanage_ibendport_t **response);
+
+extern int semanage_ibendport_exists_local(semanage_handle_t *handle,
+					   const semanage_ibendport_key_t *key,
+					   int *response);
+
+extern int semanage_ibendport_count_local(semanage_handle_t *handle,
+					  unsigned int *response);
+
+extern int semanage_ibendport_iterate_local(semanage_handle_t *handle,
+					    int (*handler)(const semanage_ibendport_t *record,
+							   void *varg),
+					    void *handler_arg);
+
+extern int semanage_ibendport_list_local(semanage_handle_t *handle,
+					 semanage_ibendport_t ***records,
+					 unsigned int *count);
+
+#endif
diff --git a/libsemanage/include/semanage/ibendports_policy.h b/libsemanage/include/semanage/ibendports_policy.h
new file mode 100644
index 0000000..3fc1976
--- /dev/null
+++ b/libsemanage/include/semanage/ibendports_policy.h
@@ -0,0 +1,28 @@
+/* Copyright (C) 2017 Mellanox Techonologies Inc */
+
+#ifndef _SEMANAGE_IBENDPORTS_POLICY_H_
+#define _SEMANAGE_IBENDPORTS_POLICY_H_
+
+#include <semanage/handle.h>
+#include <semanage/ibendport_record.h>
+
+extern int semanage_ibendport_query(semanage_handle_t *handle,
+				    const semanage_ibendport_key_t *key,
+				    semanage_ibendport_t **response);
+
+extern int semanage_ibendport_exists(semanage_handle_t *handle,
+				     const semanage_ibendport_key_t *key, int *response);
+
+extern int semanage_ibendport_count(semanage_handle_t *handle,
+				    unsigned int *response);
+
+extern int semanage_ibendport_iterate(semanage_handle_t *handle,
+				      int (*handler)(const semanage_ibendport_t *record,
+						     void *varg),
+				      void *handler_arg);
+
+extern int semanage_ibendport_list(semanage_handle_t *handle,
+				   semanage_ibendport_t ***records,
+				   unsigned int *count);
+
+#endif
diff --git a/libsemanage/include/semanage/ibpkey_record.h b/libsemanage/include/semanage/ibpkey_record.h
new file mode 100644
index 0000000..9da7dc5
--- /dev/null
+++ b/libsemanage/include/semanage/ibpkey_record.h
@@ -0,0 +1,72 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+#ifndef _SEMANAGE_IBPKEY_RECORD_H_
+#define _SEMANAGE_IBPKEY_RECORD_H_
+
+#include <semanage/context_record.h>
+#include <semanage/handle.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef _SEMANAGE_IBPKEY_DEFINED_
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey semanage_ibpkey_t;
+typedef struct semanage_ibpkey_key semanage_ibpkey_key_t;
+#define _SEMANAGE_IBPKEY_DEFINED_
+#endif
+
+extern int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
+				   const semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
+				    const semanage_ibpkey_t *ibpkey2);
+
+extern int semanage_ibpkey_key_create(semanage_handle_t *handle,
+				      const char *subnet_prefix,
+				      int low, int high,
+				      semanage_ibpkey_key_t **key_ptr);
+
+extern int semanage_ibpkey_key_extract(semanage_handle_t *handle,
+				       const semanage_ibpkey_t *ibpkey,
+				       semanage_ibpkey_key_t **key_ptr);
+
+extern void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle,
+					     const semanage_ibpkey_t *ibpkey,
+					     char **subnet_prefix_ptr);
+
+extern uint64_t semanage_ibpkey_get_subnet_prefix_bytes(const semanage_ibpkey_t *ibpkey);
+
+extern int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle,
+					     semanage_ibpkey_t *ibpkey,
+					     const char *subnet_prefix);
+
+extern void semanage_ibpkey_set_subnet_prefix_bytes(semanage_ibpkey_t *ibpkey,
+						    uint64_t subnet_prefix);
+
+extern int semanage_ibpkey_get_low(const semanage_ibpkey_t *ibpkey);
+
+extern int semanage_ibpkey_get_high(const semanage_ibpkey_t *ibpkey);
+
+extern void semanage_ibpkey_set_pkey(semanage_ibpkey_t *ibpkey, int pkey_num);
+
+extern void semanage_ibpkey_set_range(semanage_ibpkey_t *ibpkey, int low, int high);
+
+extern semanage_context_t *semanage_ibpkey_get_con(const semanage_ibpkey_t *ibpkey);
+
+extern int semanage_ibpkey_set_con(semanage_handle_t *handle,
+				   semanage_ibpkey_t *ibpkey,
+				   semanage_context_t *con);
+
+extern int semanage_ibpkey_create(semanage_handle_t *handle,
+				  semanage_ibpkey_t **ibpkey_ptr);
+
+extern int semanage_ibpkey_clone(semanage_handle_t *handle,
+				 const semanage_ibpkey_t *ibpkey,
+				 semanage_ibpkey_t **ibpkey_ptr);
+
+extern void semanage_ibpkey_free(semanage_ibpkey_t *ibpkey);
+
+#endif
diff --git a/libsemanage/include/semanage/ibpkeys_local.h b/libsemanage/include/semanage/ibpkeys_local.h
new file mode 100644
index 0000000..079a642
--- /dev/null
+++ b/libsemanage/include/semanage/ibpkeys_local.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+#ifndef _SEMANAGE_IBPKEYS_LOCAL_H_
+#define _SEMANAGE_IBPKEYS_LOCAL_H_
+
+#include <semanage/ibpkey_record.h>
+#include <semanage/handle.h>
+
+extern int semanage_ibpkey_modify_local(semanage_handle_t *handle,
+					const semanage_ibpkey_key_t *key,
+					const semanage_ibpkey_t *data);
+
+extern int semanage_ibpkey_del_local(semanage_handle_t *handle,
+				     const semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_query_local(semanage_handle_t *handle,
+				       const semanage_ibpkey_key_t *key,
+				       semanage_ibpkey_t **response);
+
+extern int semanage_ibpkey_exists_local(semanage_handle_t *handle,
+					const semanage_ibpkey_key_t *key,
+					int *response);
+
+extern int semanage_ibpkey_count_local(semanage_handle_t *handle,
+				       unsigned int *response);
+
+extern int semanage_ibpkey_iterate_local(semanage_handle_t *handle,
+					 int (*handler)(const semanage_ibpkey_t *
+							record, void *varg),
+					 void *handler_arg);
+
+extern int semanage_ibpkey_list_local(semanage_handle_t *handle,
+				      semanage_ibpkey_t ***records,
+				      unsigned int *count);
+
+#endif
diff --git a/libsemanage/include/semanage/ibpkeys_policy.h b/libsemanage/include/semanage/ibpkeys_policy.h
new file mode 100644
index 0000000..c287ac0
--- /dev/null
+++ b/libsemanage/include/semanage/ibpkeys_policy.h
@@ -0,0 +1,28 @@
+/* Copyright (C) 2017 Mellanox Technolgies Inc. */
+
+#ifndef _SEMANAGE_IBPKEYS_POLICY_H_
+#define _SEMANAGE_IBPKEYS_POLICY_H_
+
+#include <semanage/handle.h>
+#include <semanage/ibpkey_record.h>
+
+extern int semanage_ibpkey_query(semanage_handle_t *handle,
+				 const semanage_ibpkey_key_t *key,
+				 semanage_ibpkey_t **response);
+
+extern int semanage_ibpkey_exists(semanage_handle_t *handle,
+				  const semanage_ibpkey_key_t *key, int *response);
+
+extern int semanage_ibpkey_count(semanage_handle_t *handle,
+				 unsigned int *response);
+
+extern int semanage_ibpkey_iterate(semanage_handle_t *handle,
+				   int (*handler)(const semanage_ibpkey_t *record,
+						  void *varg),
+				   void *handler_arg);
+
+extern int semanage_ibpkey_list(semanage_handle_t *handle,
+				semanage_ibpkey_t ***records,
+				unsigned int *count);
+
+#endif
diff --git a/libsemanage/include/semanage/semanage.h b/libsemanage/include/semanage/semanage.h
index f417ce4..0489014 100644
--- a/libsemanage/include/semanage/semanage.h
+++ b/libsemanage/include/semanage/semanage.h
@@ -33,6 +33,8 @@
 #include <semanage/context_record.h>
 #include <semanage/iface_record.h>
 #include <semanage/port_record.h>
+#include <semanage/ibpkey_record.h>
+#include <semanage/ibendport_record.h>
 #include <semanage/node_record.h>
 
 /* Dbase */
@@ -47,6 +49,10 @@
 #include <semanage/seusers_policy.h>
 #include <semanage/ports_local.h>
 #include <semanage/ports_policy.h>
+#include <semanage/ibpkeys_local.h>
+#include <semanage/ibendports_local.h>
+#include <semanage/ibendports_policy.h>
+#include <semanage/ibpkeys_policy.h>
 #include <semanage/interfaces_local.h>
 #include <semanage/interfaces_policy.h>
 #include <semanage/nodes_local.h>
diff --git a/libsemanage/src/Makefile b/libsemanage/src/Makefile
index dba50c8..fdb178f 100644
--- a/libsemanage/src/Makefile
+++ b/libsemanage/src/Makefile
@@ -17,7 +17,7 @@
 PYSITEDIR ?= $(DESTDIR)$(shell $(PYTHON) -c 'import site; print(site.getsitepackages()[0])')
 PYCEXT ?= $(shell $(PYTHON) -c 'import imp;print([s for s,m,t in imp.get_suffixes() if t == imp.C_EXTENSION][0])')
 RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]')
-RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -lruby"')
+RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]')
 RUBYINSTALL ?= $(DESTDIR)$(shell $(RUBY) -e 'puts RbConfig::CONFIG["vendorarchdir"]')
 
 LIBBASE=$(shell basename $(LIBDIR))
@@ -51,7 +51,7 @@
 SWIGRUBYSO=$(RUBYPREFIX)_semanage.so
 LIBSO=$(TARGET).$(LIBVERSION)
 
-GENERATED=$(SWIGCOUT) $(SWIGRUBYCOUT) semanageswig_python_exception.i $(wildcard conf-*.[ch])
+GENERATED=$(SWIGCOUT) $(SWIGRUBYCOUT) semanageswig_python_exception.i $(sort $(wildcard conf-*.[ch]))
 SRCS= $(filter-out $(GENERATED),$(sort $(wildcard *.c)))
 
 OBJS= $(patsubst %.c,%.o,$(SRCS)) conf-scan.o conf-parse.o
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index f4b0416..65842df 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -40,6 +40,8 @@
 #include "user_internal.h"
 #include "seuser_internal.h"
 #include "port_internal.h"
+#include "ibpkey_internal.h"
+#include "ibendport_internal.h"
 #include "iface_internal.h"
 #include "boolean_internal.h"
 #include "fcontext_internal.h"
@@ -224,6 +226,22 @@
 				 semanage_node_dbase_local(sh)) < 0)
 		goto err;
 
+	if (ibpkey_file_dbase_init(sh,
+				   semanage_path(SEMANAGE_ACTIVE,
+					         SEMANAGE_IBPKEYS_LOCAL),
+				   semanage_path(SEMANAGE_TMP,
+					         SEMANAGE_IBPKEYS_LOCAL),
+				   semanage_ibpkey_dbase_local(sh)) < 0)
+		goto err;
+
+	if (ibendport_file_dbase_init(sh,
+				      semanage_path(SEMANAGE_ACTIVE,
+						    SEMANAGE_IBENDPORTS_LOCAL),
+				      semanage_path(SEMANAGE_TMP,
+						    SEMANAGE_IBENDPORTS_LOCAL),
+				      semanage_ibendport_dbase_local(sh)) < 0)
+		goto err;
+
 	/* Object databases: local modifications + policy */
 	if (user_base_policydb_dbase_init(sh,
 					  semanage_user_base_dbase_policy(sh)) <
@@ -248,6 +266,12 @@
 	if (port_policydb_dbase_init(sh, semanage_port_dbase_policy(sh)) < 0)
 		goto err;
 
+	if (ibpkey_policydb_dbase_init(sh, semanage_ibpkey_dbase_policy(sh)) < 0)
+		goto err;
+
+	if (ibendport_policydb_dbase_init(sh, semanage_ibendport_dbase_policy(sh)) < 0)
+		goto err;
+
 	if (iface_policydb_dbase_init(sh, semanage_iface_dbase_policy(sh)) < 0)
 		goto err;
 
@@ -320,6 +344,8 @@
 	user_extra_file_dbase_release(semanage_user_extra_dbase_local(sh));
 	user_join_dbase_release(semanage_user_dbase_local(sh));
 	port_file_dbase_release(semanage_port_dbase_local(sh));
+	ibpkey_file_dbase_release(semanage_ibpkey_dbase_local(sh));
+	ibendport_file_dbase_release(semanage_ibendport_dbase_local(sh));
 	iface_file_dbase_release(semanage_iface_dbase_local(sh));
 	bool_file_dbase_release(semanage_bool_dbase_local(sh));
 	fcontext_file_dbase_release(semanage_fcontext_dbase_local(sh));
@@ -331,6 +357,8 @@
 	user_extra_file_dbase_release(semanage_user_extra_dbase_policy(sh));
 	user_join_dbase_release(semanage_user_dbase_policy(sh));
 	port_policydb_dbase_release(semanage_port_dbase_policy(sh));
+	ibpkey_policydb_dbase_release(semanage_ibpkey_dbase_policy(sh));
+	ibendport_policydb_dbase_release(semanage_ibendport_dbase_policy(sh));
 	iface_policydb_dbase_release(semanage_iface_dbase_policy(sh));
 	bool_policydb_dbase_release(semanage_bool_dbase_policy(sh));
 	fcontext_file_dbase_release(semanage_fcontext_dbase_policy(sh));
@@ -1144,13 +1172,18 @@
 
 	int do_rebuild, do_write_kernel, do_install;
 	int fcontexts_modified, ports_modified, seusers_modified,
-		disable_dontaudit, preserve_tunables;
+		disable_dontaudit, preserve_tunables, ibpkeys_modified,
+		ibendports_modified;
 	dbase_config_t *users = semanage_user_dbase_local(sh);
 	dbase_config_t *users_base = semanage_user_base_dbase_local(sh);
 	dbase_config_t *pusers_base = semanage_user_base_dbase_policy(sh);
 	dbase_config_t *pusers_extra = semanage_user_extra_dbase_policy(sh);
 	dbase_config_t *ports = semanage_port_dbase_local(sh);
 	dbase_config_t *pports = semanage_port_dbase_policy(sh);
+	dbase_config_t *ibpkeys = semanage_ibpkey_dbase_local(sh);
+	dbase_config_t *pibpkeys = semanage_ibpkey_dbase_policy(sh);
+	dbase_config_t *ibendports = semanage_ibendport_dbase_local(sh);
+	dbase_config_t *pibendports = semanage_ibendport_dbase_policy(sh);
 	dbase_config_t *bools = semanage_bool_dbase_local(sh);
 	dbase_config_t *pbools = semanage_bool_dbase_policy(sh);
 	dbase_config_t *ifaces = semanage_iface_dbase_local(sh);
@@ -1164,6 +1197,8 @@
 
 	/* Modified flags that we need to use more than once. */
 	ports_modified = ports->dtable->is_modified(ports->dbase);
+	ibpkeys_modified = ibpkeys->dtable->is_modified(ibpkeys->dbase);
+	ibendports_modified = ibendports->dtable->is_modified(ibendports->dbase);
 	seusers_modified = seusers->dtable->is_modified(seusers->dbase);
 	fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase);
 
@@ -1285,7 +1320,8 @@
 	 * that live under /etc/selinux (kernel policy, seusers, file contexts)
 	 * will be modified.
 	 */
-	do_write_kernel = do_rebuild | ports_modified |
+	do_write_kernel = do_rebuild | ports_modified | ibpkeys_modified |
+		ibendports_modified |
 		bools->dtable->is_modified(bools->dbase) |
 		ifaces->dtable->is_modified(ifaces->dbase) |
 		nodes->dtable->is_modified(nodes->dbase) |
@@ -1431,6 +1467,8 @@
 	/* Attach our databases to the policydb we just created or loaded. */
 	dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pports->dbase, out);
+	dbase_policydb_attach((dbase_policydb_t *) pibpkeys->dbase, out);
+	dbase_policydb_attach((dbase_policydb_t *) pibendports->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pifaces->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pbools->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pnodes->dbase, out);
@@ -1479,6 +1517,19 @@
 			goto cleanup;
 	}
 
+	/* Validate local ibpkeys for overlap */
+	if (do_rebuild || ibpkeys_modified) {
+		retval = semanage_ibpkey_validate_local(sh);
+		if (retval < 0)
+			goto cleanup;
+	}
+
+	/* Validate local ibendports */
+	if (do_rebuild || ibendports_modified) {
+		retval = semanage_ibendport_validate_local(sh);
+		if (retval < 0)
+			goto cleanup;
+	}
 	/* ================== Write non-policydb components ========= */
 
 	/* Commit changes to components */
@@ -1558,6 +1609,8 @@
 	/* Detach from policydb, so it can be freed */
 	dbase_policydb_detach((dbase_policydb_t *) pusers_base->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pports->dbase);
+	dbase_policydb_detach((dbase_policydb_t *) pibpkeys->dbase);
+	dbase_policydb_detach((dbase_policydb_t *) pibendports->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pifaces->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pnodes->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pbools->dbase);
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index e8c95ee..b9a74b7 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -290,14 +290,11 @@
 	semanage_list_t *homedir_list = NULL;
 	semanage_list_t *shells = NULL;
 	fc_match_handle_t hand;
-	char *rbuf = NULL;
 	char *path = NULL;
-	long rbuflen;
 	uid_t temp, minuid = 500, maxuid = 60000;
 	int minuid_set = 0;
-	struct passwd pwstorage, *pwbuf;
+	struct passwd *pwbuf;
 	struct stat buf;
-	int retval;
 
 	path = semanage_findval(PATH_ETC_USERADD, "HOME", "=");
 	if (path && *path) {
@@ -362,14 +359,9 @@
 	free(path);
 	path = NULL;
 
-	rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
-	if (rbuflen <= 0)
-		goto fail;
-	rbuf = malloc(rbuflen);
-	if (rbuf == NULL)
-		goto fail;
+	errno = 0;
 	setpwent();
-	while ((retval = getpwent_r(&pwstorage, rbuf, rbuflen, &pwbuf)) == 0) {
+	while ((pwbuf = getpwent()) != NULL) {
 		if (pwbuf->pw_uid < minuid || pwbuf->pw_uid > maxuid)
 			continue;
 		if (!semanage_list_find(shells, pwbuf->pw_shell))
@@ -411,9 +403,10 @@
 		}
 		free(path);
 		path = NULL;
+		errno = 0;
 	}
 
-	if (retval && retval != ENOENT) {
+	if (errno) {
 		WARN(s->h_semanage, "Error while fetching users.  "
 		     "Returning list so far.");
 	}
@@ -422,14 +415,12 @@
 		goto fail;
 
 	endpwent();
-	free(rbuf);
 	semanage_list_destroy(&shells);
 
 	return homedir_list;
 
       fail:
 	endpwent();
-	free(rbuf);
 	free(path);
 	semanage_list_destroy(&homedir_list);
 	semanage_list_destroy(&shells);
@@ -1064,10 +1055,7 @@
 	long grbuflen;
 	char *grbuf = NULL;
 	struct group grstorage, *group = NULL;
-
-	long prbuflen;
-	char *pwbuf = NULL;
-	struct passwd pwstorage, *pw = NULL;
+	struct passwd *pw = NULL;
 
 	grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
 	if (grbuflen <= 0)
@@ -1104,15 +1092,8 @@
 		}
 	}
 
-	prbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
-	if (prbuflen <= 0)
-		goto cleanup;
-	pwbuf = malloc(prbuflen);
-	if (pwbuf == NULL)
-		goto cleanup;
-
 	setpwent();
-	while ((retval = getpwent_r(&pwstorage, pwbuf, prbuflen, &pw)) == 0) {
+	while ((pw = getpwent()) != NULL) {
 		// skip users who also have this group as their
 		// primary group
 		if (lfind(pw->pw_name, group->gr_mem, &nmembers,
@@ -1131,7 +1112,6 @@
 	retval = STATUS_SUCCESS;
 cleanup:
 	endpwent();
-	free(pwbuf);
 	free(grbuf);
 
 	return retval;
diff --git a/libsemanage/src/handle.h b/libsemanage/src/handle.h
index 64175c4..889871d 100644
--- a/libsemanage/src/handle.h
+++ b/libsemanage/src/handle.h
@@ -79,7 +79,7 @@
 	struct semanage_policy_table *funcs;
 
 	/* Object databases */
-#define DBASE_COUNT      19
+#define DBASE_COUNT      23
 
 /* Local modifications */
 #define DBASE_LOCAL_USERS_BASE  0
@@ -91,20 +91,24 @@
 #define DBASE_LOCAL_FCONTEXTS	6
 #define DBASE_LOCAL_SEUSERS     7
 #define DBASE_LOCAL_NODES       8
+#define DBASE_LOCAL_IBPKEYS     9
+#define DBASE_LOCAL_IBENDPORTS  10
 
 /* Policy + Local modifications */
-#define DBASE_POLICY_USERS_BASE  9
-#define DBASE_POLICY_USERS_EXTRA 10
-#define DBASE_POLICY_USERS       11
-#define DBASE_POLICY_PORTS       12
-#define DBASE_POLICY_INTERFACES  13
-#define DBASE_POLICY_BOOLEANS    14
-#define DBASE_POLICY_FCONTEXTS   15
-#define DBASE_POLICY_SEUSERS     16
-#define DBASE_POLICY_NODES       17
+#define DBASE_POLICY_USERS_BASE  11
+#define DBASE_POLICY_USERS_EXTRA 12
+#define DBASE_POLICY_USERS       13
+#define DBASE_POLICY_PORTS       14
+#define DBASE_POLICY_INTERFACES  15
+#define DBASE_POLICY_BOOLEANS    16
+#define DBASE_POLICY_FCONTEXTS   17
+#define DBASE_POLICY_SEUSERS     18
+#define DBASE_POLICY_NODES       19
+#define DBASE_POLICY_IBPKEYS     20
+#define DBASE_POLICY_IBENDPORTS  21
 
 /* Active kernel policy */
-#define DBASE_ACTIVE_BOOLEANS    18
+#define DBASE_ACTIVE_BOOLEANS    22
 	dbase_config_t dbase[DBASE_COUNT];
 };
 
@@ -134,6 +138,18 @@
 }
 
 static inline
+    dbase_config_t * semanage_ibpkey_dbase_local(semanage_handle_t * handle)
+{
+	return &handle->dbase[DBASE_LOCAL_IBPKEYS];
+}
+
+static inline
+    dbase_config_t * semanage_ibendport_dbase_local(semanage_handle_t * handle)
+{
+	return &handle->dbase[DBASE_LOCAL_IBENDPORTS];
+}
+
+static inline
     dbase_config_t * semanage_iface_dbase_local(semanage_handle_t * handle)
 {
 	return &handle->dbase[DBASE_LOCAL_INTERFACES];
@@ -190,6 +206,18 @@
 }
 
 static inline
+    dbase_config_t * semanage_ibpkey_dbase_policy(semanage_handle_t * handle)
+{
+	return &handle->dbase[DBASE_POLICY_IBPKEYS];
+}
+
+static inline
+    dbase_config_t * semanage_ibendport_dbase_policy(semanage_handle_t * handle)
+{
+	return &handle->dbase[DBASE_POLICY_IBENDPORTS];
+}
+
+static inline
     dbase_config_t * semanage_iface_dbase_policy(semanage_handle_t * handle)
 {
 	return &handle->dbase[DBASE_POLICY_INTERFACES];
diff --git a/libsemanage/src/ibendport_internal.h b/libsemanage/src/ibendport_internal.h
new file mode 100644
index 0000000..970fbdb
--- /dev/null
+++ b/libsemanage/src/ibendport_internal.h
@@ -0,0 +1,48 @@
+#ifndef _SEMANAGE_IBENDPORT_INTERNAL_H_
+#define _SEMANAGE_IBENDPORT_INTERNAL_H_
+
+#include <semanage/ibendport_record.h>
+#include <semanage/ibendports_local.h>
+#include <semanage/ibendports_policy.h>
+#include "database.h"
+#include "handle.h"
+#include "dso.h"
+
+hidden_proto(semanage_ibendport_create)
+hidden_proto(semanage_ibendport_compare)
+hidden_proto(semanage_ibendport_compare2)
+hidden_proto(semanage_ibendport_clone)
+hidden_proto(semanage_ibendport_free)
+hidden_proto(semanage_ibendport_key_extract)
+hidden_proto(semanage_ibendport_key_free)
+hidden_proto(semanage_ibendport_get_port)
+hidden_proto(semanage_ibendport_set_port)
+hidden_proto(semanage_ibendport_get_con)
+hidden_proto(semanage_ibendport_set_con)
+hidden_proto(semanage_ibendport_list_local)
+hidden_proto(semanage_ibendport_get_ibdev_name)
+hidden_proto(semanage_ibendport_set_ibdev_name)
+
+/* IBENDPORT RECORD: method table */
+extern record_table_t SEMANAGE_IBENDPORT_RTABLE;
+
+extern int ibendport_file_dbase_init(semanage_handle_t *handle,
+				     const char *path_ro,
+				     const char *path_rw,
+				     dbase_config_t *dconfig);
+
+extern void ibendport_file_dbase_release(dbase_config_t *dconfig);
+
+extern int ibendport_policydb_dbase_init(semanage_handle_t *handle,
+					 dbase_config_t *dconfig);
+
+extern void ibendport_policydb_dbase_release(dbase_config_t *dconfig);
+
+extern int hidden semanage_ibendport_validate_local(semanage_handle_t *handle);
+
+/* ==== Internal (to ibendports) API === */
+
+hidden int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport,
+					     const semanage_ibendport_t **ibendport2);
+
+#endif
diff --git a/libsemanage/src/ibendport_record.c b/libsemanage/src/ibendport_record.c
new file mode 100644
index 0000000..955067e
--- /dev/null
+++ b/libsemanage/src/ibendport_record.c
@@ -0,0 +1,154 @@
+/*Copyright (C) 2005 Red Hat, Inc. */
+
+/*Object: semanage_ibendport_t (Infiniband Pkey)
+ *Object: semanage_ibendport_key_t (Infiniband Pkey Key)
+ *Implements: record_t (Database Record)
+ *Implements: record_key_t (Database Record Key)
+ */
+
+#include <sepol/context_record.h>
+#include <sepol/ibendport_record.h>
+
+typedef sepol_context_t semanage_context_t;
+typedef sepol_ibendport_t semanage_ibendport_t;
+typedef sepol_ibendport_key_t semanage_ibendport_key_t;
+#define _SEMANAGE_IBENDPORT_DEFINED_
+#define _SEMANAGE_CONTEXT_DEFINED_
+
+typedef semanage_ibendport_t record_t;
+typedef semanage_ibendport_key_t record_key_t;
+#define DBASE_RECORD_DEFINED
+
+#include "ibendport_internal.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibendport_compare(const semanage_ibendport_t *ibendport,
+			       const semanage_ibendport_key_t *key)
+{
+	return sepol_ibendport_compare(ibendport, key);
+}
+
+hidden_def(semanage_ibendport_compare)
+
+int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport,
+				const semanage_ibendport_t *ibendport2)
+{
+	return sepol_ibendport_compare2(ibendport, ibendport2);
+}
+
+hidden_def(semanage_ibendport_compare2)
+
+hidden int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport,
+					     const semanage_ibendport_t **ibendport2)
+{
+	return sepol_ibendport_compare2(*ibendport, *ibendport2);
+}
+
+int semanage_ibendport_key_create(semanage_handle_t *handle,
+				  const char *ibdev_name,
+				  int port,
+				  semanage_ibendport_key_t **key_ptr)
+{
+	return sepol_ibendport_key_create(handle->sepolh, ibdev_name, port, key_ptr);
+}
+
+int semanage_ibendport_key_extract(semanage_handle_t *handle,
+				   const semanage_ibendport_t *ibendport,
+				   semanage_ibendport_key_t **key_ptr)
+{
+	return sepol_ibendport_key_extract(handle->sepolh, ibendport, key_ptr);
+}
+
+hidden_def(semanage_ibendport_key_extract)
+
+void semanage_ibendport_key_free(semanage_ibendport_key_t *key)
+{
+	sepol_ibendport_key_free(key);
+}
+
+hidden_def(semanage_ibendport_key_free)
+
+int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle,
+				      const semanage_ibendport_t *ibendport,
+				      char **ibdev_name_ptr)
+{
+	return sepol_ibendport_get_ibdev_name(handle->sepolh, ibendport, ibdev_name_ptr);
+}
+
+hidden_def(semanage_ibendport_get_ibdev_name)
+
+int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle,
+				      semanage_ibendport_t *ibendport,
+				      const char *ibdev_name)
+{
+	return sepol_ibendport_set_ibdev_name(handle->sepolh, ibendport, ibdev_name);
+}
+
+hidden_def(semanage_ibendport_set_ibdev_name)
+
+int semanage_ibendport_get_port(const semanage_ibendport_t *ibendport)
+{
+	return sepol_ibendport_get_port(ibendport);
+}
+
+hidden_def(semanage_ibendport_get_port)
+
+void semanage_ibendport_set_port(semanage_ibendport_t *ibendport, int port)
+{
+	sepol_ibendport_set_port(ibendport, port);
+}
+
+hidden_def(semanage_ibendport_set_port)
+
+semanage_context_t *semanage_ibendport_get_con(const semanage_ibendport_t *ibendport)
+{
+	return sepol_ibendport_get_con(ibendport);
+}
+
+hidden_def(semanage_ibendport_get_con)
+
+int semanage_ibendport_set_con(semanage_handle_t *handle,
+			       semanage_ibendport_t *ibendport,
+			       semanage_context_t *con)
+{
+	return sepol_ibendport_set_con(handle->sepolh, ibendport, con);
+}
+
+hidden_def(semanage_ibendport_set_con)
+
+int semanage_ibendport_create(semanage_handle_t *handle,
+			      semanage_ibendport_t **ibendport_ptr)
+{
+	return sepol_ibendport_create(handle->sepolh, ibendport_ptr);
+}
+
+hidden_def(semanage_ibendport_create)
+
+int semanage_ibendport_clone(semanage_handle_t *handle,
+			     const semanage_ibendport_t *ibendport,
+			     semanage_ibendport_t **ibendport_ptr)
+{
+	return sepol_ibendport_clone(handle->sepolh, ibendport, ibendport_ptr);
+}
+
+hidden_def(semanage_ibendport_clone)
+
+void semanage_ibendport_free(semanage_ibendport_t *ibendport)
+{
+	sepol_ibendport_free(ibendport);
+}
+
+hidden_def(semanage_ibendport_free)
+
+/*key base functions */
+record_table_t SEMANAGE_IBENDPORT_RTABLE = {
+	.create = semanage_ibendport_create,
+	.key_extract = semanage_ibendport_key_extract,
+	.key_free = semanage_ibendport_key_free,
+	.clone = semanage_ibendport_clone,
+	.compare = semanage_ibendport_compare,
+	.compare2 = semanage_ibendport_compare2,
+	.compare2_qsort = semanage_ibendport_compare2_qsort,
+	.free = semanage_ibendport_free,
+};
diff --git a/libsemanage/src/ibendports_file.c b/libsemanage/src/ibendports_file.c
new file mode 100644
index 0000000..402c7a5
--- /dev/null
+++ b/libsemanage/src/ibendports_file.c
@@ -0,0 +1,157 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc. */
+
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport record_t;
+typedef struct semanage_ibendport_key record_key_t;
+#define DBASE_RECORD_DEFINED
+
+struct dbase_file;
+typedef struct dbase_file dbase_t;
+#define DBASE_DEFINED
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <semanage/handle.h>
+#include "ibendport_internal.h"
+#include "context_internal.h"
+#include "database_file.h"
+#include "parse_utils.h"
+#include "debug.h"
+
+static int ibendport_print(semanage_handle_t *handle,
+			   semanage_ibendport_t *ibendport,
+			   FILE *str)
+{
+	char *con_str = NULL;
+	char *ibdev_name_str = NULL;
+	int port = semanage_ibendport_get_port(ibendport);
+
+	if (semanage_ibendport_get_ibdev_name(handle, ibendport, &ibdev_name_str) != 0)
+		goto err;
+
+	semanage_context_t *con = semanage_ibendport_get_con(ibendport);
+
+	if (fprintf(str, "ibendportcon %s ", ibdev_name_str) < 0)
+		goto err;
+
+	if (fprintf(str, "%d ", port) < 0)
+		goto err;
+
+	if (semanage_context_to_string(handle, con, &con_str) < 0)
+		goto err;
+	if (fprintf(str, "%s\n", con_str) < 0)
+		goto err;
+
+	free(ibdev_name_str);
+	free(con_str);
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not print ibendport (%s) %u to stream",
+	    ibdev_name_str, port);
+	free(ibdev_name_str);
+	free(con_str);
+	return STATUS_ERR;
+}
+
+static int ibendport_parse(semanage_handle_t *handle,
+			   parse_info_t *info,
+			   semanage_ibendport_t *ibendport)
+{
+	int port;
+	char *str = NULL;
+	semanage_context_t *con = NULL;
+
+	if (parse_skip_space(handle, info) < 0)
+		goto err;
+	if (!info->ptr)
+		goto last;
+
+	/* Header */
+	if (parse_assert_str(handle, info, "ibendportcon") < 0)
+		goto err;
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+
+	/* IB Device Name */
+	if (parse_fetch_string(handle, info, &str, ' ') < 0)
+		goto err;
+	if (semanage_ibendport_set_ibdev_name(handle, ibendport, str) < 0)
+		goto err;
+	free(str);
+	str = NULL;
+
+	/* Port */
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+	if (parse_fetch_int(handle, info, &port, ' ') < 0)
+		goto err;
+	semanage_ibendport_set_port(ibendport, port);
+
+	/* context */
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+	if (parse_fetch_string(handle, info, &str, ' ') < 0)
+		goto err;
+	if (semanage_context_from_string(handle, str, &con) < 0) {
+		ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
+		    str, info->filename, info->lineno, info->orig_line);
+		goto err;
+	}
+	if (!con) {
+		ERR(handle, "<<none>> context is not valid for ibendport (%s: %u):\n%s",
+		    info->filename, info->lineno, info->orig_line);
+		goto err;
+	}
+	free(str);
+	str = NULL;
+
+	if (semanage_ibendport_set_con(handle, ibendport, con) < 0)
+		goto err;
+
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+
+	semanage_context_free(con);
+	return STATUS_SUCCESS;
+
+last:
+	parse_dispose_line(info);
+	return STATUS_NODATA;
+
+err:
+	ERR(handle, "could not parse ibendport record");
+	free(str);
+	semanage_context_free(con);
+	parse_dispose_line(info);
+	return STATUS_ERR;
+}
+
+/* IBENDPORT RECORD: FILE extension: method table */
+record_file_table_t SEMANAGE_IBENDPORT_FILE_RTABLE = {
+	.parse = ibendport_parse,
+	.print = ibendport_print,
+};
+
+int ibendport_file_dbase_init(semanage_handle_t *handle,
+			      const char *path_ro,
+			      const char *path_rw,
+			      dbase_config_t *dconfig)
+{
+	if (dbase_file_init(handle,
+			    path_ro,
+			    path_rw,
+			    &SEMANAGE_IBENDPORT_RTABLE,
+			    &SEMANAGE_IBENDPORT_FILE_RTABLE, &dconfig->dbase) < 0)
+		return STATUS_ERR;
+
+	dconfig->dtable = &SEMANAGE_FILE_DTABLE;
+	return STATUS_SUCCESS;
+}
+
+void ibendport_file_dbase_release(dbase_config_t *dconfig)
+{
+	dbase_file_release(dconfig->dbase);
+}
diff --git a/libsemanage/src/ibendports_local.c b/libsemanage/src/ibendports_local.c
new file mode 100644
index 0000000..8b5567d
--- /dev/null
+++ b/libsemanage/src/ibendports_local.c
@@ -0,0 +1,153 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport_key record_key_t;
+typedef struct semanage_ibendport record_t;
+#define DBASE_RECORD_DEFINED
+
+#include <stdlib.h>
+#include <string.h>
+#include <sepol/policydb.h>
+#include "ibendport_internal.h"
+#include "debug.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibendport_modify_local(semanage_handle_t *handle,
+				    const semanage_ibendport_key_t *key,
+				    const semanage_ibendport_t *data)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_modify(handle, dconfig, key, data);
+}
+
+int semanage_ibendport_del_local(semanage_handle_t *handle,
+				 const semanage_ibendport_key_t *key)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_del(handle, dconfig, key);
+}
+
+int semanage_ibendport_query_local(semanage_handle_t *handle,
+				   const semanage_ibendport_key_t *key,
+				   semanage_ibendport_t **response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_query(handle, dconfig, key, response);
+}
+
+int semanage_ibendport_exists_local(semanage_handle_t *handle,
+				    const semanage_ibendport_key_t *key,
+				    int *response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_exists(handle, dconfig, key, response);
+}
+
+int semanage_ibendport_count_local(semanage_handle_t *handle,
+				   unsigned int *response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_count(handle, dconfig, response);
+}
+
+int semanage_ibendport_iterate_local(semanage_handle_t *handle,
+				     int (*handler)(const semanage_ibendport_t *record,
+						    void *varg), void *handler_arg)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+	return dbase_iterate(handle, dconfig, handler, handler_arg);
+}
+
+int semanage_ibendport_list_local(semanage_handle_t *handle,
+				  semanage_ibendport_t ***records,
+				  unsigned int *count)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_list(handle, dconfig, records, count);
+}
+
+hidden_def(semanage_ibendport_list_local)
+
+int hidden semanage_ibendport_validate_local(semanage_handle_t *handle)
+{
+	semanage_ibendport_t **ibendports = NULL;
+	unsigned int nibendports = 0;
+	unsigned int i = 0, j = 0;
+	char *ibdev_name;
+	char *ibdev_name2;
+	int port;
+	int port2;
+
+	/* List and sort the ibendports */
+	if (semanage_ibendport_list_local(handle, &ibendports, &nibendports) < 0)
+		goto err;
+
+	qsort(ibendports, nibendports, sizeof(semanage_ibendport_t *),
+	      (int (*)(const void *, const void *))
+	      &semanage_ibendport_compare2_qsort);
+
+	/* Test each ibendport */
+	while (i < nibendports) {
+		int stop = 0;
+
+		if (STATUS_SUCCESS !=
+				semanage_ibendport_get_ibdev_name(handle,
+								  ibendports[i],
+								  &ibdev_name)) {
+			ERR(handle, "Couldn't get IB device name");
+			goto err;
+		}
+
+		port = semanage_ibendport_get_port(ibendports[i]);
+
+		/* Find the first ibendport with matching
+		 * ibdev_name to compare against
+		 */
+		do {
+			if (j == nibendports - 1)
+				goto next;
+			j++;
+			if (STATUS_SUCCESS !=
+				semanage_ibendport_get_ibdev_name(handle,
+								  ibendports[j],
+								  &ibdev_name2)) {
+				ERR(handle, "Couldn't get IB device name.");
+				goto err;
+			}
+			port2 = semanage_ibendport_get_port(ibendports[j]);
+
+			stop = !strcmp(ibdev_name, ibdev_name2);
+		} while (!stop);
+
+		if (port == port2) {
+			ERR(handle, "ibendport %s/%u already exists.",
+			    ibdev_name2, port2);
+			goto invalid;
+		}
+next:
+		i++;
+		j = i;
+	}
+
+	for (i = 0; i < nibendports; i++)
+		semanage_ibendport_free(ibendports[i]);
+	free(ibendports);
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not complete ibendports validity check");
+
+invalid:
+	for (i = 0; i < nibendports; i++)
+		semanage_ibendport_free(ibendports[i]);
+	free(ibendports);
+	return STATUS_ERR;
+}
diff --git a/libsemanage/src/ibendports_policy.c b/libsemanage/src/ibendports_policy.c
new file mode 100644
index 0000000..1347b67
--- /dev/null
+++ b/libsemanage/src/ibendports_policy.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport_key record_key_t;
+typedef struct semanage_ibendport record_t;
+#define DBASE_RECORD_DEFINED
+
+#include "ibendport_internal.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibendport_query(semanage_handle_t *handle,
+			     const semanage_ibendport_key_t *key,
+			     semanage_ibendport_t **response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_query(handle, dconfig, key, response);
+}
+
+int semanage_ibendport_exists(semanage_handle_t *handle,
+			      const semanage_ibendport_key_t *key,
+			      int *response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_exists(handle, dconfig, key, response);
+}
+
+int semanage_ibendport_count(semanage_handle_t *handle,
+			     unsigned int *response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_count(handle, dconfig, response);
+}
+
+int semanage_ibendport_iterate(semanage_handle_t *handle,
+			       int (*handler)(const semanage_ibendport_t *record,
+					      void *varg), void *handler_arg)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_iterate(handle, dconfig, handler, handler_arg);
+}
+
+int semanage_ibendport_list(semanage_handle_t *handle,
+			    semanage_ibendport_t ***records,
+			    unsigned int *count)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_list(handle, dconfig, records, count);
+}
diff --git a/libsemanage/src/ibendports_policydb.c b/libsemanage/src/ibendports_policydb.c
new file mode 100644
index 0000000..1029810
--- /dev/null
+++ b/libsemanage/src/ibendports_policydb.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 Mellanox Technologies Inc
+ *
+ *  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.
+ */
+
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport record_t;
+typedef struct semanage_ibendport_key record_key_t;
+#define DBASE_RECORD_DEFINED
+
+struct dbase_policydb;
+typedef struct dbase_policydb dbase_t;
+#define DBASE_DEFINED
+
+#include <sepol/ibendports.h>
+#include <semanage/handle.h>
+#include "ibendport_internal.h"
+#include "debug.h"
+#include "database_policydb.h"
+#include "semanage_store.h"
+
+/* IBENDPORT RECORD (SEPOL): POLICYDB extension : method table */
+record_policydb_table_t SEMANAGE_IBENDPORT_POLICYDB_RTABLE = {
+	.add = NULL,
+	.modify = (record_policydb_table_modify_t)sepol_ibendport_modify,
+	.set = NULL,
+	.query = (record_policydb_table_query_t)sepol_ibendport_query,
+	.count = (record_policydb_table_count_t)sepol_ibendport_count,
+	.exists = (record_policydb_table_exists_t)sepol_ibendport_exists,
+	.iterate = (record_policydb_table_iterate_t)sepol_ibendport_iterate,
+};
+
+int ibendport_policydb_dbase_init(semanage_handle_t *handle,
+				  dbase_config_t *dconfig)
+{
+	if (dbase_policydb_init(handle,
+				semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL),
+				semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
+				&SEMANAGE_IBENDPORT_RTABLE,
+				&SEMANAGE_IBENDPORT_POLICYDB_RTABLE,
+				&dconfig->dbase) < 0)
+		return STATUS_ERR;
+
+	dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE;
+
+	return STATUS_SUCCESS;
+}
+
+void ibendport_policydb_dbase_release(dbase_config_t *dconfig)
+{
+	dbase_policydb_release(dconfig->dbase);
+}
diff --git a/libsemanage/src/ibpkey_internal.h b/libsemanage/src/ibpkey_internal.h
new file mode 100644
index 0000000..9465bb8
--- /dev/null
+++ b/libsemanage/src/ibpkey_internal.h
@@ -0,0 +1,52 @@
+#ifndef _SEMANAGE_IBPKEY_INTERNAL_H_
+#define _SEMANAGE_IBPKEY_INTERNAL_H_
+
+#include <semanage/ibpkey_record.h>
+#include <semanage/ibpkeys_local.h>
+#include <semanage/ibpkeys_policy.h>
+#include "database.h"
+#include "handle.h"
+#include "dso.h"
+
+hidden_proto(semanage_ibpkey_create)
+hidden_proto(semanage_ibpkey_compare)
+hidden_proto(semanage_ibpkey_compare2)
+hidden_proto(semanage_ibpkey_clone)
+hidden_proto(semanage_ibpkey_free)
+hidden_proto(semanage_ibpkey_key_extract)
+hidden_proto(semanage_ibpkey_key_free)
+hidden_proto(semanage_ibpkey_get_high)
+hidden_proto(semanage_ibpkey_get_low)
+hidden_proto(semanage_ibpkey_set_pkey)
+hidden_proto(semanage_ibpkey_set_range)
+hidden_proto(semanage_ibpkey_get_con)
+hidden_proto(semanage_ibpkey_set_con)
+hidden_proto(semanage_ibpkey_list_local)
+hidden_proto(semanage_ibpkey_get_subnet_prefix)
+hidden_proto(semanage_ibpkey_get_subnet_prefix_bytes)
+hidden_proto(semanage_ibpkey_set_subnet_prefix)
+hidden_proto(semanage_ibpkey_set_subnet_prefix_bytes)
+
+/* PKEY RECORD: method table */
+extern record_table_t SEMANAGE_IBPKEY_RTABLE;
+
+extern int ibpkey_file_dbase_init(semanage_handle_t *handle,
+				  const char *path_ro,
+				  const char *path_rw,
+				  dbase_config_t *dconfig);
+
+extern void ibpkey_file_dbase_release(dbase_config_t *dconfig);
+
+extern int ibpkey_policydb_dbase_init(semanage_handle_t *handle,
+				      dbase_config_t *dconfig);
+
+extern void ibpkey_policydb_dbase_release(dbase_config_t *dconfig);
+
+extern int hidden semanage_ibpkey_validate_local(semanage_handle_t *handle);
+
+/* ==== Internal (to ibpkeys) API === */
+
+hidden int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t **ibpkey,
+					  const semanage_ibpkey_t **ibpkey2);
+
+#endif
diff --git a/libsemanage/src/ibpkey_record.c b/libsemanage/src/ibpkey_record.c
new file mode 100644
index 0000000..ca5bc76
--- /dev/null
+++ b/libsemanage/src/ibpkey_record.c
@@ -0,0 +1,182 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc. */
+
+/* Object: semanage_ibpkey_t (Infiniband Pkey)
+ * Object: semanage_ibpkey_key_t (Infiniband Pkey Key)
+ * Implements: record_t (Database Record)
+ * Implements: record_key_t (Database Record Key)
+ */
+
+#include <sepol/context_record.h>
+#include <sepol/ibpkey_record.h>
+
+typedef sepol_context_t semanage_context_t;
+typedef sepol_ibpkey_t semanage_ibpkey_t;
+typedef sepol_ibpkey_key_t semanage_ibpkey_key_t;
+#define _SEMANAGE_IBPKEY_DEFINED_
+#define _SEMANAGE_CONTEXT_DEFINED_
+
+typedef semanage_ibpkey_t record_t;
+typedef semanage_ibpkey_key_t record_key_t;
+#define DBASE_RECORD_DEFINED
+
+#include "ibpkey_internal.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
+			    const semanage_ibpkey_key_t *key)
+{
+	return sepol_ibpkey_compare(ibpkey, key);
+}
+
+hidden_def(semanage_ibpkey_compare)
+
+int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
+			     const semanage_ibpkey_t *ibpkey2)
+{
+	return sepol_ibpkey_compare2(ibpkey, ibpkey2);
+}
+
+hidden_def(semanage_ibpkey_compare2)
+
+hidden int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t **ibpkey,
+					  const semanage_ibpkey_t **ibpkey2)
+{
+	return sepol_ibpkey_compare2(*ibpkey, *ibpkey2);
+}
+
+int semanage_ibpkey_key_create(semanage_handle_t *handle,
+			       const char *subnet_prefix,
+			       int low, int high,
+			       semanage_ibpkey_key_t **key_ptr)
+{
+	return sepol_ibpkey_key_create(handle->sepolh, subnet_prefix, low, high, key_ptr);
+}
+
+int semanage_ibpkey_key_extract(semanage_handle_t *handle,
+				const semanage_ibpkey_t *ibpkey,
+				semanage_ibpkey_key_t **key_ptr)
+{
+	return sepol_ibpkey_key_extract(handle->sepolh, ibpkey, key_ptr);
+}
+
+hidden_def(semanage_ibpkey_key_extract)
+
+void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key)
+{
+	sepol_ibpkey_key_free(key);
+}
+
+hidden_def(semanage_ibpkey_key_free)
+
+int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle,
+				      const semanage_ibpkey_t *ibpkey,
+				      char **subnet_prefix_ptr)
+{
+	return sepol_ibpkey_get_subnet_prefix(handle->sepolh, ibpkey, subnet_prefix_ptr);
+}
+
+hidden_def(semanage_ibpkey_get_subnet_prefix)
+
+uint64_t semanage_ibpkey_get_subnet_prefix_bytes(const semanage_ibpkey_t *ibpkey)
+{
+	return sepol_ibpkey_get_subnet_prefix_bytes(ibpkey);
+}
+
+hidden_def(semanage_ibpkey_get_subnet_prefix_bytes)
+
+int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle,
+				      semanage_ibpkey_t *ibpkey,
+				      const char *subnet_prefix)
+{
+	return sepol_ibpkey_set_subnet_prefix(handle->sepolh, ibpkey, subnet_prefix);
+}
+
+hidden_def(semanage_ibpkey_set_subnet_prefix)
+
+void semanage_ibpkey_set_subnet_prefix_bytes(semanage_ibpkey_t *ibpkey,
+					     uint64_t subnet_prefix)
+{
+	return sepol_ibpkey_set_subnet_prefix_bytes(ibpkey, subnet_prefix);
+}
+
+hidden_def(semanage_ibpkey_set_subnet_prefix_bytes)
+
+int semanage_ibpkey_get_low(const semanage_ibpkey_t *ibpkey)
+{
+	return sepol_ibpkey_get_low(ibpkey);
+}
+
+hidden_def(semanage_ibpkey_get_low)
+
+int semanage_ibpkey_get_high(const semanage_ibpkey_t *ibpkey)
+{
+	return sepol_ibpkey_get_high(ibpkey);
+}
+
+hidden_def(semanage_ibpkey_get_high)
+
+void semanage_ibpkey_set_pkey(semanage_ibpkey_t *ibpkey, int ibpkey_num)
+{
+	sepol_ibpkey_set_pkey(ibpkey, ibpkey_num);
+}
+
+hidden_def(semanage_ibpkey_set_pkey)
+
+void semanage_ibpkey_set_range(semanage_ibpkey_t *ibpkey, int low, int high)
+{
+	sepol_ibpkey_set_range(ibpkey, low, high);
+}
+
+hidden_def(semanage_ibpkey_set_range)
+
+semanage_context_t *semanage_ibpkey_get_con(const semanage_ibpkey_t *ibpkey)
+{
+	return sepol_ibpkey_get_con(ibpkey);
+}
+
+hidden_def(semanage_ibpkey_get_con)
+
+int semanage_ibpkey_set_con(semanage_handle_t *handle,
+			    semanage_ibpkey_t *ibpkey, semanage_context_t *con)
+{
+	return sepol_ibpkey_set_con(handle->sepolh, ibpkey, con);
+}
+
+hidden_def(semanage_ibpkey_set_con)
+
+int semanage_ibpkey_create(semanage_handle_t *handle,
+			   semanage_ibpkey_t **ibpkey_ptr)
+{
+	return sepol_ibpkey_create(handle->sepolh, ibpkey_ptr);
+}
+
+hidden_def(semanage_ibpkey_create)
+
+int semanage_ibpkey_clone(semanage_handle_t *handle,
+			  const semanage_ibpkey_t *ibpkey,
+			  semanage_ibpkey_t **ibpkey_ptr)
+{
+	return sepol_ibpkey_clone(handle->sepolh, ibpkey, ibpkey_ptr);
+}
+
+hidden_def(semanage_ibpkey_clone)
+
+void semanage_ibpkey_free(semanage_ibpkey_t *ibpkey)
+{
+	sepol_ibpkey_free(ibpkey);
+}
+
+hidden_def(semanage_ibpkey_free)
+
+/* key base functions */
+record_table_t SEMANAGE_IBPKEY_RTABLE = {
+	.create = semanage_ibpkey_create,
+	.key_extract = semanage_ibpkey_key_extract,
+	.key_free = semanage_ibpkey_key_free,
+	.clone = semanage_ibpkey_clone,
+	.compare = semanage_ibpkey_compare,
+	.compare2 = semanage_ibpkey_compare2,
+	.compare2_qsort = semanage_ibpkey_compare2_qsort,
+	.free = semanage_ibpkey_free,
+};
diff --git a/libsemanage/src/ibpkeys_file.c b/libsemanage/src/ibpkeys_file.c
new file mode 100644
index 0000000..ceaea7a
--- /dev/null
+++ b/libsemanage/src/ibpkeys_file.c
@@ -0,0 +1,181 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc. */
+
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey record_t;
+typedef struct semanage_ibpkey_key record_key_t;
+#define DBASE_RECORD_DEFINED
+
+struct dbase_file;
+typedef struct dbase_file dbase_t;
+#define DBASE_DEFINED
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <semanage/handle.h>
+#include "ibpkey_internal.h"
+#include "context_internal.h"
+#include "database_file.h"
+#include "parse_utils.h"
+#include "debug.h"
+
+static int ibpkey_print(semanage_handle_t *handle,
+			semanage_ibpkey_t *ibpkey, FILE *str)
+{
+	char *con_str = NULL;
+	char *subnet_prefix_str = NULL;
+
+	int low = semanage_ibpkey_get_low(ibpkey);
+	int high = semanage_ibpkey_get_high(ibpkey);
+
+	if (semanage_ibpkey_get_subnet_prefix(handle, ibpkey, &subnet_prefix_str) != 0)
+		goto err;
+
+	semanage_context_t *con = semanage_ibpkey_get_con(ibpkey);
+
+	if (fprintf(str, "ibpkeycon %s ", subnet_prefix_str) < 0)
+		goto err;
+
+	if (low == high) {
+		if (fprintf(str, "%d ", low) < 0)
+			goto err;
+	} else {
+		if (fprintf(str, "%d - %d ", low, high) < 0)
+			goto err;
+	}
+
+	if (semanage_context_to_string(handle, con, &con_str) < 0)
+		goto err;
+	if (fprintf(str, "%s\n", con_str) < 0)
+		goto err;
+
+	free(subnet_prefix_str);
+	free(con_str);
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not print ibpkey range (%s) %u - %u to stream",
+	    subnet_prefix_str, low, high);
+	free(subnet_prefix_str);
+	free(con_str);
+	return STATUS_ERR;
+}
+
+static int ibpkey_parse(semanage_handle_t *handle,
+			parse_info_t *info, semanage_ibpkey_t *ibpkey)
+{
+	int low, high;
+	char *str = NULL;
+	semanage_context_t *con = NULL;
+
+	if (parse_skip_space(handle, info) < 0)
+		goto err;
+	if (!info->ptr)
+		goto last;
+
+	/* Header */
+	if (parse_assert_str(handle, info, "ibpkeycon") < 0)
+		goto err;
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+
+	/* Subnet Prefix */
+	if (parse_fetch_string(handle, info, &str, ' ') < 0)
+		goto err;
+	if (semanage_ibpkey_set_subnet_prefix(handle, ibpkey, str) < 0)
+		goto err;
+	free(str);
+	str = NULL;
+
+	/* Range/Pkey */
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+	if (parse_fetch_int(handle, info, &low, '-') < 0)
+		goto err;
+
+	/* If range (-) does not follow immediately, require a space
+	 * In other words, the space here is optional, but only
+	 * in the ranged case, not in the single ibpkey case,
+	 * so do a custom test
+	 */
+	if (*info->ptr && *info->ptr != '-') {
+		if (parse_assert_space(handle, info) < 0)
+			goto err;
+	}
+
+	if (parse_optional_ch(info, '-') != STATUS_NODATA) {
+		if (parse_skip_space(handle, info) < 0)
+			goto err;
+		if (parse_fetch_int(handle, info, &high, ' ') < 0)
+			goto err;
+		if (parse_assert_space(handle, info) < 0)
+			goto err;
+		semanage_ibpkey_set_range(ibpkey, low, high);
+	} else {
+		semanage_ibpkey_set_pkey(ibpkey, low);
+	}
+	/* Pkey context */
+	if (parse_fetch_string(handle, info, &str, ' ') < 0)
+		goto err;
+	if (semanage_context_from_string(handle, str, &con) < 0) {
+		ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
+		    str, info->filename, info->lineno, info->orig_line);
+		goto err;
+	}
+	if (!con) {
+		ERR(handle, "<<none>> context is not valid for ibpkeys (%s: %u):\n%s",
+		    info->filename,
+		    info->lineno, info->orig_line);
+		goto err;
+	}
+	free(str);
+	str = NULL;
+
+	if (semanage_ibpkey_set_con(handle, ibpkey, con) < 0)
+		goto err;
+
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+
+	semanage_context_free(con);
+	return STATUS_SUCCESS;
+
+last:
+	parse_dispose_line(info);
+	return STATUS_NODATA;
+
+err:
+	ERR(handle, "could not parse ibpkey record");
+	free(str);
+	semanage_context_free(con);
+	parse_dispose_line(info);
+	return STATUS_ERR;
+}
+
+/* IBPKEY RECORD: FILE extension: method table */
+record_file_table_t SEMANAGE_IBPKEY_FILE_RTABLE = {
+	.parse = ibpkey_parse,
+	.print = ibpkey_print,
+};
+
+int ibpkey_file_dbase_init(semanage_handle_t *handle,
+			   const char *path_ro,
+			   const char *path_rw,
+			   dbase_config_t *dconfig)
+{
+	if (dbase_file_init(handle,
+			    path_ro,
+			    path_rw,
+			    &SEMANAGE_IBPKEY_RTABLE,
+			    &SEMANAGE_IBPKEY_FILE_RTABLE, &dconfig->dbase) < 0)
+		return STATUS_ERR;
+
+	dconfig->dtable = &SEMANAGE_FILE_DTABLE;
+	return STATUS_SUCCESS;
+}
+
+void ibpkey_file_dbase_release(dbase_config_t *dconfig)
+{
+	dbase_file_release(dconfig->dbase);
+}
diff --git a/libsemanage/src/ibpkeys_local.c b/libsemanage/src/ibpkeys_local.c
new file mode 100644
index 0000000..e194ee0
--- /dev/null
+++ b/libsemanage/src/ibpkeys_local.c
@@ -0,0 +1,164 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc. */
+
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey_key record_key_t;
+typedef struct semanage_ibpkey record_t;
+#define DBASE_RECORD_DEFINED
+
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include "ibpkey_internal.h"
+#include "debug.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibpkey_modify_local(semanage_handle_t *handle,
+				 const semanage_ibpkey_key_t *key,
+				 const semanage_ibpkey_t *data)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
+
+	return dbase_modify(handle, dconfig, key, data);
+}
+
+int semanage_ibpkey_del_local(semanage_handle_t *handle,
+			      const semanage_ibpkey_key_t *key)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
+
+	return dbase_del(handle, dconfig, key);
+}
+
+int semanage_ibpkey_query_local(semanage_handle_t *handle,
+				const semanage_ibpkey_key_t *key,
+				semanage_ibpkey_t **response)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
+
+	return dbase_query(handle, dconfig, key, response);
+}
+
+int semanage_ibpkey_exists_local(semanage_handle_t *handle,
+				 const semanage_ibpkey_key_t *key,
+				 int *response)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
+
+	return dbase_exists(handle, dconfig, key, response);
+}
+
+int semanage_ibpkey_count_local(semanage_handle_t *handle,
+				unsigned int *response)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
+
+	return dbase_count(handle, dconfig, response);
+}
+
+int semanage_ibpkey_iterate_local(semanage_handle_t *handle,
+				  int (*handler)(const semanage_ibpkey_t *record,
+						 void *varg), void *handler_arg)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
+
+	return dbase_iterate(handle, dconfig, handler, handler_arg);
+}
+
+int semanage_ibpkey_list_local(semanage_handle_t *handle,
+			       semanage_ibpkey_t ***records, unsigned int *count)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
+
+	return dbase_list(handle, dconfig, records, count);
+}
+
+hidden_def(semanage_ibpkey_list_local)
+
+int hidden semanage_ibpkey_validate_local(semanage_handle_t *handle)
+{
+	semanage_ibpkey_t **ibpkeys = NULL;
+	unsigned int nibpkeys = 0;
+	unsigned int i = 0, j = 0;
+	uint64_t subnet_prefix;
+	uint64_t subnet_prefix2;
+	char *subnet_prefix_str;
+	char *subnet_prefix_str2;
+	int low, high;
+	int low2, high2;
+
+	/* List and sort the ibpkeys */
+	if (semanage_ibpkey_list_local(handle, &ibpkeys, &nibpkeys) < 0)
+		goto err;
+
+	qsort(ibpkeys, nibpkeys, sizeof(semanage_ibpkey_t *),
+	      (int (*)(const void *, const void *))
+	      &semanage_ibpkey_compare2_qsort);
+
+	/* Test each ibpkey for overlap */
+	while (i < nibpkeys) {
+		if (STATUS_SUCCESS != semanage_ibpkey_get_subnet_prefix(handle,
+									ibpkeys[i],
+									&subnet_prefix_str)) {
+			ERR(handle, "Couldn't get subnet prefix string");
+			goto err;
+		}
+
+		subnet_prefix = semanage_ibpkey_get_subnet_prefix_bytes(ibpkeys[i]);
+		low = semanage_ibpkey_get_low(ibpkeys[i]);
+		high = semanage_ibpkey_get_high(ibpkeys[i]);
+
+		/* Find the first ibpkey with matching
+		 * subnet_prefix to compare against
+		 */
+		do {
+			if (j == nibpkeys - 1)
+				goto next;
+			j++;
+
+			if (STATUS_SUCCESS !=
+				semanage_ibpkey_get_subnet_prefix(handle,
+								  ibpkeys[j],
+								  &subnet_prefix_str2)) {
+				ERR(handle, "Couldn't get subnet prefix string");
+				goto err;
+			}
+			subnet_prefix2 = semanage_ibpkey_get_subnet_prefix_bytes(ibpkeys[j]);
+			low2 = semanage_ibpkey_get_low(ibpkeys[j]);
+			high2 = semanage_ibpkey_get_high(ibpkeys[j]);
+		} while (subnet_prefix != subnet_prefix2);
+
+		/* Overlap detected */
+		if (low2 <= high) {
+			ERR(handle, "ibpkey overlap between ranges "
+			    "(%s) %u - %u <--> (%s) %u - %u.",
+			    subnet_prefix_str, low, high,
+			    subnet_prefix_str2, low2, high2);
+			goto invalid;
+		}
+
+		/* If closest ibpkey of matching subnet prefix doesn't overlap
+		 * with test ibpkey, neither do the rest of them, because that's
+		 * how the sort function works on ibpkeys - lower bound
+		 * ibpkeys come first
+		 */
+next:
+		i++;
+		j = i;
+	}
+
+	for (i = 0; i < nibpkeys; i++)
+		semanage_ibpkey_free(ibpkeys[i]);
+	free(ibpkeys);
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not complete ibpkeys validity check");
+
+invalid:
+	for (i = 0; i < nibpkeys; i++)
+		semanage_ibpkey_free(ibpkeys[i]);
+	free(ibpkeys);
+	return STATUS_ERR;
+}
diff --git a/libsemanage/src/ibpkeys_policy.c b/libsemanage/src/ibpkeys_policy.c
new file mode 100644
index 0000000..0956230
--- /dev/null
+++ b/libsemanage/src/ibpkeys_policy.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc. */
+
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey_key record_key_t;
+typedef struct semanage_ibpkey record_t;
+#define DBASE_RECORD_DEFINED
+
+#include "ibpkey_internal.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibpkey_query(semanage_handle_t *handle,
+			  const semanage_ibpkey_key_t *key,
+			  semanage_ibpkey_t **response)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle);
+
+	return dbase_query(handle, dconfig, key, response);
+}
+
+int semanage_ibpkey_exists(semanage_handle_t *handle,
+			   const semanage_ibpkey_key_t *key, int *response)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle);
+
+	return dbase_exists(handle, dconfig, key, response);
+}
+
+int semanage_ibpkey_count(semanage_handle_t *handle, unsigned int *response)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle);
+
+	return dbase_count(handle, dconfig, response);
+}
+
+int semanage_ibpkey_iterate(semanage_handle_t *handle,
+			    int (*handler)(const semanage_ibpkey_t *record,
+					   void *varg), void *handler_arg)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle);
+
+	return dbase_iterate(handle, dconfig, handler, handler_arg);
+}
+
+int semanage_ibpkey_list(semanage_handle_t *handle,
+			 semanage_ibpkey_t ***records, unsigned int *count)
+{
+	dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle);
+
+	return dbase_list(handle, dconfig, records, count);
+}
diff --git a/libsemanage/src/ibpkeys_policydb.c b/libsemanage/src/ibpkeys_policydb.c
new file mode 100644
index 0000000..8d73cf6
--- /dev/null
+++ b/libsemanage/src/ibpkeys_policydb.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 Mellanox Technologies Inc
+ *
+ *  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.
+ */
+
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey record_t;
+typedef struct semanage_ibpkey_key record_key_t;
+#define DBASE_RECORD_DEFINED
+
+struct dbase_policydb;
+typedef struct dbase_policydb dbase_t;
+#define DBASE_DEFINED
+
+#include <sepol/ibpkeys.h>
+#include <semanage/handle.h>
+#include "ibpkey_internal.h"
+#include "debug.h"
+#include "database_policydb.h"
+#include "semanage_store.h"
+
+/* PKEY RECORD (SEPOL): POLICYDB extension : method table */
+record_policydb_table_t SEMANAGE_IBPKEY_POLICYDB_RTABLE = {
+	.add = NULL,
+	.modify = (record_policydb_table_modify_t)sepol_ibpkey_modify,
+	.set = NULL,
+	.query = (record_policydb_table_query_t)sepol_ibpkey_query,
+	.count = (record_policydb_table_count_t)sepol_ibpkey_count,
+	.exists = (record_policydb_table_exists_t)sepol_ibpkey_exists,
+	.iterate = (record_policydb_table_iterate_t)sepol_ibpkey_iterate,
+};
+
+int ibpkey_policydb_dbase_init(semanage_handle_t *handle,
+			       dbase_config_t *dconfig)
+{
+	if (dbase_policydb_init(handle,
+				semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL),
+				semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
+				&SEMANAGE_IBPKEY_RTABLE,
+				&SEMANAGE_IBPKEY_POLICYDB_RTABLE,
+				&dconfig->dbase) < 0)
+		return STATUS_ERR;
+
+	dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE;
+
+	return STATUS_SUCCESS;
+}
+
+void ibpkey_policydb_dbase_release(dbase_config_t *dconfig)
+{
+	dbase_policydb_release(dconfig->dbase);
+}
diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
index 9f8a754..0203669 100644
--- a/libsemanage/src/libsemanage.map
+++ b/libsemanage/src/libsemanage.map
@@ -18,6 +18,8 @@
 	  semanage_root;
 	  semanage_user_*; semanage_bool_*; semanage_seuser_*;
 	  semanage_iface_*; semanage_port_*; semanage_context_*;
+	  semanage_ibpkey_*;
+	  semanage_ibendport_*;
 	  semanage_node_*;
 	  semanage_fcontext_*; semanage_access_check; semanage_set_create_store;
 	  semanage_is_connected; semanage_get_disable_dontaudit; semanage_set_disable_dontaudit;
diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
index 90c5e49..62af101 100644
--- a/libsemanage/src/modules.c
+++ b/libsemanage/src/modules.c
@@ -600,8 +600,10 @@
 			break;
 		case SEMANAGE_MODULE_PATH_HLL:
 			if (file == NULL) file = "hll";
+			/* FALLTHRU */
 		case SEMANAGE_MODULE_PATH_CIL:
 			if (file == NULL) file = "cil";
+			/* FALLTHRU */
 		case SEMANAGE_MODULE_PATH_LANG_EXT:
 			if (file == NULL) file = "lang_ext";
 
diff --git a/libsemanage/src/policy_components.c b/libsemanage/src/policy_components.c
index d31bd48..896ac51 100644
--- a/libsemanage/src/policy_components.c
+++ b/libsemanage/src/policy_components.c
@@ -137,12 +137,17 @@
 
 		{semanage_node_dbase_local(handle),
 		 semanage_node_dbase_policy(handle), MODE_MODIFY | MODE_SORT},
+
+		{semanage_ibpkey_dbase_local(handle),
+		 semanage_ibpkey_dbase_policy(handle), MODE_MODIFY},
+
+		{semanage_ibendport_dbase_local(handle),
+		 semanage_ibendport_dbase_policy(handle), MODE_MODIFY},
 	};
 	const unsigned int CCOUNT = sizeof(components) / sizeof(components[0]);
 
 	/* Merge components into policy (and validate) */
 	for (i = 0; i < CCOUNT; i++) {
-
 		record_t **records = NULL;
 		unsigned int nrecords = 0;
 
@@ -218,6 +223,8 @@
 		semanage_seuser_dbase_policy(handle),
 		semanage_bool_dbase_active(handle),
 		semanage_node_dbase_local(handle),
+		semanage_ibpkey_dbase_local(handle),
+		semanage_ibendport_dbase_local(handle),
 	};
 	const int CCOUNT = sizeof(components) / sizeof(components[0]);
 
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 6b75002..6158d08 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -99,6 +99,8 @@
 	"/homedir_template",
 	"/file_contexts.template",
 	"/commit_num",
+	"/pkeys.local",
+	"/ibendports.local",
 	"/ports.local",
 	"/interfaces.local",
 	"/nodes.local",
@@ -812,7 +814,7 @@
 		return -1;
 	}
 	for (i = 0; i < num_entries; i++) {
-		char s[NAME_MAX];
+		char s[PATH_MAX];
 		struct stat buf;
 		snprintf(s, sizeof(s), "%s/%s", path, namelist[i]->d_name);
 		if (stat(s, &buf) == -1) {
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index 0b96fbe..fcaa505 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -44,6 +44,8 @@
 	SEMANAGE_HOMEDIR_TMPL,
 	SEMANAGE_FC_TMPL,
 	SEMANAGE_COMMIT_NUM_FILE,
+	SEMANAGE_IBPKEYS_LOCAL,
+	SEMANAGE_IBENDPORTS_LOCAL,
 	SEMANAGE_PORTS_LOCAL,
 	SEMANAGE_INTERFACES_LOCAL,
 	SEMANAGE_NODES_LOCAL,
diff --git a/libsemanage/src/semanageswig.i b/libsemanage/src/semanageswig.i
index 583b7d8..ebf39cf 100644
--- a/libsemanage/src/semanageswig.i
+++ b/libsemanage/src/semanageswig.i
@@ -39,6 +39,12 @@
 %include "../include/semanage/port_record.h"
 %include "../include/semanage/ports_local.h"
 %include "../include/semanage/ports_policy.h"
+%include "../include/semanage/ibpkey_record.h"
+%include "../include/semanage/ibpkeys_local.h"
+%include "../include/semanage/ibpkeys_policy.h"
+%include "../include/semanage/ibendport_record.h"
+%include "../include/semanage/ibendports_local.h"
+%include "../include/semanage/ibendports_policy.h"
 %include "../include/semanage/fcontext_record.h"
 %include "../include/semanage/fcontexts_local.h"
 %include "../include/semanage/fcontexts_policy.h"
diff --git a/libsemanage/src/semanageswig_python.i b/libsemanage/src/semanageswig_python.i
index 1346b2e..8604b8a 100644
--- a/libsemanage/src/semanageswig_python.i
+++ b/libsemanage/src/semanageswig_python.i
@@ -437,6 +437,92 @@
 	$1 = &temp;
 }
 
+/** ibpkey typemaps **/
+
+/* the wrapper will setup this parameter for passing... the resulting python functions
+   will not take the semanage_ibpkey_t *** parameter */
+%typemap(in, numinputs=0) semanage_ibpkey_t ***(semanage_ibpkey_t **temp=NULL) {
+	$1 = &temp;
+}
+
+%typemap(argout) (
+	semanage_handle_t* handle,
+	semanage_ibpkey_t*** records,
+	unsigned int* count) {
+
+	if ($result) {
+		int value;
+		SWIG_AsVal_int($result, &value);
+		if (value >= 0) {
+			PyObject* plist = NULL;
+			if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_ibpkey,
+				(void (*) (void*)) &semanage_ibpkey_free, &plist) < 0)
+				$result = SWIG_From_int(STATUS_ERR);
+			else
+				$result = SWIG_Python_AppendOutput($result, plist);
+		}
+	}
+}
+
+%typemap(in, numinputs=0) semanage_ibpkey_t **(semanage_ibpkey_t *temp=NULL) {
+	$1 = &temp;
+}
+
+%typemap(argout) semanage_ibpkey_t ** {
+	$result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+
+%typemap(argout) semanage_ibpkey_key_t ** {
+	$result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+
+%typemap(in, numinputs=0) semanage_ibpkey_key_t **(semanage_ibpkey_key_t *temp=NULL) {
+	$1 = &temp;
+}
+
+/** ibendport typemaps **/
+
+/* the wrapper will setup this parameter for passing... the resulting python functions
+   will not take the semanage_ibendport_t *** parameter */
+%typemap(in, numinputs=0) semanage_ibendport_t ***(semanage_ibendport_t **temp=NULL) {
+	$1 = &temp;
+}
+
+%typemap(argout) (
+	semanage_handle_t* handle,
+	semanage_ibendport_t*** records,
+	unsigned int* count) {
+
+	if ($result) {
+		int value;
+		SWIG_AsVal_int($result, &value);
+		if (value >= 0) {
+			PyObject* plist = NULL;
+			if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_ibendport,
+				(void (*) (void*)) &semanage_ibendport_free, &plist) < 0)
+				$result = SWIG_From_int(STATUS_ERR);
+			else
+				$result = SWIG_Python_AppendOutput($result, plist);
+		}
+	}
+}
+
+%typemap(in, numinputs=0) semanage_ibendport_t **(semanage_ibendport_t *temp=NULL) {
+	$1 = &temp;
+}
+
+%typemap(argout) semanage_ibendport_t ** {
+	$result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+
+%typemap(argout) semanage_ibendport_key_t ** {
+	$result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+
+%typemap(in, numinputs=0) semanage_ibendport_key_t **(semanage_ibendport_key_t *temp=NULL) {
+	$1 = &temp;
+}
+
 /** node typemaps **/
 
 /* the wrapper will setup this parameter for passing... the resulting python functions
diff --git a/libsemanage/tests/Makefile b/libsemanage/tests/Makefile
index 9b27224..2ef8d30 100644
--- a/libsemanage/tests/Makefile
+++ b/libsemanage/tests/Makefile
@@ -2,26 +2,21 @@
 LIBDIR ?= $(PREFIX)/lib
 
 # Add your test source files here:
-SOURCES = $(wildcard *.c)
-
-# Add the required external object files here:
-LIBS = ../src/libsemanage.a -lselinux -lsepol
+SOURCES = $(sort $(wildcard *.c))
 
 ###########################################################################
 
 EXECUTABLE = libsemanage-tests
 CFLAGS += -g -O0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter
-INCLUDE = -I../src -I../include
-LDLIBS += -lcunit -lbz2 -laudit
+override CFLAGS += -I../src -I../include
+override LDLIBS += -lcunit -lbz2 -laudit -lselinux -lsepol
+
 OBJECTS = $(SOURCES:.c=.o) 
 
 all: $(EXECUTABLE) 
 
 $(EXECUTABLE): $(OBJECTS) ../src/libsemanage.a
-	$(CC) $(OBJECTS) $(LIBS) $(LDFLAGS) -o $@ $(LDLIBS)
-
-%.o: %.c
-	$(CC) $(CFLAGS) $(INCLUDE) -c $*.c -o $*.o
+	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 
 clean distclean: 
 	rm -rf $(OBJECTS) $(EXECUTABLE)
diff --git a/libsemanage/utils/semanage_migrate_store b/libsemanage/utils/semanage_migrate_store
index 0ebd285..2e6cb27 100755
--- a/libsemanage/utils/semanage_migrate_store
+++ b/libsemanage/utils/semanage_migrate_store
@@ -253,7 +253,9 @@
 		"preserve_tunables",
 		"policy.kern",
 		"file_contexts",
-		"homedir_template"]
+		"homedir_template",
+		"pkeys.local",
+		"ibendports.local"]
 
 
 	create_dir(newroot_path(), 0o755)
diff --git a/libsepol/VERSION b/libsepol/VERSION
index 5154b3f..1effb00 100644
--- a/libsepol/VERSION
+++ b/libsepol/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/libsepol/cil/include/cil/cil.h b/libsepol/cil/include/cil/cil.h
index 4507892..86117f2 100644
--- a/libsepol/cil/include/cil/cil.h
+++ b/libsepol/cil/include/cil/cil.h
@@ -32,6 +32,10 @@
 
 #include <sepol/policydb/policydb.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct cil_db;
 typedef struct cil_db cil_db_t;
 
@@ -71,4 +75,7 @@
 
 extern void cil_set_malloc_error_handler(void (*handler)(void));
 
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 9b9ccc3..c02a41a 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -188,6 +188,8 @@
 	CIL_KEY_MLSVALIDATETRANS = cil_strpool_add("mlsvalidatetrans");
 	CIL_KEY_CONTEXT = cil_strpool_add("context");
 	CIL_KEY_FILECON = cil_strpool_add("filecon");
+	CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon");
+	CIL_KEY_IBENDPORTCON = cil_strpool_add("ibendportcon");
 	CIL_KEY_PORTCON = cil_strpool_add("portcon");
 	CIL_KEY_NODECON = cil_strpool_add("nodecon");
 	CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -257,6 +259,8 @@
 	cil_sort_init(&(*db)->genfscon);
 	cil_sort_init(&(*db)->filecon);
 	cil_sort_init(&(*db)->nodecon);
+	cil_sort_init(&(*db)->ibpkeycon);
+	cil_sort_init(&(*db)->ibendportcon);
 	cil_sort_init(&(*db)->portcon);
 	cil_sort_init(&(*db)->pirqcon);
 	cil_sort_init(&(*db)->iomemcon);
@@ -308,6 +312,8 @@
 	cil_sort_destroy(&(*db)->genfscon);
 	cil_sort_destroy(&(*db)->filecon);
 	cil_sort_destroy(&(*db)->nodecon);
+	cil_sort_destroy(&(*db)->ibpkeycon);
+	cil_sort_destroy(&(*db)->ibendportcon);
 	cil_sort_destroy(&(*db)->portcon);
 	cil_sort_destroy(&(*db)->pirqcon);
 	cil_sort_destroy(&(*db)->iomemcon);
@@ -728,9 +734,15 @@
 	case CIL_FILECON:
 		cil_destroy_filecon(*data);
 		break;
+	case CIL_IBPKEYCON:
+		cil_destroy_ibpkeycon(*data);
+		break;
 	case CIL_PORTCON:
 		cil_destroy_portcon(*data);
 		break;
+	case CIL_IBENDPORTCON:
+		cil_destroy_ibendportcon(*data);
+		break;
 	case CIL_NODECON:
 		cil_destroy_nodecon(*data);
 		break;
@@ -1097,6 +1109,10 @@
 		return CIL_KEY_FSUSE;
 	case CIL_FILECON:
 		return CIL_KEY_FILECON;
+	case CIL_IBPKEYCON:
+		return CIL_KEY_IBPKEYCON;
+	case CIL_IBENDPORTCON:
+		return CIL_KEY_IBENDPORTCON;
 	case CIL_PORTCON:
 		return CIL_KEY_PORTCON;
 	case CIL_NODECON:
@@ -1830,6 +1846,16 @@
 	(*netifcon)->context_str = NULL;
 }
 
+void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon)
+{
+	*ibendportcon = cil_malloc(sizeof(**ibendportcon));
+
+	(*ibendportcon)->dev_name_str = NULL;
+	(*ibendportcon)->port = 0;
+	(*ibendportcon)->context_str = NULL;
+	(*ibendportcon)->context = NULL;
+}
+
 void cil_context_init(struct cil_context **context)
 {
 	*context = cil_malloc(sizeof(**context));
@@ -2255,6 +2281,17 @@
 	(*filecon)->context = NULL;
 }
 
+void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon)
+{
+	*ibpkeycon = cil_malloc(sizeof(**ibpkeycon));
+
+	(*ibpkeycon)->subnet_prefix_str = NULL;
+	(*ibpkeycon)->pkey_low = 0;
+	(*ibpkeycon)->pkey_high = 0;
+	(*ibpkeycon)->context_str = NULL;
+	(*ibpkeycon)->context = NULL;
+}
+
 void cil_portcon_init(struct cil_portcon **portcon)
 {
 	*portcon = cil_malloc(sizeof(**portcon));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index e1481a4..c0ca60f 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3218,6 +3218,40 @@
 	return rc;
 }
 
+int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons)
+{
+	int rc = SEPOL_ERR;
+	uint32_t i = 0;
+	ocontext_t *tail = NULL;
+	struct in6_addr subnet_prefix;
+
+	for (i = 0; i < ibpkeycons->count; i++) {
+		struct cil_ibpkeycon *cil_ibpkeycon = ibpkeycons->array[i];
+		ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_IBPKEY], &tail);
+
+		rc = inet_pton(AF_INET6, cil_ibpkeycon->subnet_prefix_str, &subnet_prefix);
+		if (rc != 1) {
+			cil_log(CIL_ERR, "ibpkeycon subnet prefix not in valid IPV6 format\n");
+			rc = SEPOL_ERR;
+			goto exit;
+		}
+
+		memcpy(&new_ocon->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0],
+		       sizeof(new_ocon->u.ibpkey.subnet_prefix));
+		new_ocon->u.ibpkey.low_pkey = cil_ibpkeycon->pkey_low;
+		new_ocon->u.ibpkey.high_pkey = cil_ibpkeycon->pkey_high;
+
+		rc = __cil_context_to_sepol_context(pdb, cil_ibpkeycon->context, &new_ocon->context[0]);
+		if (rc != SEPOL_OK)
+			goto exit;
+	}
+
+	return SEPOL_OK;
+
+exit:
+	return rc;
+}
+
 int cil_portcon_to_policydb(policydb_t *pdb, struct cil_sort *portcons)
 {
 	int rc = SEPOL_ERR;
@@ -3289,6 +3323,30 @@
 	return rc;
 }
 
+int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort *ibendportcons)
+{
+	int rc = SEPOL_ERR;
+	uint32_t i;
+	ocontext_t *tail = NULL;
+
+	for (i = 0; i < ibendportcons->count; i++) {
+		ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_IBENDPORT], &tail);
+		struct cil_ibendportcon *cil_ibendportcon = ibendportcons->array[i];
+
+		new_ocon->u.ibendport.dev_name = cil_strdup(cil_ibendportcon->dev_name_str);
+		new_ocon->u.ibendport.port = cil_ibendportcon->port;
+
+		rc = __cil_context_to_sepol_context(pdb, cil_ibendportcon->context, &new_ocon->context[0]);
+		if (rc != SEPOL_OK)
+			goto exit;
+	}
+
+	return SEPOL_OK;
+
+exit:
+	return rc;
+}
+
 int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons)
 {
 	int rc = SEPOL_ERR;
@@ -3848,6 +3906,16 @@
 		goto exit;
 	}
 
+	rc = cil_ibpkeycon_to_policydb(pdb, db->ibpkeycon);
+	if (rc != SEPOL_OK) {
+		goto exit;
+	}
+
+	rc = cil_ibendportcon_to_policydb(pdb, db->ibendportcon);
+	if (rc != SEPOL_OK) {
+		goto exit;
+	}
+
 	if (db->target_platform == SEPOL_TARGET_XEN) {
 		rc = cil_pirqcon_to_policydb(pdb, db->pirqcon);
 		if (rc != SEPOL_OK) {
diff --git a/libsepol/cil/src/cil_binary.h b/libsepol/cil/src/cil_binary.h
index c59b1e3..5367feb 100644
--- a/libsepol/cil/src/cil_binary.h
+++ b/libsepol/cil/src/cil_binary.h
@@ -330,6 +330,30 @@
 int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_rangetransition *rangetrans, hashtab_t range_trans_table);
 
 /**
+ * Insert cil ibpkeycon structure into sepol policydb.
+ * The function is given a structure containing the sorted ibpkeycons and
+ * loops over this structure inserting them into the policy database.
+ *
+ * @param[in] pdb The policy database to insert the ibpkeycon into.
+ * @param[in] node The cil_sort structure that contains the sorted ibpkeycons.
+ *
+ * @return SEPOL_OK upon success or an error otherwise.
+ */
+int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons);
+
+/**
+ * Insert cil idbev structure into sepol policydb.
+ * The function is given a structure containing the sorted ibendportcons and
+ * loops over this structure inserting them into the policy database.
+ *
+ * @param[in] pdb The policy database to insert the pkeycon into.
+ * @param[in] node The cil_sort structure that contains the sorted ibendportcons.
+ *
+ * @return SEPOL_OK upon success or an error otherwise.
+ */
+int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort *pkeycons);
+
+/**
  * Insert cil portcon structure into sepol policydb.
  * The function is given a structure containing the sorted portcons and
  * loops over this structure inserting them into the policy database.
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 36cc673..04492e5 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -4256,6 +4256,89 @@
 	free(filecon);
 }
 
+int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
+{
+	enum cil_syntax syntax[] = {
+		CIL_SYN_STRING,
+		CIL_SYN_STRING,
+		CIL_SYN_STRING | CIL_SYN_LIST,
+		CIL_SYN_STRING | CIL_SYN_LIST,
+		CIL_SYN_END
+	};
+	int syntax_len = sizeof(syntax) / sizeof(*syntax);
+	int rc = SEPOL_ERR;
+	struct cil_ibpkeycon *ibpkeycon = NULL;
+
+	if (!parse_current || !ast_node)
+		goto exit;
+
+	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
+	if (rc != SEPOL_OK)
+		goto exit;
+
+	cil_ibpkeycon_init(&ibpkeycon);
+
+	ibpkeycon->subnet_prefix_str = parse_current->next->data;
+
+	if (parse_current->next->next->cl_head) {
+		if (parse_current->next->next->cl_head->next &&
+		    !parse_current->next->next->cl_head->next->next) {
+			rc = cil_fill_integer(parse_current->next->next->cl_head, &ibpkeycon->pkey_low, 0);
+			if (rc != SEPOL_OK) {
+				cil_log(CIL_ERR, "Improper ibpkey specified\n");
+				goto exit;
+			}
+			rc = cil_fill_integer(parse_current->next->next->cl_head->next, &ibpkeycon->pkey_high, 0);
+			if (rc != SEPOL_OK) {
+				cil_log(CIL_ERR, "Improper ibpkey specified\n");
+				goto exit;
+			}
+		} else {
+			cil_log(CIL_ERR, "Improper ibpkey range specified\n");
+			rc = SEPOL_ERR;
+			goto exit;
+		}
+	} else {
+		rc = cil_fill_integer(parse_current->next->next, &ibpkeycon->pkey_low, 0);
+		if (rc != SEPOL_OK) {
+			cil_log(CIL_ERR, "Improper ibpkey specified\n");
+			goto exit;
+		}
+		ibpkeycon->pkey_high = ibpkeycon->pkey_low;
+	}
+
+	if (!parse_current->next->next->next->cl_head) {
+		ibpkeycon->context_str = parse_current->next->next->next->data;
+	} else {
+		cil_context_init(&ibpkeycon->context);
+
+		rc = cil_fill_context(parse_current->next->next->next->cl_head, ibpkeycon->context);
+		if (rc != SEPOL_OK)
+			goto exit;
+	}
+
+	ast_node->data = ibpkeycon;
+	ast_node->flavor = CIL_IBPKEYCON;
+	return SEPOL_OK;
+
+exit:
+	cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration");
+	cil_destroy_ibpkeycon(ibpkeycon);
+
+	return rc;
+}
+
+void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
+{
+	if (!ibpkeycon)
+		return;
+
+	if (!ibpkeycon->context_str && ibpkeycon->context)
+		cil_destroy_context(ibpkeycon->context);
+
+	free(ibpkeycon);
+}
+
 int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
 {
 	enum cil_syntax syntax[] = {
@@ -4584,6 +4667,68 @@
 	free(netifcon);
 }
 
+int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
+{
+	enum cil_syntax syntax[] = {
+		CIL_SYN_STRING,
+		CIL_SYN_STRING,
+		CIL_SYN_STRING,
+		CIL_SYN_STRING | CIL_SYN_LIST,
+		CIL_SYN_END
+	};
+	int syntax_len = sizeof(syntax) / sizeof(*syntax);
+	int rc = SEPOL_ERR;
+	struct cil_ibendportcon *ibendportcon = NULL;
+
+	if (!parse_current || !ast_node)
+		goto exit;
+
+	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
+	if (rc != SEPOL_OK)
+		goto exit;
+
+	cil_ibendportcon_init(&ibendportcon);
+
+	ibendportcon->dev_name_str = parse_current->next->data;
+
+	rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Improper ibendport port specified\n");
+		goto exit;
+	}
+
+	if (!parse_current->next->next->next->cl_head) {
+		ibendportcon->context_str = parse_current->next->next->next->data;
+	} else {
+		cil_context_init(&ibendportcon->context);
+
+		rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context);
+		if (rc != SEPOL_OK)
+			goto exit;
+	}
+
+	ast_node->data = ibendportcon;
+	ast_node->flavor = CIL_IBENDPORTCON;
+
+	return SEPOL_OK;
+
+exit:
+	cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
+	cil_destroy_ibendportcon(ibendportcon);
+	return SEPOL_ERR;
+}
+
+void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
+{
+	if (!ibendportcon)
+		return;
+
+	if (!ibendportcon->context_str && ibendportcon->context)
+		cil_destroy_context(ibendportcon->context);
+
+	free(ibendportcon);
+}
+
 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
 {
 	enum cil_syntax syntax[] = {
@@ -6215,6 +6360,12 @@
 	} else if (parse_current->data == CIL_KEY_FILECON) {
 		rc = cil_gen_filecon(db, parse_current, ast_node);
 		*finished = CIL_TREE_SKIP_NEXT;
+	} else if (parse_current->data == CIL_KEY_IBPKEYCON) {
+		rc = cil_gen_ibpkeycon(db, parse_current, ast_node);
+		*finished = CIL_TREE_SKIP_NEXT;
+	} else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
+		rc = cil_gen_ibendportcon(db, parse_current, ast_node);
+		*finished = CIL_TREE_SKIP_NEXT;
 	} else if (parse_current->data == CIL_KEY_PORTCON) {
 		rc = cil_gen_portcon(db, parse_current, ast_node);
 		*finished = CIL_TREE_SKIP_NEXT;
diff --git a/libsepol/cil/src/cil_build_ast.h b/libsepol/cil/src/cil_build_ast.h
index 33bae99..8153e51 100644
--- a/libsepol/cil/src/cil_build_ast.h
+++ b/libsepol/cil/src/cil_build_ast.h
@@ -175,6 +175,10 @@
 void cil_destroy_context(struct cil_context *context);
 int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
 void cil_destroy_filecon(struct cil_filecon *filecon);
+int cil_gen_ibpkeycon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
+void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon);
+int cil_gen_ibendportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
+void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon);
 int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
 void cil_destroy_portcon(struct cil_portcon *portcon);
 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c
index d668505..7af00aa 100644
--- a/libsepol/cil/src/cil_copy_ast.c
+++ b/libsepol/cil/src/cil_copy_ast.c
@@ -1204,6 +1204,51 @@
 	return SEPOL_OK;
 }
 
+int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
+{
+	struct cil_ibpkeycon *orig = data;
+	struct cil_ibpkeycon *new = NULL;
+
+	cil_ibpkeycon_init(&new);
+
+	new->subnet_prefix_str = orig->subnet_prefix_str;
+	new->pkey_low = orig->pkey_low;
+	new->pkey_high = orig->pkey_high;
+
+	if (orig->context_str) {
+		new->context_str = orig->context_str;
+	} else {
+		cil_context_init(&new->context);
+		cil_copy_fill_context(db, orig->context, new->context);
+	}
+
+	*copy = new;
+
+	return SEPOL_OK;
+}
+
+int cil_copy_ibendportcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
+{
+	struct cil_ibendportcon *orig = data;
+	struct cil_ibendportcon *new = NULL;
+
+	cil_ibendportcon_init(&new);
+
+	new->dev_name_str = orig->dev_name_str;
+	new->port = orig->port;
+
+	if (orig->context_str) {
+		new->context_str = orig->context_str;
+	} else {
+		cil_context_init(&new->context);
+		cil_copy_fill_context(db, orig->context, new->context);
+	}
+
+	*copy = new;
+
+	return SEPOL_OK;
+}
+
 int cil_copy_portcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
 {
 	struct cil_portcon *orig = data;
@@ -1916,6 +1961,12 @@
 	case CIL_NODECON:
 		copy_func = &cil_copy_nodecon;
 		break;
+	case CIL_IBPKEYCON:
+		copy_func = &cil_copy_ibpkeycon;
+		break;
+	case CIL_IBENDPORTCON:
+		copy_func = &cil_copy_ibendportcon;
+		break;
 	case CIL_PORTCON:
 		copy_func = &cil_copy_portcon;
 		break;
diff --git a/libsepol/cil/src/cil_copy_ast.h b/libsepol/cil/src/cil_copy_ast.h
index 78c34b8..a50c370 100644
--- a/libsepol/cil/src/cil_copy_ast.h
+++ b/libsepol/cil/src/cil_copy_ast.h
@@ -99,6 +99,7 @@
 int cil_copy_genfscon(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
 int cil_copy_filecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
 int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
+int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
 int cil_copy_portcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
 int cil_copy_pirqcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
 int cil_copy_iomemcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
diff --git a/libsepol/cil/src/cil_flavor.h b/libsepol/cil/src/cil_flavor.h
index c01f967..c2f0cee 100644
--- a/libsepol/cil/src/cil_flavor.h
+++ b/libsepol/cil/src/cil_flavor.h
@@ -113,6 +113,8 @@
 	CIL_HANDLEUNKNOWN,
 	CIL_MLS,
 	CIL_SRC_INFO,
+	CIL_IBPKEYCON,
+	CIL_IBENDPORTCON,
 
 /*
  *          boolean  constraint  set  catset
diff --git a/libsepol/cil/src/cil_fqn.c b/libsepol/cil/src/cil_fqn.c
index dad1347..717358a 100644
--- a/libsepol/cil/src/cil_fqn.c
+++ b/libsepol/cil/src/cil_fqn.c
@@ -121,7 +121,7 @@
 
 exit:
 	if (rc != SEPOL_OK) {
-		cil_tree_log(child_args.node, CIL_ERR,"Problem qualifying names in block");
+		cil_tree_log(node, CIL_ERR,"Problem qualifying names in block");
 	}
 
 	return rc;
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index aee3f00..6d6a7d9 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -203,6 +203,8 @@
 char *CIL_KEY_MLSVALIDATETRANS;
 char *CIL_KEY_CONTEXT;
 char *CIL_KEY_FILECON;
+char *CIL_KEY_IBPKEYCON;
+char *CIL_KEY_IBENDPORTCON;
 char *CIL_KEY_PORTCON;
 char *CIL_KEY_NODECON;
 char *CIL_KEY_GENFSCON;
@@ -286,6 +288,8 @@
 	struct cil_sort *genfscon;
 	struct cil_sort *filecon;
 	struct cil_sort *nodecon;
+	struct cil_sort *ibpkeycon;
+	struct cil_sort *ibendportcon;
 	struct cil_sort *portcon;
 	struct cil_sort *pirqcon;
 	struct cil_sort *iomemcon;
@@ -737,6 +741,14 @@
 	CIL_PROTOCOL_DCCP
 };
 
+struct cil_ibpkeycon {
+	char *subnet_prefix_str;
+	uint32_t pkey_low;
+	uint32_t pkey_high;
+	char *context_str;
+	struct cil_context *context;
+};
+
 struct cil_portcon {
 	enum cil_protocol proto;
 	uint32_t port_low;
@@ -779,6 +791,12 @@
 	char *context_str;
 };
 
+struct cil_ibendportcon {
+	char *dev_name_str;
+	uint32_t port;
+	char *context_str;
+	struct cil_context *context;
+};
 struct cil_pirqcon {
 	uint32_t pirq;
 	char *context_str;
@@ -964,6 +982,7 @@
 void cil_sort_init(struct cil_sort **sort);
 void cil_sort_destroy(struct cil_sort **sort);
 void cil_netifcon_init(struct cil_netifcon **netifcon);
+void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon);
 void cil_context_init(struct cil_context **context);
 void cil_level_init(struct cil_level **level);
 void cil_levelrange_init(struct cil_levelrange **lvlrange);
@@ -1007,6 +1026,7 @@
 void cil_cats_init(struct cil_cats **cats);
 void cil_senscat_init(struct cil_senscat **senscat);
 void cil_filecon_init(struct cil_filecon **filecon);
+void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon);
 void cil_portcon_init(struct cil_portcon **portcon);
 void cil_nodecon_init(struct cil_nodecon **nodecon);
 void cil_genfscon_init(struct cil_genfscon **genfscon);
diff --git a/libsepol/cil/src/cil_parser.c b/libsepol/cil/src/cil_parser.c
index 101520c..585ea77 100644
--- a/libsepol/cil/src/cil_parser.c
+++ b/libsepol/cil/src/cil_parser.c
@@ -251,6 +251,7 @@
 		case QSTRING:
 			tok.value[strlen(tok.value) - 1] = '\0';
 			tok.value = tok.value+1;
+			/* FALLTHRU */
 		case SYMBOL:
 			if (paren_count == 0) {
 				cil_log(CIL_ERR, "Symbol not inside parenthesis at line %d of %s\n", tok.line, path);
@@ -275,6 +276,7 @@
 			if (tok.type != END_OF_FILE) {
 				break;
 			}
+			/* FALLTHRU */
 			// Fall through if EOF
 		case END_OF_FILE:
 			if (paren_count > 0) {
diff --git a/libsepol/cil/src/cil_policy.c b/libsepol/cil/src/cil_policy.c
index 77179e6..729b6e0 100644
--- a/libsepol/cil/src/cil_policy.c
+++ b/libsepol/cil/src/cil_policy.c
@@ -1069,7 +1069,7 @@
 		child = i1->data;
 		if (child->bounds != NULL) {
 			parent = child->bounds;
-			fprintf(out, "typebounds %s %s\n", parent->datum.fqn, child->datum.fqn);
+			fprintf(out, "typebounds %s %s;\n", parent->datum.fqn, child->datum.fqn);
 		}
 	}
 }
@@ -1714,6 +1714,35 @@
 	}
 }
 
+static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int mls)
+{
+	uint32_t i = 0;
+
+	for (i = 0; i < ibpkeycons->count; i++) {
+		struct cil_ibpkeycon *ibpkeycon = (struct cil_ibpkeycon *)ibpkeycons->array[i];
+
+		fprintf(out, "ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
+		fprintf(out, "%d ", ibpkeycon->pkey_low);
+		fprintf(out, "%d ", ibpkeycon->pkey_high);
+		cil_context_to_policy(out, ibpkeycon->context, mls);
+		fprintf(out, "\n");
+	}
+}
+
+static void cil_ibendportcons_to_policy(FILE *out, struct cil_sort *ibendportcons, int mls)
+{
+	uint32_t i;
+
+	for (i = 0; i < ibendportcons->count; i++) {
+		struct cil_ibendportcon *ibendportcon = (struct cil_ibendportcon *)ibendportcons->array[i];
+
+		fprintf(out, "ibendportcon %s ", ibendportcon->dev_name_str);
+		fprintf(out, "%u ", ibendportcon->port);
+		cil_context_to_policy(out, ibendportcon->context, mls);
+		fprintf(out, "\n");
+	}
+}
+
 static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls)
 {
 	unsigned i;
@@ -1750,7 +1779,7 @@
 		cil_context_to_policy(out, netifcon->if_context, mls);
 		fprintf(out, " ");
 		cil_context_to_policy(out, netifcon->packet_context, mls);
-		fprintf(out, ";\n");
+		fprintf(out, "\n");
 	}
 }
 
@@ -1807,7 +1836,7 @@
 		}
 
 		cil_context_to_policy(out, nodecon->context, mls);
-		fprintf(out, ";\n");
+		fprintf(out, "\n");
 	}
 }
 
@@ -1899,9 +1928,9 @@
 	cil_commons_to_policy(out, lists[CIL_LIST_COMMON]);
 	cil_classes_to_policy(out, db->classorder);
 
-	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], CIL_KEY_DEFAULTUSER);
-	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], CIL_KEY_DEFAULTROLE);
-	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], CIL_KEY_DEFAULTTYPE);
+	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], "default_user");
+	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], "default_role");
+	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], "default_type");
 
 	if (db->mls == CIL_TRUE) {
 		cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]);
@@ -1942,6 +1971,8 @@
 	cil_genfscons_to_policy(out, db->genfscon, db->mls);
 	cil_portcons_to_policy(out, db->portcon, db->mls);
 	cil_netifcons_to_policy(out, db->netifcon, db->mls);
+	cil_ibpkeycons_to_policy(out, db->ibpkeycon, db->mls);
+	cil_ibendportcons_to_policy(out, db->ibendportcon, db->mls);
 	cil_nodecons_to_policy(out, db->nodecon, db->mls);
 	cil_pirqcons_to_policy(out, db->pirqcon, db->mls);
 	cil_iomemcons_to_policy(out, db->iomemcon, db->mls);
diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
index 1941fab..ad073e8 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -102,6 +102,7 @@
 			break;
 		case '\\':
 			c++;
+			/* FALLTHRU */
 		default:
 			if (!fc->meta) {
 				fc->stem_len++;
@@ -154,6 +155,28 @@
 	return rc;
 }
 
+int cil_post_ibpkeycon_compare(const void *a, const void *b)
+{
+	int rc = SEPOL_ERR;
+	struct cil_ibpkeycon *aibpkeycon = *(struct cil_ibpkeycon **)a;
+	struct cil_ibpkeycon *bibpkeycon = *(struct cil_ibpkeycon **)b;
+
+	rc = strcmp(aibpkeycon->subnet_prefix_str, bibpkeycon->subnet_prefix_str);
+	if (rc)
+		return rc;
+
+	rc = (aibpkeycon->pkey_high - aibpkeycon->pkey_low)
+		- (bibpkeycon->pkey_high - bibpkeycon->pkey_low);
+	if (rc == 0) {
+		if (aibpkeycon->pkey_low < bibpkeycon->pkey_low)
+			rc = -1;
+		else if (bibpkeycon->pkey_low < aibpkeycon->pkey_low)
+			rc = 1;
+	}
+
+	return rc;
+}
+
 int cil_post_portcon_compare(const void *a, const void *b)
 {
 	int rc = SEPOL_ERR;
@@ -195,6 +218,25 @@
 	return  strcmp(anetifcon->interface_str, bnetifcon->interface_str);
 }
 
+int cil_post_ibendportcon_compare(const void *a, const void *b)
+{
+	int rc = SEPOL_ERR;
+
+	struct cil_ibendportcon *aibendportcon = *(struct cil_ibendportcon **)a;
+	struct cil_ibendportcon *bibendportcon = *(struct cil_ibendportcon **)b;
+
+	rc = strcmp(aibendportcon->dev_name_str, bibendportcon->dev_name_str);
+	if (rc)
+		return rc;
+
+	if (aibendportcon->port < bibendportcon->port)
+		return -1;
+	else if (bibendportcon->port < aibendportcon->port)
+		return 1;
+
+	return rc;
+}
+
 int cil_post_nodecon_compare(const void *a, const void *b)
 {
 	struct cil_nodecon *anodecon;
@@ -401,6 +443,12 @@
 	case CIL_NODECON:
 		db->nodecon->count++;
 		break;
+	case CIL_IBPKEYCON:
+		db->ibpkeycon->count++;
+		break;
+	case CIL_IBENDPORTCON:
+		db->ibendportcon->count++;
+		break;
 	case CIL_PORTCON:
 		db->portcon->count++;
 		break;
@@ -491,6 +539,17 @@
 		sort->index++;
 		break;
 	}
+	case CIL_IBENDPORTCON: {
+		struct cil_sort *sort = db->ibendportcon;
+		uint32_t count = sort->count;
+		uint32_t i = sort->index;
+
+		if (!sort->array)
+			sort->array = cil_malloc(sizeof(*sort->array) * count);
+		sort->array[i] = node->data;
+		sort->index++;
+		break;
+	}
 	case CIL_FSUSE: {
 		struct cil_sort *sort = db->fsuse;
 		uint32_t count = sort->count;
@@ -535,6 +594,17 @@
 		sort->index++;
 		break;
 	}
+	case CIL_IBPKEYCON: {
+		struct cil_sort *sort = db->ibpkeycon;
+		uint32_t count = sort->count;
+		uint32_t i = sort->index;
+
+		if (!sort->array)
+			sort->array = cil_malloc(sizeof(*sort->array) * count);
+		sort->array[i] = node->data;
+		sort->index++;
+		break;
+	}
 	case CIL_PORTCON: {
 		struct cil_sort *sort = db->portcon;
 		uint32_t count = sort->count;
@@ -1618,6 +1688,22 @@
 		}
 		break;
 	}
+	case CIL_IBPKEYCON: {
+		struct cil_ibpkeycon *ibpkeycon = node->data;
+
+		rc = __evaluate_levelrange_expression(ibpkeycon->context->range, db);
+		if (rc != SEPOL_OK)
+			goto exit;
+		break;
+	}
+	case CIL_IBENDPORTCON: {
+		struct cil_ibendportcon *ibendportcon = node->data;
+
+		rc = __evaluate_levelrange_expression(ibendportcon->context->range, db);
+		if (rc != SEPOL_OK)
+			goto exit;
+		break;
+	}
 	case CIL_PORTCON: {
 		struct cil_portcon *portcon = node->data;
 		rc = __evaluate_levelrange_expression(portcon->context->range, db);
@@ -1977,6 +2063,8 @@
 
 	qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare);
 	qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
+	qsort(db->ibpkeycon->array, db->ibpkeycon->count, sizeof(db->ibpkeycon->array), cil_post_ibpkeycon_compare);
+	qsort(db->ibendportcon->array, db->ibendportcon->count, sizeof(db->ibendportcon->array), cil_post_ibendportcon_compare);
 	qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare);
 	qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare);
 	qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare);
diff --git a/libsepol/cil/src/cil_post.h b/libsepol/cil/src/cil_post.h
index 74393cc..3d54154 100644
--- a/libsepol/cil/src/cil_post.h
+++ b/libsepol/cil/src/cil_post.h
@@ -38,7 +38,9 @@
 
 void cil_post_fc_fill_data(struct fc_data *fc, char *path);
 int cil_post_filecon_compare(const void *a, const void *b);
+int cil_post_ibpkeycon_compare(const void *a, const void *b);
 int cil_post_portcon_compare(const void *a, const void *b);
+int cil_post_ibendportcon_compare(const void *a, const void *b);
 int cil_post_genfscon_compare(const void *a, const void *b);
 int cil_post_netifcon_compare(const void *a, const void *b);
 int cil_post_nodecon_compare(const void *a, const void *b);
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 676e156..8a13a1c 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -288,6 +288,12 @@
 	}
 }
 
+static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
+{
+	if (!ibpkeycon->context_str)
+		cil_reset_context(ibpkeycon->context);
+}
+
 static void cil_reset_portcon(struct cil_portcon *portcon)
 {
 	if (portcon->context_str == NULL) {
@@ -320,6 +326,13 @@
 	}
 }
 
+static void cil_reset_ibendportcon(struct cil_ibendportcon *ibendportcon)
+{
+	if (!ibendportcon->context_str) {
+		cil_reset_context(ibendportcon->context);
+	}
+}
+
 static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon)
 {
 	if (pirqcon->context_str == NULL) {
@@ -489,6 +502,12 @@
 	case CIL_FILECON:
 		cil_reset_filecon(node->data);
 		break;
+	case CIL_IBPKEYCON:
+		cil_reset_ibpkeycon(node->data);
+		break;
+	case CIL_IBENDPORTCON:
+		cil_reset_ibendportcon(node->data);
+		break;
 	case CIL_PORTCON:
 		cil_reset_portcon(node->data);
 		break;
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 8925b27..d1a5ed8 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -515,12 +515,13 @@
 		goto exit;
 	}
 
-	rc = cil_resolve_name(current, aliasactual->alias_str, sym_index, extra_args, &alias_datum);
+	rc = cil_resolve_name_keep_aliases(current, aliasactual->alias_str, sym_index, extra_args, &alias_datum);
 	if (rc != SEPOL_OK) {
 		goto exit;
 	}
 	if (NODE(alias_datum)->flavor != alias_flavor) {
 		cil_log(CIL_ERR, "%s is not an alias\n",alias_datum->name);
+		rc = SEPOL_ERR;
 		goto exit;
 	}
 
@@ -529,10 +530,16 @@
 		goto exit;
 	}
 
+	if (NODE(actual_datum)->flavor != flavor && NODE(actual_datum)->flavor != alias_flavor) {
+		cil_log(CIL_ERR, "%s is a %s, but aliases a %s\n", alias_datum->name, cil_node_to_string(NODE(alias_datum)), cil_node_to_string(NODE(actual_datum)));
+		rc = SEPOL_ERR;
+		goto exit;
+	}
+
 	alias = (struct cil_alias *)alias_datum;
 
 	if (alias->actual != NULL) {
-		cil_log(CIL_ERR, "Alias cannot bind more than one value\n");
+		cil_log(CIL_ERR, "%s %s cannot bind more than one value\n", cil_node_to_string(NODE(alias_datum)), alias_datum->name);
 		rc = SEPOL_ERR;
 		goto exit;
 	}
@@ -1923,6 +1930,30 @@
 	return SEPOL_OK;
 }
 
+int cil_resolve_ibpkeycon(struct cil_tree_node *current, void *extra_args)
+{
+	struct cil_ibpkeycon *ibpkeycon = current->data;
+	struct cil_symtab_datum *context_datum = NULL;
+	int rc = SEPOL_ERR;
+
+	if (ibpkeycon->context_str) {
+		rc = cil_resolve_name(current, ibpkeycon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
+		if (rc != SEPOL_OK)
+			goto exit;
+
+		ibpkeycon->context = (struct cil_context *)context_datum;
+	} else {
+		rc = cil_resolve_context(current, ibpkeycon->context, extra_args);
+		if (rc != SEPOL_OK)
+			goto exit;
+	}
+
+	return SEPOL_OK;
+
+exit:
+	return rc;
+}
+
 int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args)
 {
 	struct cil_portcon *portcon = current->data;
@@ -2062,6 +2093,31 @@
 	return rc;
 }
 
+int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args)
+{
+	struct cil_ibendportcon *ibendportcon = current->data;
+	struct cil_symtab_datum *con_datum = NULL;
+
+	int rc = SEPOL_ERR;
+
+	if (ibendportcon->context_str) {
+		rc = cil_resolve_name(current, ibendportcon->context_str, CIL_SYM_CONTEXTS, extra_args, &con_datum);
+		if (rc != SEPOL_OK)
+			goto exit;
+
+		ibendportcon->context = (struct cil_context *)con_datum;
+	} else {
+		rc = cil_resolve_context(current, ibendportcon->context, extra_args);
+		if (rc != SEPOL_OK)
+			goto exit;
+	}
+
+	return SEPOL_OK;
+
+exit:
+	return rc;
+}
+
 int cil_resolve_pirqcon(struct cil_tree_node *current, void *extra_args)
 {
 	struct cil_pirqcon *pirqcon = current->data;
@@ -3567,6 +3623,9 @@
 		case CIL_FILECON:
 			rc = cil_resolve_filecon(node, args);
 			break;
+		case CIL_IBPKEYCON:
+			rc = cil_resolve_ibpkeycon(node, args);
+			break;
 		case CIL_PORTCON:
 			rc = cil_resolve_portcon(node, args);
 			break;
@@ -3579,6 +3638,9 @@
 		case CIL_NETIFCON:
 			rc = cil_resolve_netifcon(node, args);
 			break;
+		case CIL_IBENDPORTCON:
+			rc = cil_resolve_ibendportcon(node, args);
+			break;
 		case CIL_PIRQCON:
 			rc = cil_resolve_pirqcon(node, args);
 			break;
@@ -4060,6 +4122,34 @@
 int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum)
 {
 	int rc = SEPOL_ERR;
+	struct cil_tree_node *node = NULL;
+
+	rc = cil_resolve_name_keep_aliases(ast_node, name, sym_index, extra_args, datum);
+	if (rc != SEPOL_OK) {
+		goto exit;
+	}
+
+	/* If this datum is an alias, then return the actual node
+	 * This depends on aliases already being processed
+	 */
+	node = NODE(*datum);
+	if (node->flavor == CIL_TYPEALIAS || node->flavor == CIL_SENSALIAS
+		|| node->flavor == CIL_CATALIAS) {
+		struct cil_alias *alias = (struct cil_alias *)(*datum);
+		if (alias->actual) {
+			*datum = alias->actual;
+		}
+	}
+
+	rc = SEPOL_OK;
+
+exit:
+	return rc;
+}
+
+int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum)
+{
+	int rc = SEPOL_ERR;
 	struct cil_args_resolve *args = extra_args;
 	struct cil_db *db = args->db;
 	struct cil_tree_node *node = NULL;
@@ -4146,20 +4236,6 @@
 		*datum = NULL;
 	}
 
-	if (*datum != NULL) {
-		/* If this datum is an alias, then return the actual node
-		 * This depends on aliases already being processed
-		 */
-		node = NODE(*datum);
-		if (node->flavor == CIL_TYPEALIAS || node->flavor == CIL_SENSALIAS
-			|| node->flavor == CIL_CATALIAS) {
-			struct cil_alias *alias = (struct cil_alias *)(*datum);
-			if (alias->actual) {
-				*datum = alias->actual;
-			}
-		}
-	}
-
 	args->last_resolved_name = name;
 
 	return rc;
diff --git a/libsepol/cil/src/cil_resolve_ast.h b/libsepol/cil/src/cil_resolve_ast.h
index 1175f97..1d971fd 100644
--- a/libsepol/cil/src/cil_resolve_ast.h
+++ b/libsepol/cil/src/cil_resolve_ast.h
@@ -74,6 +74,8 @@
 int cil_resolve_validatetrans(struct cil_tree_node *current, void *extra_args);
 int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args);
 int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args);
+int cil_resolve_ibpkeycon(struct cil_tree_node *current, void *extra_args);
+int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args);
 int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args);
 int cil_resolve_genfscon(struct cil_tree_node *current, void *extra_args);
 int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args);
@@ -97,5 +99,6 @@
 
 int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current);
 int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum);
+int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum);
 
 #endif /* CIL_RESOLVE_AST_H_ */
diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
index 2cc2744..d36401b 100644
--- a/libsepol/cil/src/cil_tree.c
+++ b/libsepol/cil/src/cil_tree.c
@@ -1,6 +1,6 @@
 /*
  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  * 
@@ -1409,6 +1409,20 @@
 			return;
 
 		}
+		case CIL_IBPKEYCON: {
+			struct cil_ibpkeycon *ibpkeycon = node->data;
+
+			cil_log(CIL_INFO, "IBPKEYCON: %s", ibpkeycon->subnet_prefix_str);
+			cil_log(CIL_INFO, " (%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high);
+
+			if (ibpkeycon->context)
+				cil_tree_print_context(ibpkeycon->context);
+			else if (ibpkeycon->context_str)
+				cil_log(CIL_INFO, " %s", ibpkeycon->context_str);
+
+			cil_log(CIL_INFO, "\n");
+			return;
+		}
 		case CIL_PORTCON: {
 			struct cil_portcon *portcon = node->data;
 			cil_log(CIL_INFO, "PORTCON:");
@@ -1492,6 +1506,19 @@
 			cil_log(CIL_INFO, "\n");
 			return;
 		}
+		case CIL_IBENDPORTCON: {
+			struct cil_ibendportcon *ibendportcon = node->data;
+
+			cil_log(CIL_INFO, "IBENDPORTCON: %s %u ", ibendportcon->dev_name_str, ibendportcon->port);
+
+			if (ibendportcon->context)
+				cil_tree_print_context(ibendportcon->context);
+			else if (ibendportcon->context_str)
+				cil_log(CIL_INFO, " %s", ibendportcon->context_str);
+
+			cil_log(CIL_INFO, "\n");
+			return;
+		}
 		case CIL_PIRQCON: {
 			struct cil_pirqcon *pirqcon = node->data;
 
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 47dcfaa..1036d73 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -1012,6 +1012,26 @@
 	return rc;
 }
 
+int __cil_verify_ibendportcon(struct cil_db *db, struct cil_tree_node *node)
+{
+	int rc = SEPOL_ERR;
+	struct cil_ibendportcon *ib_end_port = node->data;
+	struct cil_context *ctx = ib_end_port->context;
+
+	/* Verify only when anonymous */
+	if (!ctx->datum.name) {
+		rc = __cil_verify_context(db, ctx);
+		if (rc != SEPOL_OK)
+			goto exit;
+	}
+
+	return SEPOL_OK;
+
+exit:
+	cil_tree_log(node, CIL_ERR, "Invalid ibendportcon");
+	return rc;
+}
+
 int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node)
 {
 	int rc = SEPOL_ERR;
@@ -1080,6 +1100,26 @@
 	return rc;
 }
 
+int __cil_verify_ibpkeycon(struct cil_db *db, struct cil_tree_node *node)
+{
+	int rc = SEPOL_ERR;
+	struct cil_ibpkeycon *pkey = node->data;
+	struct cil_context *ctx = pkey->context;
+
+	/* Verify only when anonymous */
+	if (!ctx->datum.name) {
+		rc = __cil_verify_context(db, ctx);
+		if (rc != SEPOL_OK)
+			goto exit;
+	}
+
+	return SEPOL_OK;
+
+exit:
+	cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon");
+	return rc;
+}
+
 int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node)
 {
 	int rc = SEPOL_ERR;
@@ -1452,6 +1492,12 @@
 		case CIL_NODECON:
 			rc = __cil_verify_nodecon(db, node);
 			break;
+		case CIL_IBPKEYCON:
+			rc = __cil_verify_ibpkeycon(db, node);
+			break;
+		case CIL_IBENDPORTCON:
+			rc = __cil_verify_ibendportcon(db, node);
+			break;
 		case CIL_PORTCON:
 			rc = __cil_verify_portcon(db, node);
 			break;
diff --git a/libsepol/include/sepol/ibendport_record.h b/libsepol/include/sepol/ibendport_record.h
new file mode 100644
index 0000000..2a37ec6
--- /dev/null
+++ b/libsepol/include/sepol/ibendport_record.h
@@ -0,0 +1,72 @@
+#ifndef _SEPOL_IBENDPORT_RECORD_H_
+#define _SEPOL_IBENDPORT_RECORD_H_
+
+#include <stddef.h>
+#include <sepol/context_record.h>
+#include <sepol/handle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct sepol_ibendport;
+struct sepol_ibendport_key;
+typedef struct sepol_ibendport sepol_ibendport_t;
+typedef struct sepol_ibendport_key sepol_ibendport_key_t;
+
+extern int sepol_ibendport_compare(const sepol_ibendport_t *ibendport,
+				   const sepol_ibendport_key_t *key);
+
+extern int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport,
+				    const sepol_ibendport_t *ibendport2);
+
+extern int sepol_ibendport_key_create(sepol_handle_t *handle,
+				      const char *ibdev_name,
+				      int port,
+				      sepol_ibendport_key_t **key_ptr);
+
+extern void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key,
+				       const char **ibdev_name,
+				       int *port);
+
+extern int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle,
+					    char **ibdev_name);
+
+extern int sepol_ibendport_key_extract(sepol_handle_t *handle,
+				       const sepol_ibendport_t *ibendport,
+				       sepol_ibendport_key_t **key_ptr);
+
+extern void sepol_ibendport_key_free(sepol_ibendport_key_t *key);
+
+extern void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port);
+
+extern int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport);
+
+extern int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle,
+					  const sepol_ibendport_t *ibendport,
+					  char **ibdev_name);
+
+extern int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle,
+					  sepol_ibendport_t *ibendport,
+					  const char *ibdev_name);
+
+extern sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport);
+
+extern int sepol_ibendport_set_con(sepol_handle_t *handle,
+				   sepol_ibendport_t *ibendport,
+				   sepol_context_t *con);
+
+extern int sepol_ibendport_create(sepol_handle_t *handle,
+				  sepol_ibendport_t **ibendport_ptr);
+
+extern int sepol_ibendport_clone(sepol_handle_t *handle,
+				 const sepol_ibendport_t *ibendport,
+				 sepol_ibendport_t **ibendport_ptr);
+
+extern void sepol_ibendport_free(sepol_ibendport_t *ibendport);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libsepol/include/sepol/ibendports.h b/libsepol/include/sepol/ibendports.h
new file mode 100644
index 0000000..4ad77a1
--- /dev/null
+++ b/libsepol/include/sepol/ibendports.h
@@ -0,0 +1,50 @@
+#ifndef _SEPOL_IBENDPORTS_H_
+#define _SEPOL_IBENDPORTS_H_
+
+#include <sepol/handle.h>
+#include <sepol/policydb.h>
+#include <sepol/ibendport_record.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return the number of ibendports */
+extern int sepol_ibendport_count(sepol_handle_t *handle,
+				 const sepol_policydb_t *p,
+				 unsigned int *response);
+
+/* Check if a ibendport exists */
+extern int sepol_ibendport_exists(sepol_handle_t *handle,
+				  const sepol_policydb_t *policydb,
+				  const sepol_ibendport_key_t *key, int *response);
+
+/* Query a ibendport - returns the ibendport, or NULL if not found */
+extern int sepol_ibendport_query(sepol_handle_t *handle,
+				 const sepol_policydb_t *policydb,
+				 const sepol_ibendport_key_t *key,
+				 sepol_ibendport_t **response);
+
+/* Modify a ibendport, or add it, if the key is not found */
+extern int sepol_ibendport_modify(sepol_handle_t *handle,
+				  sepol_policydb_t *policydb,
+				  const sepol_ibendport_key_t *key,
+				  const sepol_ibendport_t *data);
+
+/* Iterate the ibendports
+ * The handler may return:
+ * -1 to signal an error condition,
+ * 1 to signal successful exit
+ * 0 to signal continue
+ */
+extern int sepol_ibendport_iterate(sepol_handle_t *handle,
+				   const sepol_policydb_t *policydb,
+				   int (*fn)(const sepol_ibendport_t *ibendport,
+					     void *fn_arg), void *arg);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libsepol/include/sepol/ibpkey_record.h b/libsepol/include/sepol/ibpkey_record.h
new file mode 100644
index 0000000..1511785
--- /dev/null
+++ b/libsepol/include/sepol/ibpkey_record.h
@@ -0,0 +1,80 @@
+#ifndef _SEPOL_IBPKEY_RECORD_H_
+#define _SEPOL_IBPKEY_RECORD_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sepol/context_record.h>
+#include <sepol/handle.h>
+
+#define INET6_ADDRLEN 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct sepol_ibpkey;
+struct sepol_ibpkey_key;
+typedef struct sepol_ibpkey sepol_ibpkey_t;
+typedef struct sepol_ibpkey_key sepol_ibpkey_key_t;
+
+extern int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey,
+				const sepol_ibpkey_key_t *key);
+
+extern int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey,
+				 const sepol_ibpkey_t *ibpkey2);
+
+extern int sepol_ibpkey_key_create(sepol_handle_t *handle,
+				   const char *subnet_prefix,
+				   int low, int high,
+				   sepol_ibpkey_key_t **key_ptr);
+
+extern void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key,
+				    uint64_t *subnet_prefix,
+				    int *low, int *high);
+
+extern int sepol_ibpkey_key_extract(sepol_handle_t *handle,
+				    const sepol_ibpkey_t *ibpkey,
+				    sepol_ibpkey_key_t **key_ptr);
+
+extern void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key);
+
+extern int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey);
+
+extern int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey);
+
+extern void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num);
+
+extern void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high);
+
+extern int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle,
+					  const sepol_ibpkey_t *ibpkey,
+					  char **subnet_prefix);
+
+extern uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey);
+
+extern int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
+					  sepol_ibpkey_t *ibpkey,
+					  const char *subnet_prefix);
+
+extern void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey,
+						 uint64_t subnet_prefix);
+
+extern sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey);
+
+extern int sepol_ibpkey_set_con(sepol_handle_t *handle,
+				sepol_ibpkey_t *ibpkey, sepol_context_t *con);
+
+extern int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey_ptr);
+
+extern int sepol_ibpkey_clone(sepol_handle_t *handle,
+			      const sepol_ibpkey_t *ibpkey,
+			      sepol_ibpkey_t **ibpkey_ptr);
+
+extern void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libsepol/include/sepol/ibpkeys.h b/libsepol/include/sepol/ibpkeys.h
new file mode 100644
index 0000000..4b69d1e
--- /dev/null
+++ b/libsepol/include/sepol/ibpkeys.h
@@ -0,0 +1,50 @@
+#ifndef _SEPOL_IBPKEYS_H_
+#define _SEPOL_IBPKEYS_H_
+
+#include <sepol/handle.h>
+#include <sepol/policydb.h>
+#include <sepol/ibpkey_record.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return the number of ibpkeys */
+extern int sepol_ibpkey_count(sepol_handle_t *handle,
+			      const sepol_policydb_t *p, unsigned int *response);
+
+/* Check if a ibpkey exists */
+extern int sepol_ibpkey_exists(sepol_handle_t *handle,
+			       const sepol_policydb_t *policydb,
+			       const sepol_ibpkey_key_t *key, int *response);
+
+/* Query a ibpkey - returns the ibpkey, or NULL if not found */
+extern int sepol_ibpkey_query(sepol_handle_t *handle,
+			      const sepol_policydb_t *policydb,
+			      const sepol_ibpkey_key_t *key,
+			      sepol_ibpkey_t **response);
+
+/* Modify a ibpkey, or add it, if the key is not found */
+extern int sepol_ibpkey_modify(sepol_handle_t *handle,
+			       sepol_policydb_t *policydb,
+			       const sepol_ibpkey_key_t *key,
+			       const sepol_ibpkey_t *data);
+
+/* Iterate the ibpkeys
+ * The handler may return:
+ * -1 to signal an error condition,
+ * 1 to signal successful exit
+ * 0 to signal continue
+ */
+extern int sepol_ibpkey_iterate(sepol_handle_t *handle,
+				const sepol_policydb_t *policydb,
+				int (*fn)(const sepol_ibpkey_t *ibpkey,
+					  void *fn_arg), void *arg);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libsepol/include/sepol/policydb/polcaps.h b/libsepol/include/sepol/policydb/polcaps.h
index 087541d..dc9356a 100644
--- a/libsepol/include/sepol/policydb/polcaps.h
+++ b/libsepol/include/sepol/policydb/polcaps.h
@@ -12,6 +12,7 @@
 	POLICYDB_CAPABILITY_EXTSOCKCLASS,
 	POLICYDB_CAPABILITY_ALWAYSNETWORK,
 	POLICYDB_CAPABILITY_CGROUPSECLABEL,
+	POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION,
 	__POLICYDB_CAPABILITY_MAX
 };
 #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 37e0c9e..1b2d782 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -24,6 +24,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
  * Copyright (C) 2003 - 2004 Red Hat, Inc.
+ * Copyright (C) 2017 Mellanox Techonolgies Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -72,6 +73,8 @@
 extern "C" {
 #endif
 
+#define IB_DEVICE_NAME_MAX 64
+
 /*
  * A datum type is defined for each kind of symbol 
  * in the configuration data:  individual permissions, 
@@ -358,6 +361,15 @@
 			uint32_t low_ioport;
 			uint32_t high_ioport;
 		} ioport;
+		struct {
+			uint64_t subnet_prefix;
+			uint16_t low_pkey;
+			uint16_t high_pkey;
+		} ibpkey;
+		struct {
+			char *dev_name;
+			uint8_t port;
+		} ibendport;
 	} u;
 	union {
 		uint32_t sclass;	/* security class for genfs */
@@ -386,14 +398,15 @@
 #define SYM_NUM     8
 
 /* object context array indices */
-#define OCON_ISID  0		/* initial SIDs */
-#define OCON_FS    1		/* unlabeled file systems */
-#define OCON_PORT  2		/* TCP and UDP port numbers */
-#define OCON_NETIF 3		/* network interfaces */
-#define OCON_NODE  4		/* nodes */
-#define OCON_FSUSE 5		/* fs_use */
-#define OCON_NODE6 6		/* IPv6 nodes */
-#define OCON_GENFS 7            /* needed for ocontext_supported */
+#define OCON_ISID  0	/* initial SIDs */
+#define OCON_FS    1	/* unlabeled file systems */
+#define OCON_PORT  2	/* TCP and UDP port numbers */
+#define OCON_NETIF 3	/* network interfaces */
+#define OCON_NODE  4	/* nodes */
+#define OCON_FSUSE 5	/* fs_use */
+#define OCON_NODE6 6	/* IPv6 nodes */
+#define OCON_IBPKEY 7	/* Infiniband PKEY */
+#define OCON_IBENDPORT 8	/* Infiniband End Port */
 
 /* object context array indices for Xen */
 #define OCON_XEN_ISID  	    0    /* initial SIDs */
@@ -404,7 +417,7 @@
 #define OCON_XEN_DEVICETREE 5    /* device tree node */
 
 /* OCON_NUM needs to be the largest index in any platform's ocontext array */
-#define OCON_NUM   7
+#define OCON_NUM   9
 
 /* section: module information */
 
@@ -726,10 +739,11 @@
 #define POLICYDB_VERSION_CONSTRAINT_NAMES	29
 #define POLICYDB_VERSION_XEN_DEVICETREE		30 /* Xen-specific */
 #define POLICYDB_VERSION_XPERMS_IOCTL	30 /* Linux-specific */
+#define POLICYDB_VERSION_INFINIBAND		31 /* Linux-specific */
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN	POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_XPERMS_IOCTL
+#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_INFINIBAND
 
 /* Module versions and specific changes*/
 #define MOD_POLICYDB_VERSION_BASE		4
@@ -748,9 +762,11 @@
 #define MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS	15
 #define MOD_POLICYDB_VERSION_DEFAULT_TYPE	16
 #define MOD_POLICYDB_VERSION_CONSTRAINT_NAMES  17
+#define MOD_POLICYDB_VERSION_XPERMS_IOCTL  18
+#define MOD_POLICYDB_VERSION_INFINIBAND		19
 
 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_CONSTRAINT_NAMES
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_INFINIBAND
 
 #define POLICYDB_CONFIG_MLS    1
 
diff --git a/libsepol/include/sepol/policydb/services.h b/libsepol/include/sepol/policydb/services.h
index 9162149..efdf7de 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -188,6 +188,22 @@
 			  uint16_t port, sepol_security_id_t * out_sid);
 
 /*
+ * Return the SID of the ibpkey specified by
+ * `subnet prefix', and `pkey'.
+ */
+extern int sepol_ibpkey_sid(uint64_t subnet_prefix_p,
+			    uint16_t pkey,
+			    sepol_security_id_t *out_sid);
+
+/*
+ * Return the SID of the ibendport specified by
+ * `dev_name', and `port'.
+ */
+extern int sepol_ibendport_sid(char *dev_name,
+			       uint8_t port,
+			       sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/include/sepol/sepol.h b/libsepol/include/sepol/sepol.h
index 513f77d..540609a 100644
--- a/libsepol/include/sepol/sepol.h
+++ b/libsepol/include/sepol/sepol.h
@@ -11,12 +11,16 @@
 #include <sepol/user_record.h>
 #include <sepol/context_record.h>
 #include <sepol/iface_record.h>
+#include <sepol/ibpkey_record.h>
+#include <sepol/ibendport_record.h>
 #include <sepol/port_record.h>
 #include <sepol/boolean_record.h>
 #include <sepol/node_record.h>
 
 #include <sepol/booleans.h>
 #include <sepol/interfaces.h>
+#include <sepol/ibpkeys.h>
+#include <sepol/ibendports.h>
 #include <sepol/ports.h>
 #include <sepol/nodes.h>
 #include <sepol/users.h>
diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c
index 27c39e7..b08757b 100644
--- a/libsepol/src/assertion.c
+++ b/libsepol/src/assertion.c
@@ -222,7 +222,7 @@
 	ebitmap_node_t *snode, *tnode;
 	unsigned int i, j;
 
-	if (k->specified != AVTAB_ALLOWED)
+	if ((k->specified & AVTAB_ALLOWED) == 0)
 		return 0;
 
 	if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
@@ -471,7 +471,7 @@
 	avrule_t *avrule = a->avrule;
 	avtab_t *avtab = a->avtab;
 
-	if (k->specified != AVTAB_ALLOWED)
+	if ((k->specified & AVTAB_ALLOWED) == 0)
 		goto exit;
 
 	if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c
index 224e999..5a873af 100644
--- a/libsepol/src/avrule_block.c
+++ b/libsepol/src/avrule_block.c
@@ -156,20 +156,35 @@
 {
 	scope_datum_t *scope =
 	    (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id);
-	uint32_t i;
+	avrule_decl_t *decl;
+	uint32_t len = scope->decl_ids_len;
+
 	if (scope == NULL) {
 		return 0;
 	}
 	if (scope->scope != SCOPE_DECL) {
 		return 0;
 	}
-	for (i = 0; i < scope->decl_ids_len; i++) {
-		avrule_decl_t *decl =
-		    p->decl_val_to_struct[scope->decl_ids[i] - 1];
+
+	if (len < 1) {
+		return 0;
+	}
+
+	if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) {
+		uint32_t i;
+		for (i = 0; i < len; i++) {
+			decl = p->decl_val_to_struct[scope->decl_ids[i] - 1];
+			if (decl != NULL && decl->enabled) {
+				return 1;
+			}
+		}
+	} else {
+		decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1];
 		if (decl != NULL && decl->enabled) {
 			return 1;
 		}
 	}
+
 	return 0;
 }
 
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 54bf781..6f1b235 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2004-2005 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2017 Mellanox Technologies, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -938,7 +939,7 @@
 		return -1;
 
 	if (mls_semantic_level_expand(&sr->level[1], &r->level[1], p, h) < 0) {
-		mls_semantic_level_destroy(&sr->level[0]);
+		mls_level_destroy(&r->level[0]);
 		return -1;
 	}
 
@@ -2217,6 +2218,20 @@
 					return -1;
 				}
 				break;
+			case OCON_IBPKEY:
+				n->u.ibpkey.subnet_prefix = c->u.ibpkey.subnet_prefix;
+
+				n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey;
+				n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey;
+			break;
+			case OCON_IBENDPORT:
+				n->u.ibendport.dev_name = strdup(c->u.ibendport.dev_name);
+				if (!n->u.ibendport.dev_name) {
+					ERR(state->handle, "Out of memory!");
+					return -1;
+				}
+				n->u.ibendport.port = c->u.ibendport.port;
+				break;
 			case OCON_PORT:
 				n->u.port.protocol = c->u.port.protocol;
 				n->u.port.low_port = c->u.port.low_port;
@@ -2337,13 +2352,20 @@
 	value = type->s.value;
 
 	if (type->flavor == TYPE_ATTRIB) {
-		if (ebitmap_cpy(&p->attr_type_map[value - 1], &type->types)) {
-			goto oom;
-		}
-		ebitmap_for_each_bit(&type->types, tnode, i) {
-			if (!ebitmap_node_get_bit(tnode, i))
-				continue;
-			if (ebitmap_set_bit(&p->type_attr_map[i], value - 1, 1)) {
+		if (!(type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE)) {
+			if (ebitmap_cpy(&p->attr_type_map[value - 1], &type->types)) {
+				goto oom;
+			}
+			ebitmap_for_each_bit(&type->types, tnode, i) {
+				if (!ebitmap_node_get_bit(tnode, i))
+					continue;
+				if (ebitmap_set_bit(&p->type_attr_map[i], value - 1, 1)) {
+					goto oom;
+				}
+			}
+		} else {
+			/* Attribute is being expanded, so remove */
+			if (ebitmap_set_bit(&p->type_attr_map[value - 1], value - 1, 0)) {
 				goto oom;
 			}
 		}
@@ -2513,46 +2535,41 @@
 	unsigned int i;
 	ebitmap_t types, neg_types;
 	ebitmap_node_t *tnode;
+	unsigned char expand = alwaysexpand || ebitmap_length(&set->negset) || set->flags;
+	type_datum_t *type;
 	int rc =-1;
 
 	ebitmap_init(&types);
 	ebitmap_init(t);
 
-	if (alwaysexpand || ebitmap_length(&set->negset) || set->flags) {
-		/* First go through the types and OR all the attributes to types */
-		ebitmap_for_each_bit(&set->types, tnode, i) {
-			if (ebitmap_node_get_bit(tnode, i)) {
+	/* First go through the types and OR all the attributes to types */
+	ebitmap_for_each_bit(&set->types, tnode, i) {
+		if (!ebitmap_node_get_bit(tnode, i))
+			continue;
 
-				/*
-				 * invalid policies might have more types set in the ebitmap than
-				 * what's available in the type_val_to_struct mapping
-				 */
-				if (i >= p->p_types.nprim)
-					goto err_types;
+		/*
+		 * invalid policies might have more types set in the ebitmap than
+		 * what's available in the type_val_to_struct mapping
+		 */
+		if (i >= p->p_types.nprim)
+			goto err_types;
 
-				if (!p->type_val_to_struct[i]) {
-					goto err_types;
-				}
+		type = p->type_val_to_struct[i];
 
-				if (p->type_val_to_struct[i]->flavor ==
-				    TYPE_ATTRIB) {
-					if (ebitmap_union
-					    (&types,
-					     &p->type_val_to_struct[i]->
-					     types)) {
-						goto err_types;
-					}
-				} else {
-					if (ebitmap_set_bit(&types, i, 1)) {
-						goto err_types;
-					}
-				}
+		if (!type) {
+			goto err_types;
+		}
+
+		if (type->flavor == TYPE_ATTRIB &&
+		    (expand || (type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE))) {
+			if (ebitmap_union(&types, &type->types)) {
+				goto err_types;
+			}
+		} else {
+			if (ebitmap_set_bit(&types, i, 1)) {
+				goto err_types;
 			}
 		}
-	} else {
-		/* No expansion of attributes, just copy the set as is. */
-		if (ebitmap_cpy(&types, &set->types))
-			goto err_types;
 	}
 
 	/* Now do the same thing for negset */
diff --git a/libsepol/src/ibendport_internal.h b/libsepol/src/ibendport_internal.h
new file mode 100644
index 0000000..ed8f9b4
--- /dev/null
+++ b/libsepol/src/ibendport_internal.h
@@ -0,0 +1,18 @@
+#ifndef _SEPOL_IBENDPORT_INTERNAL_H_
+#define _SEPOL_IBENDPORT_INTERNAL_H_
+
+#include <sepol/ibendport_record.h>
+#include <sepol/ibendports.h>
+#include "dso.h"
+
+hidden_proto(sepol_ibendport_create)
+hidden_proto(sepol_ibendport_free)
+hidden_proto(sepol_ibendport_get_con)
+hidden_proto(sepol_ibendport_get_port)
+hidden_proto(sepol_ibendport_key_create)
+hidden_proto(sepol_ibendport_key_unpack)
+hidden_proto(sepol_ibendport_set_con)
+hidden_proto(sepol_ibendport_set_port)
+hidden_proto(sepol_ibendport_get_ibdev_name)
+hidden_proto(sepol_ibendport_set_ibdev_name)
+#endif
diff --git a/libsepol/src/ibendport_record.c b/libsepol/src/ibendport_record.c
new file mode 100644
index 0000000..912aeb5
--- /dev/null
+++ b/libsepol/src/ibendport_record.c
@@ -0,0 +1,298 @@
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include "sepol/policydb/policydb.h"
+#include "ibendport_internal.h"
+#include "context_internal.h"
+#include "debug.h"
+
+struct sepol_ibendport {
+	/* Device Name */
+	char *ibdev_name;
+
+	/* Port number */
+	int port;
+
+	/* Context */
+	sepol_context_t *con;
+};
+
+struct sepol_ibendport_key {
+	/* Device Name */
+	char *ibdev_name;
+
+	/* Port number */
+	int port;
+};
+
+/* Allocates a sufficiently large string (ibdev_name) */
+int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle,
+				     char **ibdev_name)
+{
+	char *tmp_ibdev_name = NULL;
+
+	tmp_ibdev_name = calloc(1, IB_DEVICE_NAME_MAX);
+
+	if (!tmp_ibdev_name)
+		goto omem;
+
+	*ibdev_name = tmp_ibdev_name;
+	return STATUS_SUCCESS;
+
+omem:
+	ERR(handle, "out of memory");
+	ERR(handle, "could not allocate string buffer for ibdev_name");
+	return STATUS_ERR;
+}
+
+/* Key */
+int sepol_ibendport_key_create(sepol_handle_t *handle,
+			       const char *ibdev_name,
+			       int port,
+			       sepol_ibendport_key_t **key_ptr)
+{
+	sepol_ibendport_key_t *tmp_key =
+	    (sepol_ibendport_key_t *)malloc(sizeof(sepol_ibendport_key_t));
+
+	if (!tmp_key) {
+		ERR(handle, "out of memory, could not create ibendport key");
+		goto omem;
+	}
+
+	if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_key->ibdev_name) < 0)
+		goto err;
+
+	strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX);
+	tmp_key->port = port;
+
+	*key_ptr = tmp_key;
+	return STATUS_SUCCESS;
+
+omem:
+	ERR(handle, "out of memory");
+
+err:
+	sepol_ibendport_key_free(tmp_key);
+	ERR(handle, "could not create ibendport key for IB device %s, port %u",
+	    ibdev_name, port);
+	return STATUS_ERR;
+}
+
+hidden_def(sepol_ibendport_key_create)
+
+void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key,
+				const char **ibdev_name, int *port)
+{
+	*ibdev_name = key->ibdev_name;
+	*port = key->port;
+}
+
+hidden_def(sepol_ibendport_key_unpack)
+
+int sepol_ibendport_key_extract(sepol_handle_t *handle,
+				const sepol_ibendport_t *ibendport,
+				sepol_ibendport_key_t **key_ptr)
+{
+	if (sepol_ibendport_key_create
+	    (handle, ibendport->ibdev_name, ibendport->port, key_ptr) < 0) {
+		ERR(handle, "could not extract key from ibendport device %s port %d",
+		    ibendport->ibdev_name,
+		    ibendport->port);
+
+		return STATUS_ERR;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+void sepol_ibendport_key_free(sepol_ibendport_key_t *key)
+{
+	if (!key)
+		return;
+	free(key->ibdev_name);
+	free(key);
+}
+
+int sepol_ibendport_compare(const sepol_ibendport_t *ibendport, const sepol_ibendport_key_t *key)
+{
+	int rc;
+
+	rc = strcmp(ibendport->ibdev_name, key->ibdev_name);
+
+	if ((ibendport->port == key->port) && !rc)
+		return 0;
+
+	if (ibendport->port < key->port)
+		return -1;
+	else if (key->port < ibendport->port)
+		return 1;
+	else
+		return rc;
+}
+
+int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport, const sepol_ibendport_t *ibendport2)
+{
+	int rc;
+
+	rc = strcmp(ibendport->ibdev_name, ibendport2->ibdev_name);
+
+	if ((ibendport->port == ibendport2->port) && !rc)
+		return 0;
+
+	if (ibendport->port < ibendport2->port)
+		return -1;
+	else if (ibendport2->port < ibendport->port)
+		return 1;
+	else
+		return rc;
+}
+
+int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport)
+{
+	return ibendport->port;
+}
+
+hidden_def(sepol_ibendport_get_port)
+
+void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port)
+{
+	ibendport->port = port;
+}
+
+hidden_def(sepol_ibendport_set_port)
+
+int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle,
+				   const sepol_ibendport_t *ibendport,
+				   char **ibdev_name)
+{
+	char *tmp_ibdev_name = NULL;
+
+	if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0)
+		goto err;
+
+	strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
+	*ibdev_name = tmp_ibdev_name;
+	return STATUS_SUCCESS;
+
+err:
+	free(tmp_ibdev_name);
+	ERR(handle, "could not get ibendport ibdev_name");
+	return STATUS_ERR;
+}
+
+hidden_def(sepol_ibendport_get_ibdev_name)
+
+int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle,
+				   sepol_ibendport_t *ibendport,
+				   const char *ibdev_name)
+{
+	char *tmp = NULL;
+
+	if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0)
+		goto err;
+
+	strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX);
+	free(ibendport->ibdev_name);
+	ibendport->ibdev_name = tmp;
+	return STATUS_SUCCESS;
+
+err:
+	free(tmp);
+	ERR(handle, "could not set ibendport subnet prefix to %s", ibdev_name);
+	return STATUS_ERR;
+}
+
+hidden_def(sepol_ibendport_set_ibdev_name)
+
+/* Create */
+int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport)
+{
+	sepol_ibendport_t *tmp_ibendport = (sepol_ibendport_t *)malloc(sizeof(sepol_ibendport_t));
+
+	if (!tmp_ibendport) {
+		ERR(handle, "out of memory, could not create ibendport record");
+		return STATUS_ERR;
+	}
+
+	tmp_ibendport->ibdev_name = NULL;
+	tmp_ibendport->port = 0;
+	tmp_ibendport->con = NULL;
+	*ibendport = tmp_ibendport;
+
+	return STATUS_SUCCESS;
+}
+
+hidden_def(sepol_ibendport_create)
+
+/* Deep copy clone */
+int sepol_ibendport_clone(sepol_handle_t *handle,
+			  const sepol_ibendport_t *ibendport,
+			  sepol_ibendport_t **ibendport_ptr)
+{
+	sepol_ibendport_t *new_ibendport = NULL;
+
+	if (sepol_ibendport_create(handle, &new_ibendport) < 0)
+		goto err;
+
+	if (sepol_ibendport_alloc_ibdev_name(handle, &new_ibendport->ibdev_name) < 0)
+		goto omem;
+
+	strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
+	new_ibendport->port = ibendport->port;
+
+	if (ibendport->con &&
+	    (sepol_context_clone(handle, ibendport->con, &new_ibendport->con) < 0))
+		goto err;
+
+	*ibendport_ptr = new_ibendport;
+	return STATUS_SUCCESS;
+
+omem:
+	ERR(handle, "out of memory");
+
+err:
+	ERR(handle, "could not clone ibendport record");
+	sepol_ibendport_free(new_ibendport);
+	return STATUS_ERR;
+}
+
+/* Destroy */
+void sepol_ibendport_free(sepol_ibendport_t *ibendport)
+{
+	if (!ibendport)
+		return;
+
+	free(ibendport->ibdev_name);
+	sepol_context_free(ibendport->con);
+	free(ibendport);
+}
+
+hidden_def(sepol_ibendport_free)
+
+/* Context */
+sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport)
+{
+	return ibendport->con;
+}
+
+hidden_def(sepol_ibendport_get_con)
+
+int sepol_ibendport_set_con(sepol_handle_t *handle,
+			    sepol_ibendport_t *ibendport, sepol_context_t *con)
+{
+	sepol_context_t *newcon;
+
+	if (sepol_context_clone(handle, con, &newcon) < 0) {
+		ERR(handle, "out of memory, could not set ibendport context");
+		return STATUS_ERR;
+	}
+
+	sepol_context_free(ibendport->con);
+	ibendport->con = newcon;
+	return STATUS_SUCCESS;
+}
+
+hidden_def(sepol_ibendport_set_con)
diff --git a/libsepol/src/ibendports.c b/libsepol/src/ibendports.c
new file mode 100644
index 0000000..6d56c9a
--- /dev/null
+++ b/libsepol/src/ibendports.c
@@ -0,0 +1,254 @@
+#include <netinet/in.h>
+#include <stdlib.h>
+
+#include "debug.h"
+#include "context.h"
+#include "handle.h"
+
+#include <sepol/policydb/policydb.h>
+#include "ibendport_internal.h"
+
+/* Create a low level ibendport structure from
+ * a high level representation
+ */
+static int ibendport_from_record(sepol_handle_t *handle,
+				 const policydb_t *policydb,
+				 ocontext_t **ibendport,
+				 const sepol_ibendport_t *data)
+{
+	ocontext_t *tmp_ibendport = NULL;
+	context_struct_t *tmp_con = NULL;
+	char *ibdev_name = NULL;
+	int port = sepol_ibendport_get_port(data);
+
+	tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t));
+	if (!tmp_ibendport)
+		goto omem;
+
+	if (sepol_ibendport_alloc_ibdev_name(handle,
+					     &tmp_ibendport->u.ibendport.dev_name) < 0)
+		goto omem;
+
+	if (sepol_ibendport_get_ibdev_name(handle,
+					   data,
+					   &ibdev_name) < 0)
+		goto err;
+
+	strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX);
+
+	free(ibdev_name);
+	ibdev_name = NULL;
+
+	tmp_ibendport->u.ibendport.port = port;
+
+	/* Context */
+	if (context_from_record(handle, policydb, &tmp_con,
+				sepol_ibendport_get_con(data)) < 0)
+		goto err;
+	context_cpy(&tmp_ibendport->context[0], tmp_con);
+	context_destroy(tmp_con);
+	free(tmp_con);
+	tmp_con = NULL;
+
+	*ibendport = tmp_ibendport;
+	return STATUS_SUCCESS;
+
+omem:
+	ERR(handle, "out of memory");
+
+err:
+	if (tmp_ibendport) {
+		context_destroy(&tmp_ibendport->context[0]);
+		free(tmp_ibendport);
+	}
+	context_destroy(tmp_con);
+	free(tmp_con);
+	free(ibdev_name);
+	ERR(handle, "could not create ibendport structure");
+	return STATUS_ERR;
+}
+
+static int ibendport_to_record(sepol_handle_t *handle,
+			       const policydb_t *policydb,
+			       ocontext_t *ibendport,
+			       sepol_ibendport_t **record)
+{
+	int port = ibendport->u.ibendport.port;
+	context_struct_t *con = &ibendport->context[0];
+
+	sepol_context_t *tmp_con = NULL;
+	sepol_ibendport_t *tmp_record = NULL;
+
+	if (sepol_ibendport_create(handle, &tmp_record) < 0)
+		goto err;
+
+	if (sepol_ibendport_set_ibdev_name(handle, tmp_record,
+					   ibendport->u.ibendport.dev_name) < 0)
+		goto err;
+
+	sepol_ibendport_set_port(tmp_record, port);
+
+	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
+		goto err;
+
+	if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0)
+		goto err;
+
+	sepol_context_free(tmp_con);
+	*record = tmp_record;
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not convert ibendport to record");
+	sepol_context_free(tmp_con);
+	sepol_ibendport_free(tmp_record);
+	return STATUS_ERR;
+}
+
+/* Return the number of ibendports */
+extern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)),
+				 const sepol_policydb_t *p, unsigned int *response)
+{
+	unsigned int count = 0;
+	ocontext_t *c, *head;
+	const policydb_t *policydb = &p->p;
+
+	head = policydb->ocontexts[OCON_IBENDPORT];
+	for (c = head; c; c = c->next)
+		count++;
+
+	*response = count;
+
+	return STATUS_SUCCESS;
+}
+
+/* Check if a ibendport exists */
+int sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)),
+			   const sepol_policydb_t *p,
+			   const sepol_ibendport_key_t *key, int *response)
+{
+	const policydb_t *policydb = &p->p;
+	ocontext_t *c, *head;
+	int port;
+	const char *ibdev_name;
+
+	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
+
+	head = policydb->ocontexts[OCON_IBENDPORT];
+	for (c = head; c; c = c->next) {
+		const char *ibdev_name2 = c->u.ibendport.dev_name;
+		int port2 = c->u.ibendport.port;
+
+		if (port2 == port &&
+		    (!strcmp(ibdev_name, ibdev_name2))) {
+			*response = 1;
+			return STATUS_SUCCESS;
+		}
+	}
+
+	*response = 0;
+	return STATUS_SUCCESS;
+}
+
+int sepol_ibendport_query(sepol_handle_t *handle,
+			  const sepol_policydb_t *p,
+			  const sepol_ibendport_key_t *key,
+			  sepol_ibendport_t **response)
+{
+	const policydb_t *policydb = &p->p;
+	ocontext_t *c, *head;
+	int port;
+	const char *ibdev_name;
+
+	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
+
+	head = policydb->ocontexts[OCON_IBENDPORT];
+	for (c = head; c; c = c->next) {
+		const char *ibdev_name2 = c->u.ibendport.dev_name;
+		int port2 = c->u.ibendport.port;
+
+		if (port2 == port &&
+		    (!strcmp(ibdev_name, ibdev_name2))) {
+			if (ibendport_to_record(handle, policydb, c, response) < 0)
+				goto err;
+			return STATUS_SUCCESS;
+		}
+	}
+
+	*response = NULL;
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not query ibendport, IB device: %s port %u",
+	    ibdev_name, port);
+	return STATUS_ERR;
+}
+
+/* Load a ibendport into policy */
+int sepol_ibendport_modify(sepol_handle_t *handle,
+			   sepol_policydb_t *p,
+			   const sepol_ibendport_key_t *key,
+			   const sepol_ibendport_t *data)
+{
+	policydb_t *policydb = &p->p;
+	ocontext_t *ibendport = NULL;
+	int port;
+	const char *ibdev_name;
+
+	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
+
+	if (ibendport_from_record(handle, policydb, &ibendport, data) < 0)
+		goto err;
+
+	/* Attach to context list */
+	ibendport->next = policydb->ocontexts[OCON_IBENDPORT];
+	policydb->ocontexts[OCON_IBENDPORT] = ibendport;
+
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not load ibendport %s/%d",
+	    ibdev_name, port);
+	if (ibendport) {
+		context_destroy(&ibendport->context[0]);
+		free(ibendport);
+	}
+	return STATUS_ERR;
+}
+
+int sepol_ibendport_iterate(sepol_handle_t *handle,
+			    const sepol_policydb_t *p,
+			    int (*fn)(const sepol_ibendport_t *ibendport,
+				      void *fn_arg), void *arg)
+{
+	const policydb_t *policydb = &p->p;
+	ocontext_t *c, *head;
+	sepol_ibendport_t *ibendport = NULL;
+
+	head = policydb->ocontexts[OCON_IBENDPORT];
+	for (c = head; c; c = c->next) {
+		int status;
+
+		if (ibendport_to_record(handle, policydb, c, &ibendport) < 0)
+			goto err;
+
+		/* Invoke handler */
+		status = fn(ibendport, arg);
+		if (status < 0)
+			goto err;
+
+		sepol_ibendport_free(ibendport);
+		ibendport = NULL;
+
+		/* Handler requested exit */
+		if (status > 0)
+			break;
+	}
+
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not iterate over ibendports");
+	sepol_ibendport_free(ibendport);
+	return STATUS_ERR;
+}
diff --git a/libsepol/src/ibpkey_internal.h b/libsepol/src/ibpkey_internal.h
new file mode 100644
index 0000000..addf80a
--- /dev/null
+++ b/libsepol/src/ibpkey_internal.h
@@ -0,0 +1,21 @@
+#ifndef _SEPOL_IBPKEY_INTERNAL_H_
+#define _SEPOL_IBPKEY_INTERNAL_H_
+
+#include <sepol/ibpkey_record.h>
+#include <sepol/ibpkeys.h>
+#include "dso.h"
+
+hidden_proto(sepol_ibpkey_create)
+hidden_proto(sepol_ibpkey_free)
+hidden_proto(sepol_ibpkey_get_con)
+hidden_proto(sepol_ibpkey_get_high)
+hidden_proto(sepol_ibpkey_get_low)
+hidden_proto(sepol_ibpkey_key_create)
+hidden_proto(sepol_ibpkey_key_unpack)
+hidden_proto(sepol_ibpkey_set_con)
+hidden_proto(sepol_ibpkey_set_range)
+hidden_proto(sepol_ibpkey_get_subnet_prefix)
+hidden_proto(sepol_ibpkey_get_subnet_prefix_bytes)
+hidden_proto(sepol_ibpkey_set_subnet_prefix)
+hidden_proto(sepol_ibpkey_set_subnet_prefix_bytes)
+#endif
diff --git a/libsepol/src/ibpkey_record.c b/libsepol/src/ibpkey_record.c
new file mode 100644
index 0000000..badf2b3
--- /dev/null
+++ b/libsepol/src/ibpkey_record.c
@@ -0,0 +1,379 @@
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <sepol/ibpkey_record.h>
+
+#include "ibpkey_internal.h"
+#include "context_internal.h"
+#include "debug.h"
+
+struct sepol_ibpkey {
+	/* Subnet prefix */
+	uint64_t subnet_prefix;
+
+	/* Low - High range. Same for single ibpkeys. */
+	int low, high;
+
+	/* Context */
+	sepol_context_t *con;
+};
+
+struct sepol_ibpkey_key {
+	/* Subnet prefix */
+	uint64_t subnet_prefix;
+
+	/* Low - High range. Same for single ibpkeys. */
+	int low, high;
+};
+
+/* Converts a string represtation (subnet_prefix_str)
+ * to a numeric representation (subnet_prefix_bytes)
+ */
+static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle,
+				      const char *subnet_prefix_str,
+				      uint64_t *subnet_prefix)
+{
+	struct in6_addr in_addr;
+
+	if (inet_pton(AF_INET6, subnet_prefix_str, &in_addr) <= 0) {
+		ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %s",
+		    subnet_prefix_str, strerror(errno));
+		return STATUS_ERR;
+	}
+
+	memcpy(subnet_prefix, in_addr.s6_addr, sizeof(*subnet_prefix));
+
+	return STATUS_SUCCESS;
+}
+
+/* Converts a numeric representation (subnet_prefix_bytes)
+ * to a string representation (subnet_prefix_str)
+ */
+
+static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle,
+				       uint64_t subnet_prefix,
+				       char *subnet_prefix_str)
+{
+	struct in6_addr addr;
+
+	memset(&addr, 0, sizeof(struct in6_addr));
+	memcpy(&addr.s6_addr[0], &subnet_prefix, sizeof(subnet_prefix));
+
+	if (inet_ntop(AF_INET6, &addr, subnet_prefix_str,
+		      INET6_ADDRSTRLEN) == NULL) {
+		ERR(handle,
+		    "could not expand IPv6 address to string: %s",
+		    strerror(errno));
+		return STATUS_ERR;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+/* Allocates a sufficiently large string (subnet_prefix)
+ * for an IPV6 address for the subnet prefix
+ */
+static int ibpkey_alloc_subnet_prefix_string(sepol_handle_t *handle,
+					     char **subnet_prefix)
+{
+	char *tmp_subnet_prefix = NULL;
+
+	tmp_subnet_prefix = malloc(INET6_ADDRSTRLEN);
+
+	if (!tmp_subnet_prefix)
+		goto omem;
+
+	*subnet_prefix = tmp_subnet_prefix;
+	return STATUS_SUCCESS;
+
+omem:
+	ERR(handle, "out of memory");
+
+	ERR(handle, "could not allocate string buffer for subnet_prefix");
+	return STATUS_ERR;
+}
+
+/* Key */
+int sepol_ibpkey_key_create(sepol_handle_t *handle,
+			    const char *subnet_prefix,
+			    int low, int high,
+			    sepol_ibpkey_key_t **key_ptr)
+{
+	sepol_ibpkey_key_t *tmp_key =
+	    (sepol_ibpkey_key_t *)malloc(sizeof(sepol_ibpkey_key_t));
+
+	if (!tmp_key) {
+		ERR(handle, "out of memory, could not create ibpkey key");
+		goto omem;
+	}
+
+	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, &tmp_key->subnet_prefix) < 0)
+		goto err;
+
+	tmp_key->low = low;
+	tmp_key->high = high;
+
+	*key_ptr = tmp_key;
+	return STATUS_SUCCESS;
+
+omem:
+	ERR(handle, "out of memory");
+
+err:
+	sepol_ibpkey_key_free(tmp_key);
+	ERR(handle, "could not create ibpkey key for subnet prefix%s, range %u, %u",
+	    subnet_prefix, low, high);
+	return STATUS_ERR;
+}
+
+hidden_def(sepol_ibpkey_key_create)
+
+void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key,
+			     uint64_t *subnet_prefix, int *low, int *high)
+{
+	*subnet_prefix = key->subnet_prefix;
+	*low = key->low;
+	*high = key->high;
+}
+
+hidden_def(sepol_ibpkey_key_unpack)
+
+int sepol_ibpkey_key_extract(sepol_handle_t *handle,
+			     const sepol_ibpkey_t *ibpkey,
+			     sepol_ibpkey_key_t **key_ptr)
+{
+	char subnet_prefix_str[INET6_ADDRSTRLEN];
+
+	ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, subnet_prefix_str);
+
+	if (sepol_ibpkey_key_create
+	    (handle, subnet_prefix_str, ibpkey->low, ibpkey->high, key_ptr) < 0) {
+		ERR(handle, "could not extract key from ibpkey %s %d:%d",
+		    subnet_prefix_str,
+		    ibpkey->low, ibpkey->high);
+
+		return STATUS_ERR;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key)
+{
+	if (!key)
+		return;
+	free(key);
+}
+
+int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key)
+{
+	if (ibpkey->subnet_prefix < key->subnet_prefix)
+		return -1;
+	if (key->subnet_prefix < ibpkey->subnet_prefix)
+		return 1;
+
+	if (ibpkey->low < key->low)
+		return -1;
+	if (key->low < ibpkey->low)
+		return 1;
+
+	if (ibpkey->high < key->high)
+		return -1;
+	if (key->high < ibpkey->high)
+		return 1;
+
+	return 0;
+}
+
+int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2)
+{
+	if (ibpkey->subnet_prefix < ibpkey2->subnet_prefix)
+		return -1;
+	if (ibpkey2->subnet_prefix < ibpkey->subnet_prefix)
+		return 1;
+
+	if (ibpkey->low < ibpkey2->low)
+		return -1;
+	if (ibpkey2->low < ibpkey->low)
+		return 1;
+
+	if (ibpkey->high < ibpkey2->high)
+		return -1;
+	if (ibpkey2->high < ibpkey->high)
+		return 1;
+
+	return 0;
+}
+
+/* Pkey */
+int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey)
+{
+	return ibpkey->low;
+}
+
+hidden_def(sepol_ibpkey_get_low)
+
+int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey)
+{
+	return ibpkey->high;
+}
+
+hidden_def(sepol_ibpkey_get_high)
+
+void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num)
+{
+	ibpkey->low = pkey_num;
+	ibpkey->high = pkey_num;
+}
+
+void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high)
+{
+	ibpkey->low = low;
+	ibpkey->high = high;
+}
+
+hidden_def(sepol_ibpkey_set_range)
+
+int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle,
+				   const sepol_ibpkey_t *ibpkey,
+				   char **subnet_prefix)
+{
+	char *tmp_subnet_prefix = NULL;
+
+	if (ibpkey_alloc_subnet_prefix_string(handle, &tmp_subnet_prefix) < 0)
+		goto err;
+
+	if (ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, tmp_subnet_prefix) < 0)
+		goto err;
+
+	*subnet_prefix = tmp_subnet_prefix;
+	return STATUS_SUCCESS;
+
+err:
+	free(tmp_subnet_prefix);
+	ERR(handle, "could not get ibpkey subnet_prefix");
+	return STATUS_ERR;
+}
+
+hidden_def(sepol_ibpkey_get_subnet_prefix)
+
+/* Subnet prefix */
+uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey)
+{
+	return ibpkey->subnet_prefix;
+}
+
+hidden_def(sepol_ibpkey_get_subnet_prefix_bytes)
+
+int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
+				   sepol_ibpkey_t *ibpkey,
+				   const char *subnet_prefix_str)
+{
+	uint64_t tmp = 0;
+
+	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix_str, &tmp) < 0)
+		goto err;
+
+	ibpkey->subnet_prefix = tmp;
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not set ibpkey subnet prefix to %s", subnet_prefix_str);
+	return STATUS_ERR;
+}
+
+hidden_def(sepol_ibpkey_set_subnet_prefix)
+
+void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey,
+					  uint64_t subnet_prefix)
+{
+	ibpkey->subnet_prefix = subnet_prefix;
+}
+
+hidden_def(sepol_ibpkey_set_subnet_prefix_bytes)
+
+/* Create */
+int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey)
+{
+	sepol_ibpkey_t *tmp_ibpkey = (sepol_ibpkey_t *)malloc(sizeof(sepol_ibpkey_t));
+
+	if (!tmp_ibpkey) {
+		ERR(handle, "out of memory, could not create ibpkey record");
+		return STATUS_ERR;
+	}
+
+	tmp_ibpkey->subnet_prefix = 0;
+	tmp_ibpkey->low = 0;
+	tmp_ibpkey->high = 0;
+	tmp_ibpkey->con = NULL;
+	*ibpkey = tmp_ibpkey;
+
+	return STATUS_SUCCESS;
+}
+
+hidden_def(sepol_ibpkey_create)
+
+/* Deep copy clone */
+int sepol_ibpkey_clone(sepol_handle_t *handle,
+		       const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t **ibpkey_ptr)
+{
+	sepol_ibpkey_t *new_ibpkey = NULL;
+
+	if (sepol_ibpkey_create(handle, &new_ibpkey) < 0)
+		goto err;
+
+	new_ibpkey->subnet_prefix = ibpkey->subnet_prefix;
+	new_ibpkey->low = ibpkey->low;
+	new_ibpkey->high = ibpkey->high;
+
+	if (ibpkey->con &&
+	    (sepol_context_clone(handle, ibpkey->con, &new_ibpkey->con) < 0))
+		goto err;
+
+	*ibpkey_ptr = new_ibpkey;
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not clone ibpkey record");
+	sepol_ibpkey_free(new_ibpkey);
+	return STATUS_ERR;
+}
+
+/* Destroy */
+void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey)
+{
+	if (!ibpkey)
+		return;
+
+	sepol_context_free(ibpkey->con);
+	free(ibpkey);
+}
+
+hidden_def(sepol_ibpkey_free)
+
+/* Context */
+sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey)
+{
+	return ibpkey->con;
+}
+
+hidden_def(sepol_ibpkey_get_con)
+
+int sepol_ibpkey_set_con(sepol_handle_t *handle,
+			 sepol_ibpkey_t *ibpkey, sepol_context_t *con)
+{
+	sepol_context_t *newcon;
+
+	if (sepol_context_clone(handle, con, &newcon) < 0) {
+		ERR(handle, "out of memory, could not set ibpkey context");
+		return STATUS_ERR;
+	}
+
+	sepol_context_free(ibpkey->con);
+	ibpkey->con = newcon;
+	return STATUS_SUCCESS;
+}
+
+hidden_def(sepol_ibpkey_set_con)
diff --git a/libsepol/src/ibpkeys.c b/libsepol/src/ibpkeys.c
new file mode 100644
index 0000000..682bf5d
--- /dev/null
+++ b/libsepol/src/ibpkeys.c
@@ -0,0 +1,250 @@
+#include <netinet/in.h>
+#include <stdlib.h>
+
+#include "debug.h"
+#include "context.h"
+#include "handle.h"
+
+#include <sepol/ibpkey_record.h>
+#include <sepol/policydb/policydb.h>
+#include "ibpkey_internal.h"
+
+/* Create a low level ibpkey structure from
+ * a high level representation
+ */
+static int ibpkey_from_record(sepol_handle_t *handle,
+			      const policydb_t *policydb,
+			      ocontext_t **ibpkey, const sepol_ibpkey_t *data)
+{
+	ocontext_t *tmp_ibpkey = NULL;
+	context_struct_t *tmp_con = NULL;
+	char *subnet_prefix_buf = NULL;
+	int low = sepol_ibpkey_get_low(data);
+	int high = sepol_ibpkey_get_high(data);
+
+	tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey));
+	if (!tmp_ibpkey)
+		goto omem;
+
+	tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data);
+
+	/* Pkey range */
+	tmp_ibpkey->u.ibpkey.low_pkey = low;
+	tmp_ibpkey->u.ibpkey.high_pkey = high;
+	if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) {
+		ERR(handle, "low ibpkey %d exceeds high ibpkey %d",
+		    tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey);
+		goto err;
+	}
+
+	/* Context */
+	if (context_from_record(handle, policydb, &tmp_con,
+				sepol_ibpkey_get_con(data)) < 0)
+		goto err;
+	context_cpy(&tmp_ibpkey->context[0], tmp_con);
+	context_destroy(tmp_con);
+	free(tmp_con);
+	tmp_con = NULL;
+
+	*ibpkey = tmp_ibpkey;
+	return STATUS_SUCCESS;
+
+omem:
+	ERR(handle, "out of memory");
+
+err:
+	if (tmp_ibpkey) {
+		context_destroy(&tmp_ibpkey->context[0]);
+		free(tmp_ibpkey);
+	}
+	context_destroy(tmp_con);
+	free(tmp_con);
+	free(subnet_prefix_buf);
+	ERR(handle, "could not create ibpkey structure");
+	return STATUS_ERR;
+}
+
+static int ibpkey_to_record(sepol_handle_t *handle,
+			    const policydb_t *policydb,
+			    ocontext_t *ibpkey, sepol_ibpkey_t **record)
+{
+	context_struct_t *con = &ibpkey->context[0];
+	sepol_context_t *tmp_con = NULL;
+	sepol_ibpkey_t *tmp_record = NULL;
+
+	if (sepol_ibpkey_create(handle, &tmp_record) < 0)
+		goto err;
+
+	sepol_ibpkey_set_subnet_prefix_bytes(tmp_record,
+					     ibpkey->u.ibpkey.subnet_prefix);
+
+	sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey,
+			       ibpkey->u.ibpkey.high_pkey);
+
+	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
+		goto err;
+
+	if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0)
+		goto err;
+
+	sepol_context_free(tmp_con);
+	*record = tmp_record;
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not convert ibpkey to record");
+	sepol_context_free(tmp_con);
+	sepol_ibpkey_free(tmp_record);
+	return STATUS_ERR;
+}
+
+/* Return the number of ibpkeys */
+extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)),
+			      const sepol_policydb_t *p, unsigned int *response)
+{
+	unsigned int count = 0;
+	ocontext_t *c, *head;
+	const policydb_t *policydb = &p->p;
+
+	head = policydb->ocontexts[OCON_IBPKEY];
+	for (c = head; c; c = c->next)
+		count++;
+
+	*response = count;
+
+	return STATUS_SUCCESS;
+}
+
+/* Check if a ibpkey exists */
+int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)),
+			const sepol_policydb_t *p,
+			const sepol_ibpkey_key_t *key, int *response)
+{
+	const policydb_t *policydb = &p->p;
+	ocontext_t *c, *head;
+	int low, high;
+	uint64_t subnet_prefix;
+
+	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
+
+	head = policydb->ocontexts[OCON_IBPKEY];
+	for (c = head; c; c = c->next) {
+		uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
+		uint16_t low2 = c->u.ibpkey.low_pkey;
+		uint16_t high2 = c->u.ibpkey.high_pkey;
+
+		if (low2 == low &&
+		    high2 == high &&
+		    subnet_prefix == subnet_prefix2) {
+			*response = 1;
+			return STATUS_SUCCESS;
+		}
+	}
+
+	*response = 0;
+	return STATUS_SUCCESS;
+}
+
+/* Query a ibpkey */
+int sepol_ibpkey_query(sepol_handle_t *handle,
+		       const sepol_policydb_t *p,
+		       const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response)
+{
+	const policydb_t *policydb = &p->p;
+	ocontext_t *c, *head;
+	int low, high;
+	uint64_t subnet_prefix;
+
+	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
+
+	head = policydb->ocontexts[OCON_IBPKEY];
+	for (c = head; c; c = c->next) {
+		uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
+		int low2 = c->u.ibpkey.low_pkey;
+		int high2 = c->u.ibpkey.high_pkey;
+
+		if (low2 == low &&
+		    high2 == high &&
+		    subnet_prefix == subnet_prefix2) {
+			if (ibpkey_to_record(handle, policydb, c, response) < 0)
+				goto err;
+			return STATUS_SUCCESS;
+		}
+	}
+
+	*response = NULL;
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not query ibpkey subnet prefix: %#lx range %u - %u exists",
+	    subnet_prefix, low, high);
+	return STATUS_ERR;
+}
+
+/* Load a ibpkey into policy */
+int sepol_ibpkey_modify(sepol_handle_t *handle,
+			sepol_policydb_t *p,
+			const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data)
+{
+	policydb_t *policydb = &p->p;
+	ocontext_t *ibpkey = NULL;
+	int low, high;
+	uint64_t subnet_prefix;
+
+	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
+
+	if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0)
+		goto err;
+
+	/* Attach to context list */
+	ibpkey->next = policydb->ocontexts[OCON_IBPKEY];
+	policydb->ocontexts[OCON_IBPKEY] = ibpkey;
+
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not load ibpkey subnet prefix: %#lx range %u - %u exists",
+	    subnet_prefix, low, high);
+	if (ibpkey) {
+		context_destroy(&ibpkey->context[0]);
+		free(ibpkey);
+	}
+	return STATUS_ERR;
+}
+
+int sepol_ibpkey_iterate(sepol_handle_t *handle,
+			 const sepol_policydb_t *p,
+			 int (*fn)(const sepol_ibpkey_t *ibpkey,
+				   void *fn_arg), void *arg)
+{
+	const policydb_t *policydb = &p->p;
+	ocontext_t *c, *head;
+	sepol_ibpkey_t *ibpkey = NULL;
+
+	head = policydb->ocontexts[OCON_IBPKEY];
+	for (c = head; c; c = c->next) {
+		int status;
+
+		if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0)
+			goto err;
+
+		/* Invoke handler */
+		status = fn(ibpkey, arg);
+		if (status < 0)
+			goto err;
+
+		sepol_ibpkey_free(ibpkey);
+		ibpkey = NULL;
+
+		/* Handler requested exit */
+		if (status > 0)
+			break;
+	}
+
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not iterate over ibpkeys");
+	sepol_ibpkey_free(ibpkey);
+	return STATUS_ERR;
+}
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index 3a1c0be..f1905a9 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -2043,7 +2043,7 @@
 		num++;
 	}
 
-	cond_data = calloc(sizeof(struct cond_data), num);
+	cond_data = calloc(num, sizeof(struct cond_data));
 	if (!cond_data) {
 		rc = -1;
 		goto exit;
@@ -2784,6 +2784,100 @@
 	return rc;
 }
 
+static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)
+{
+	struct ocontext *ibpkeycon;
+	char subnet_prefix_str[INET6_ADDRSTRLEN];
+	struct in6_addr subnet_prefix = {0};
+	uint16_t low;
+	uint16_t high;
+	char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
+	char *ctx;
+	int rc = 0;
+
+	for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL;
+	     ibpkeycon = ibpkeycon->next) {
+		memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix,
+		       sizeof(ibpkeycon->u.ibpkey.subnet_prefix));
+
+		if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
+			      subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
+			sepol_log_err("ibpkeycon subnet_prefix is invalid: %s",
+				      strerror(errno));
+			rc = -1;
+			goto exit;
+		}
+
+		low = ibpkeycon->u.ibpkey.low_pkey;
+		high = ibpkeycon->u.ibpkey.high_pkey;
+		if (low == high) {
+			rc = snprintf(low_high_str, 44, "%u", low);
+		} else {
+			rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
+		}
+		if (rc < 0 || rc >= 44) {
+			rc = -1;
+			goto exit;
+		}
+
+		ctx = context_to_str(pdb, &ibpkeycon->context[0]);
+		if (!ctx) {
+			rc = -1;
+			goto exit;
+		}
+
+		sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx);
+
+		free(ctx);
+	}
+
+	rc = 0;
+
+exit:
+	if (rc != 0) {
+		sepol_log_err("Error writing ibpkeycon rules to CIL\n");
+	}
+
+	return rc;
+}
+
+static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)
+{
+	struct ocontext *ibendportcon;
+	char port_str[4];
+	char *ctx;
+	int rc = 0;
+
+	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
+	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
+		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
+		if (rc < 0 || rc >= 4) {
+			rc = -1;
+			goto exit;
+		}
+
+		ctx = context_to_str(pdb, &ibendportcon->context[0]);
+		if (!ctx) {
+			rc = -1;
+			goto exit;
+		}
+
+		sepol_printf(out, "(ibendportcon %s %s %s)\n",
+			     ibendportcon->u.ibendport.dev_name, port_str, ctx);
+
+		free(ctx);
+	}
+
+	rc = 0;
+
+exit:
+	if (rc != 0) {
+		sepol_log_err("Error writing ibendportcon rules to CIL\n");
+	}
+
+	return rc;
+}
+
 static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
 {
 	return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str);
@@ -3180,6 +3274,16 @@
 		if (rc != 0) {
 			goto exit;
 		}
+
+		rc = write_selinux_ibpkey_rules_to_cil(out, pdb);
+		if (rc != 0) {
+			goto exit;
+		}
+
+		rc = write_selinux_ibendport_rules_to_cil(out, pdb);
+		if (rc != 0) {
+			goto exit;
+		}
 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
 		rc = write_xen_isid_rules_to_cil(out, pdb);
 		if (rc != 0) {
diff --git a/libsepol/src/kernel_to_common.c b/libsepol/src/kernel_to_common.c
index 45adc5d..01ffc8f 100644
--- a/libsepol/src/kernel_to_common.c
+++ b/libsepol/src/kernel_to_common.c
@@ -518,6 +518,33 @@
 	return memcmp(&(*aa)->u.node6.addr, &(*bb)->u.node6.addr, sizeof((*aa)->u.node6.addr));
 }
 
+static int ibpkey_data_cmp(const void *a, const void *b)
+{
+	int rc;
+	struct ocontext *const *aa = a;
+	struct ocontext *const *bb = b;
+
+	rc = (*aa)->u.ibpkey.subnet_prefix - (*bb)->u.ibpkey.subnet_prefix;
+	if (rc)
+		return rc;
+
+	return compare_ranges((*aa)->u.ibpkey.low_pkey, (*aa)->u.ibpkey.high_pkey,
+			      (*bb)->u.ibpkey.low_pkey, (*bb)->u.ibpkey.high_pkey);
+}
+
+static int ibendport_data_cmp(const void *a, const void *b)
+{
+	int rc;
+	struct ocontext *const *aa = a;
+	struct ocontext *const *bb = b;
+
+	rc = strcmp((*aa)->u.ibendport.dev_name, (*bb)->u.ibendport.dev_name);
+	if (rc)
+		return rc;
+
+	return (*aa)->u.ibendport.port - (*bb)->u.ibendport.port;
+}
+
 static int pirq_data_cmp(const void *a, const void *b)
 {
 	struct ocontext *const *aa = a;
@@ -641,6 +668,16 @@
 		if (rc != 0) {
 			goto exit;
 		}
+
+		rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBPKEY], ibpkey_data_cmp);
+		if (rc != 0) {
+			goto exit;
+		}
+
+		rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBENDPORT], ibendport_data_cmp);
+		if (rc != 0) {
+			goto exit;
+		}
 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
 		rc = sort_ocontext_data(&pdb->ocontexts[1], pirq_data_cmp);
 		if (rc != 0) {
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index 22a0909..a74873f 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -2645,6 +2645,100 @@
 	return rc;
 }
 
+static int write_selinux_ibpkey_rules_to_conf(FILE *out, struct policydb *pdb)
+{
+	struct ocontext *ibpkeycon;
+	char subnet_prefix_str[INET6_ADDRSTRLEN];
+	struct in6_addr subnet_prefix = {0};
+	uint16_t low;
+	uint16_t high;
+	char low_high_str[44]; /* 2^64 <= 20 digits so "low-high" <= 44 chars */
+	char *ctx;
+	int rc = 0;
+
+	for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL;
+	     ibpkeycon = ibpkeycon->next) {
+		memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix,
+		       sizeof(ibpkeycon->u.ibpkey.subnet_prefix));
+
+		if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
+			      subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
+			sepol_log_err("ibpkeycon address is invalid: %s",
+				      strerror(errno));
+			rc = -1;
+			goto exit;
+		}
+
+		low = ibpkeycon->u.ibpkey.low_pkey;
+		high = ibpkeycon->u.ibpkey.high_pkey;
+		if (low == high) {
+			rc = snprintf(low_high_str, 44, "%u", low);
+		} else {
+			rc = snprintf(low_high_str, 44, "%u-%u", low, high);
+		}
+		if (rc < 0 || rc >= 44) {
+			rc = -1;
+			goto exit;
+		}
+
+		ctx = context_to_str(pdb, &ibpkeycon->context[0]);
+		if (!ctx) {
+			rc = -1;
+			goto exit;
+		}
+
+		sepol_printf(out, "ibpkeycon %s %s %s\n", subnet_prefix_str,
+			     low_high_str, ctx);
+
+		free(ctx);
+	}
+
+	rc = 0;
+
+exit:
+	if (rc != 0) {
+		sepol_log_err("Error writing ibpkeycon rules to policy.conf\n");
+	}
+
+	return rc;
+}
+
+static int write_selinux_ibendport_rules_to_conf(FILE *out, struct policydb *pdb)
+{
+	struct ocontext *ibendportcon;
+	char port_str[4];
+	char *ctx;
+	int rc = 0;
+
+	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
+	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
+		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
+		if (rc < 0 || rc >= 4) {
+			rc = -1;
+			goto exit;
+		}
+
+		ctx = context_to_str(pdb, &ibendportcon->context[0]);
+		if (!ctx) {
+			rc = -1;
+			goto exit;
+		}
+
+		sepol_printf(out, "ibendportcon %s %s %s\n", ibendportcon->u.ibendport.dev_name, port_str, ctx);
+
+		free(ctx);
+	}
+
+	rc = 0;
+
+exit:
+	if (rc != 0) {
+		sepol_log_err("Error writing ibendportcon rules to policy.conf\n");
+	}
+
+	return rc;
+}
+
 static int write_xen_isid_rules_to_conf(FILE *out, struct policydb *pdb)
 {
 	return write_sid_context_rules_to_conf(out, pdb, xen_sid_to_str);
@@ -3045,6 +3139,16 @@
 		if (rc != 0) {
 			goto exit;
 		}
+
+		rc = write_selinux_ibpkey_rules_to_conf(out, pdb);
+		if (rc != 0) {
+			goto exit;
+		}
+
+		rc = write_selinux_ibendport_rules_to_conf(out, pdb);
+		if (rc != 0) {
+			goto exit;
+		}
 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
 		rc = write_xen_isid_rules_to_conf(out, pdb);
 		if (rc != 0) {
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index 4042640..dd1fec2 100644
--- a/libsepol/src/libsepol.map.in
+++ b/libsepol/src/libsepol.map.in
@@ -6,6 +6,8 @@
 	sepol_context_*; sepol_mls_*; sepol_check_context;
 	sepol_iface_*; 
 	sepol_port_*;
+	sepol_ibpkey_*;
+	sepol_ibendport_*;
 	sepol_node_*;
 	sepol_user_*; sepol_genusers; sepol_set_delusers;
 	sepol_msg_*; sepol_debug;
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index f211164..3f1d610 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -467,8 +467,8 @@
 			    state->cur_mod_name, id);
 			return -1;
 		}
-		/* permissive should pass to the base type */
-		base_type->flags |= (type->flags & TYPE_FLAGS_PERMISSIVE);
+
+		base_type->flags |= type->flags;
 	} else {
 		if (state->verbose)
 			INFO(state->handle, "copying type %s", id);
@@ -890,7 +890,7 @@
 		return -1;
 	}
 
-	target_type->flags |= (type->flags & TYPE_FLAGS_PERMISSIVE);
+	target_type->flags |= type->flags;
 
 	base_type = hashtab_search(state->base->p_types.table, id);
 	if (base_type == NULL) {
@@ -938,7 +938,7 @@
 
 		base_type->flavor = TYPE_ALIAS;
 		base_type->primary = target_type->s.value;
-		base_type->flags |= (target_type->flags & TYPE_FLAGS_PERMISSIVE);
+		base_type->flags |= target_type->flags;
 
 	}
 	/* the aliases map points from its value to its primary so when this module 
@@ -1325,6 +1325,15 @@
 			tail_perm = new_perm;
 			cur_perm = cur_perm->next;
 		}
+
+		if (cur->xperms) {
+			new_rule->xperms = calloc(1, sizeof(*new_rule->xperms));
+			if (!new_rule->xperms)
+				goto cleanup;
+			memcpy(new_rule->xperms, cur->xperms,
+			       sizeof(*new_rule->xperms));
+		}
+
 		new_rule->line = cur->line;
 		new_rule->source_line = cur->source_line;
 		if (cur->source_filename) {
@@ -2569,6 +2578,12 @@
 			goto cleanup;
 		}
 
+		if (mods[i]->policyvers > b->policyvers) {
+			WARN(state.handle,
+			     "Upgrading policy version from %u to %u\n", b->policyvers, mods[i]->policyvers);
+			b->policyvers = mods[i]->policyvers;
+		}
+
 		if ((modules[i] =
 		     (policy_module_t *) calloc(1,
 						sizeof(policy_module_t))) ==
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index 7d8eb20..619a48f 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -3,6 +3,7 @@
  * Functions to convert policy module to CIL
  *
  * Copyright (C) 2015 Tresys Technology, LLC
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -211,7 +212,12 @@
 
 static void role_list_destroy(void)
 {
-	struct list_node *curr = role_list->head;
+	struct list_node *curr;
+
+	if (role_list == NULL) {
+		return;
+	}
+	curr = role_list->head;
 
 	while (curr != NULL) {
 		free(curr->data);
@@ -317,7 +323,7 @@
 	struct type_datum *type = data;
 	struct policydb *pdb = arg;
 	struct scope_datum *scope;
-	uint32_t i;
+	uint32_t len;
 	uint32_t scope_id;
 
 	if (type->primary != 1) {
@@ -326,8 +332,9 @@
 			return -1;
 		}
 
-		for (i = 0; i < scope->decl_ids_len; i++) {
-			scope_id = scope->decl_ids[i];
+		len = scope->decl_ids_len;
+		if (len > 0) {
+			scope_id = scope->decl_ids[len-1];
 			if (typealias_lists[scope_id] == NULL) {
 				rc = list_init(&typealias_lists[scope_id]);
 				if (rc != 0) {
@@ -982,8 +989,14 @@
 
 	num = 0;
 	ebitmap_for_each_bit(map, node, i) {
-		if (ebitmap_get_bit(map, i))
+		if (ebitmap_get_bit(map, i)) {
+			if (num >= UINT32_MAX / sizeof(*name_arr)) {
+				log_err("Overflow");
+				rc = -1;
+				goto exit;
+			}
 			num++;
+		}
 	}
 
 	name_arr = malloc(sizeof(*name_arr) * num);
@@ -1111,19 +1124,30 @@
 {
 	// create a space separated string of the names
 	int rc = -1;
-	int len = 0;
+	size_t len = 0;
 	int i;
 	char *str;
 	char *strpos;
-	int name_len;
-	int rlen;
 
 	for (i = 0; i < num_names; i++) {
 		len += strlen(names[i]);
+		if (len < strlen(names[i])) {
+			log_err("Overflow");
+			return -1;
+		}
 	}
 
 	// add spaces + null terminator
-	len += (num_names - 1) + 1;
+	len += num_names;
+	if (len < (size_t)num_names) {
+		log_err("Overflow");
+		return -1;
+	}
+
+	if (!len) {
+		log_err("Empty list");
+		return -1;
+	}
 
 	str = malloc(len);
 	if (str == NULL) {
@@ -1131,22 +1155,15 @@
 		rc = -1;
 		goto exit;
 	}
+	str[0] = 0;
 
 	strpos = str;
 
 	for (i = 0; i < num_names; i++) {
-		name_len = strlen(names[i]);
-		rlen = snprintf(strpos, len - (strpos - str), "%s", names[i]);
-		if (rlen < 0 || rlen >= len) {
-			log_err("Failed to generate name list");
-			rc = -1;
-			goto exit;
-		}
-
+		strpos = stpcpy(strpos, names[i]);
 		if (i < num_names - 1) {
-			strpos[name_len] = ' ';
+			*strpos++ = ' ';
 		}
-		strpos += name_len + 1;
 	}
 
 	*string = str;
@@ -1662,6 +1679,9 @@
 
 	arr.count = 0;
 	arr.perms = calloc(common->permissions.nprim, sizeof(*arr.perms));
+	if (arr.perms == NULL) {
+		goto exit;
+	}
 	rc = hashtab_map(common->permissions.table, class_perm_to_array, &arr);
 	if (rc != 0) {
 		goto exit;
@@ -1952,6 +1972,9 @@
 
 	arr.count = 0;
 	arr.perms = calloc(class->permissions.nprim, sizeof(*arr.perms));
+	if (arr.perms == NULL) {
+		goto exit;
+	}
 	rc = hashtab_map(class->permissions.table, class_perm_to_array, &arr);
 	if (rc != 0) {
 		goto exit;
@@ -2262,6 +2285,8 @@
 			cil_printf("))\n");
 		}
 		break;
+	case TYPE_ALIAS:
+		break;
 	default:
 		log_err("Unknown flavor (%i) of type %s", type->flavor, key);
 		rc = -1;
@@ -2656,6 +2681,45 @@
 	return rc;
 }
 
+static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb,
+					struct ocontext *ibpkeycons)
+{
+	int rc = -1;
+	struct ocontext *ibpkeycon;
+	char subnet_prefix_str[INET6_ADDRSTRLEN];
+	struct in6_addr subnet_prefix = {0};
+	uint16_t high;
+	uint16_t low;
+
+	for (ibpkeycon = ibpkeycons; ibpkeycon; ibpkeycon = ibpkeycon->next) {
+		low = ibpkeycon->u.ibpkey.low_pkey;
+		high = ibpkeycon->u.ibpkey.high_pkey;
+		memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix,
+		       sizeof(ibpkeycon->u.ibpkey.subnet_prefix));
+
+		if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
+			      subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
+			log_err("ibpkeycon subnet_prefix is invalid: %s",
+				strerror(errno));
+			rc = -1;
+			goto exit;
+		}
+
+		if (low == high)
+			cil_printf("(ibpkeycon %s %i ", subnet_prefix_str, low);
+		else
+			cil_printf("(ibpkeycon %s (%i %i) ", subnet_prefix_str, low,
+				   high);
+
+		context_to_cil(pdb, &ibpkeycon->context[0]);
+
+		cil_printf(")\n");
+	}
+	return 0;
+exit:
+	return rc;
+}
+
 static int ocontext_selinux_netif_to_cil(struct policydb *pdb, struct ocontext *netifs)
 {
 	struct ocontext *netif;
@@ -2736,6 +2800,19 @@
 	return rc;
 }
 
+static int ocontext_selinux_ibendport_to_cil(struct policydb *pdb, struct ocontext *ibendports)
+{
+	struct ocontext *ibendport;
+
+	for (ibendport = ibendports; ibendport; ibendport = ibendport->next) {
+		cil_printf("(ibendportcon %s %u ", ibendport->u.ibendport.dev_name, ibendport->u.ibendport.port);
+		context_to_cil(pdb, &ibendport->context[0]);
+
+		cil_printf(")\n");
+	}
+
+	return 0;
+}
 
 static int ocontext_selinux_fsuse_to_cil(struct policydb *pdb, struct ocontext *fsuses)
 {
@@ -2889,6 +2966,8 @@
 		ocontext_selinux_node_to_cil,
 		ocontext_selinux_fsuse_to_cil,
 		ocontext_selinux_node6_to_cil,
+		ocontext_selinux_ibpkey_to_cil,
+		ocontext_selinux_ibendport_to_cil,
 	};
 	static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = {
 		ocontext_xen_isid_to_cil,
@@ -3321,6 +3400,7 @@
 {
 	struct type_datum *alias_datum;
 	char *alias_name;
+	char *type_name;
 	struct list_node *curr;
 	struct avrule_decl *decl = stack_peek(decl_stack);
 	struct list *alias_list = typealias_lists[decl->decl_id];
@@ -3337,9 +3417,13 @@
 			rc = -1;
 			goto exit;
 		}
-
+		if (alias_datum->flavor == TYPE_ALIAS) {
+			type_name = pdb->p_type_val_to_name[alias_datum->primary - 1];
+		} else {
+			type_name = pdb->p_type_val_to_name[alias_datum->s.value - 1];
+		}
 		cil_println(indent, "(typealias %s)", alias_name);
-		cil_println(indent, "(typealiasactual %s %s)", alias_name, pdb->p_type_val_to_name[alias_datum->s.value - 1]);
+		cil_println(indent, "(typealiasactual %s %s)", alias_name, type_name);
 	}
 
 	return 0;
diff --git a/libsepol/src/polcaps.c b/libsepol/src/polcaps.c
index 06a868c..b9dc352 100644
--- a/libsepol/src/polcaps.c
+++ b/libsepol/src/polcaps.c
@@ -11,6 +11,7 @@
 	"extended_socket_class",	/* POLICYDB_CAPABILITY_EXTSOCKCLASS */
 	"always_check_network",		/* POLICYDB_CAPABILITY_ALWAYSNETWORK */
 	"cgroup_seclabel",		/* POLICYDB_CAPABILITY_SECLABEL */
+	"nnp_nosuid_transition",	/* POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION */
 	NULL
 };
 
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 7093b29..691101e 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -18,6 +18,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2005 Tresys Technology, LLC
  * Copyright (C) 2003 - 2007 Red Hat, Inc.
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -186,6 +187,13 @@
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
+	 .type = POLICY_KERN,
+	 .version = POLICYDB_VERSION_INFINIBAND,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_IBENDPORT + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
 	 .type = POLICY_BASE,
 	 .version = MOD_POLICYDB_VERSION_BASE,
 	 .sym_num = SYM_NUM,
@@ -284,6 +292,20 @@
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
+	 .type = POLICY_BASE,
+	 .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_NODE6 + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
+	 .type = POLICY_BASE,
+	 .version = MOD_POLICYDB_VERSION_INFINIBAND,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_IBENDPORT + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
 	 .type = POLICY_MOD,
 	 .version = MOD_POLICYDB_VERSION_BASE,
 	 .sym_num = SYM_NUM,
@@ -381,6 +403,20 @@
 	 .ocon_num = 0,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
+	{
+	 .type = POLICY_MOD,
+	 .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = 0,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
+	 .type = POLICY_MOD,
+	 .version = MOD_POLICYDB_VERSION_INFINIBAND,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = 0,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
 };
 
 #if 0
@@ -557,6 +593,8 @@
 		next = cur->next;
 		free(cur);
 	}
+
+	free(x->xperms);
 }
 
 void role_trans_rule_init(role_trans_rule_t * x)
@@ -1682,6 +1720,19 @@
 		return -ENOMEM;
 	}
 
+	if (scope_datum->scope == SCOPE_DECL && scope == SCOPE_REQ) {
+		/* Need to keep the decl at the end of the list */
+		uint32_t len, tmp;
+		len = scope_datum->decl_ids_len;
+		if (len < 2) {
+			/* This should be impossible here */
+			return -1;
+		}
+		tmp = scope_datum->decl_ids[len-2];
+		scope_datum->decl_ids[len-2] = scope_datum->decl_ids[len-1];
+		scope_datum->decl_ids[len-1] = tmp;
+	}
+
 	return retval;
 }
 
@@ -2766,7 +2817,7 @@
 				if (rc < 0)
 					return -1;
 				len = le32_to_cpu(buf[0]);
-				if (zero_or_saturated(len))
+				if (zero_or_saturated(len) || len > 63)
 					return -1;
 				c->u.name = malloc(len + 1);
 				if (!c->u.name)
@@ -2782,6 +2833,41 @@
 				    (&c->context[1], p, fp))
 					return -1;
 				break;
+			case OCON_IBPKEY:
+				rc = next_entry(buf, fp, sizeof(uint32_t) * 4);
+				if (rc < 0 || buf[2] > 0xffff || buf[3] > 0xffff)
+					return -1;
+
+				memcpy(&c->u.ibpkey.subnet_prefix, buf,
+				       sizeof(c->u.ibpkey.subnet_prefix));
+
+				c->u.ibpkey.low_pkey = le32_to_cpu(buf[2]);
+				c->u.ibpkey.high_pkey = le32_to_cpu(buf[3]);
+
+				if (context_read_and_validate
+				    (&c->context[0], p, fp))
+					return -1;
+				break;
+			case OCON_IBENDPORT:
+				rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
+				if (rc < 0)
+					return -1;
+				len = le32_to_cpu(buf[0]);
+				if (len == 0 || len > IB_DEVICE_NAME_MAX - 1)
+					return -1;
+
+				c->u.ibendport.dev_name = malloc(len + 1);
+				if (!c->u.ibendport.dev_name)
+					return -1;
+				rc = next_entry(c->u.ibendport.dev_name, fp, len);
+				if (rc < 0)
+					return -1;
+				c->u.ibendport.dev_name[len] = 0;
+				c->u.ibendport.port = le32_to_cpu(buf[1]);
+				if (context_read_and_validate
+				    (&c->context[0], p, fp))
+					return -1;
+				break;
 			case OCON_PORT:
 				rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
 				if (rc < 0)
@@ -3196,8 +3282,7 @@
 
 /************** module reading functions below **************/
 
-static avrule_t *avrule_read(policydb_t * p
-			     __attribute__ ((unused)), struct policy_file *fp)
+static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp)
 {
 	unsigned int i;
 	uint32_t buf[2], len;
@@ -3215,8 +3300,8 @@
 	if (rc < 0)
 		goto bad;
 
-	(avrule)->specified = le32_to_cpu(buf[0]);
-	(avrule)->flags = le32_to_cpu(buf[1]);
+	avrule->specified = le32_to_cpu(buf[0]);
+	avrule->flags = le32_to_cpu(buf[1]);
 
 	if (type_set_read(&avrule->stypes, fp))
 		goto bad;
@@ -3252,6 +3337,52 @@
 		tail = cur;
 	}
 
+	if (avrule->specified & AVRULE_XPERMS) {
+		uint8_t buf8;
+		size_t nel = ARRAY_SIZE(avrule->xperms->perms);
+		uint32_t buf32[nel];
+
+		if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
+			ERR(fp->handle,
+			    "module policy version %u does not support ioctl"
+			    " extended permissions rules and one was specified",
+			    p->policyvers);
+			goto bad;
+		}
+
+		if (p->target_platform != SEPOL_TARGET_SELINUX) {
+			ERR(fp->handle,
+			    "Target platform %s does not support ioctl"
+			    " extended permissions rules and one was specified",
+			    policydb_target_strings[p->target_platform]);
+			goto bad;
+		}
+
+		avrule->xperms = calloc(1, sizeof(*avrule->xperms));
+		if (!avrule->xperms)
+			goto bad;
+
+		rc = next_entry(&buf8, fp, sizeof(uint8_t));
+		if (rc < 0) {
+			ERR(fp->handle, "truncated entry");
+			goto bad;
+		}
+		avrule->xperms->specified = buf8;
+		rc = next_entry(&buf8, fp, sizeof(uint8_t));
+		if (rc < 0) {
+			ERR(fp->handle, "truncated entry");
+			goto bad;
+		}
+		avrule->xperms->driver = buf8;
+		rc = next_entry(buf32, fp, sizeof(uint32_t)*nel);
+		if (rc < 0) {
+			ERR(fp->handle, "truncated entry");
+			goto bad;
+		}
+		for (i = 0; i < nel; i++)
+			avrule->xperms->perms[i] = le32_to_cpu(buf32[i]);
+	}
+
 	return avrule;
       bad:
 	if (avrule) {
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 03fb120..10338a6 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -21,6 +21,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
  * Copyright (C) 2003 - 2004 Red Hat, Inc.
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -1911,6 +1912,79 @@
 }
 
 /*
+ * Return the SID of the ibpkey specified by
+ * `subnet prefix', and `pkey number'.
+ */
+int hidden sepol_ibpkey_sid(uint64_t subnet_prefix,
+			    uint16_t pkey, sepol_security_id_t *out_sid)
+{
+	ocontext_t *c;
+	int rc = 0;
+
+	c = policydb->ocontexts[OCON_IBPKEY];
+	while (c) {
+		if (c->u.ibpkey.low_pkey <= pkey &&
+		    c->u.ibpkey.high_pkey >= pkey &&
+		    subnet_prefix == c->u.ibpkey.subnet_prefix)
+			break;
+		c = c->next;
+	}
+
+	if (c) {
+		if (!c->sid[0]) {
+			rc = sepol_sidtab_context_to_sid(sidtab,
+							 &c->context[0],
+							 &c->sid[0]);
+			if (rc)
+				goto out;
+		}
+		*out_sid = c->sid[0];
+	} else {
+		*out_sid = SECINITSID_UNLABELED;
+	}
+
+out:
+	return rc;
+}
+
+/*
+ * Return the SID of the subnet management interface specified by
+ * `device name', and `port'.
+ */
+int hidden sepol_ibendport_sid(char *dev_name,
+			       uint8_t port,
+			       sepol_security_id_t *out_sid)
+{
+	ocontext_t *c;
+	int rc = 0;
+
+	c = policydb->ocontexts[OCON_IBENDPORT];
+	while (c) {
+		if (c->u.ibendport.port == port &&
+		    !strcmp(dev_name, c->u.ibendport.dev_name))
+			break;
+		c = c->next;
+	}
+
+	if (c) {
+		if (!c->sid[0]) {
+			rc = sepol_sidtab_context_to_sid(sidtab,
+							 &c->context[0],
+							 &c->sid[0]);
+			if (rc)
+				goto out;
+		}
+		*out_sid = c->sid[0];
+	} else {
+		*out_sid = SECINITSID_UNLABELED;
+	}
+
+out:
+	return rc;
+}
+
+
+/*
  * Return the SID of the port specified by
  * `domain', `type', `protocol', and `port'.
  */
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index e75b9ab..e486e28 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -16,6 +16,7 @@
  *
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003-2005 Tresys Technology, LLC
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -50,7 +51,8 @@
 	struct policydb *p;
 };
 
-static int avrule_write_list(avrule_t * avrules, struct policy_file *fp);
+static int avrule_write_list(policydb_t *p,
+			     avrule_t * avrules, struct policy_file *fp);
 
 static int ebitmap_write(ebitmap_t * e, struct policy_file *fp)
 {
@@ -779,9 +781,9 @@
 		if (cond_write_av_list(p, node->false_list, fp) != 0)
 			return POLICYDB_ERROR;
 	} else {
-		if (avrule_write_list(node->avtrue_list, fp))
+		if (avrule_write_list(p, node->avtrue_list, fp))
 			return POLICYDB_ERROR;
-		if (avrule_write_list(node->avfalse_list, fp))
+		if (avrule_write_list(p, node->avfalse_list, fp))
 			return POLICYDB_ERROR;
 	}
 
@@ -1410,6 +1412,35 @@
 				if (context_write(p, &c->context[1], fp))
 					return POLICYDB_ERROR;
 				break;
+			case OCON_IBPKEY:
+				 /* The subnet prefix is in network order */
+				memcpy(buf, &c->u.ibpkey.subnet_prefix,
+				       sizeof(c->u.ibpkey.subnet_prefix));
+
+				buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey);
+				buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey);
+
+				items = put_entry(buf, sizeof(uint32_t), 4, fp);
+				if (items != 4)
+					return POLICYDB_ERROR;
+
+				if (context_write(p, &c->context[0], fp))
+					return POLICYDB_ERROR;
+				break;
+			case OCON_IBENDPORT:
+				len = strlen(c->u.ibendport.dev_name);
+				buf[0] = cpu_to_le32(len);
+				buf[1] = cpu_to_le32(c->u.ibendport.port);
+				items = put_entry(buf, sizeof(uint32_t), 2, fp);
+				if (items != 2)
+					return POLICYDB_ERROR;
+				items = put_entry(c->u.ibendport.dev_name, 1, len, fp);
+				if (items != len)
+					return POLICYDB_ERROR;
+
+				if (context_write(p, &c->context[0], fp))
+					return POLICYDB_ERROR;
+				break;
 			case OCON_PORT:
 				buf[0] = c->u.port.protocol;
 				buf[1] = c->u.port.low_port;
@@ -1613,18 +1644,13 @@
 
 /************** module writing functions below **************/
 
-static int avrule_write(avrule_t * avrule, struct policy_file *fp)
+static int avrule_write(policydb_t *p, avrule_t * avrule,
+			struct policy_file *fp)
 {
 	size_t items, items2;
 	uint32_t buf[32], len;
 	class_perm_node_t *cur;
 
-	if (avrule->specified & AVRULE_XPERMS) {
-		ERR(fp->handle, "module policy does not support extended"
-				" permissions rules and one was specified");
-		return POLICYDB_ERROR;
-	}
-
 	items = 0;
 	buf[items++] = cpu_to_le32(avrule->specified);
 	buf[items++] = cpu_to_le32(avrule->flags);
@@ -1661,10 +1687,48 @@
 		cur = cur->next;
 	}
 
+	if (avrule->specified & AVRULE_XPERMS) {
+		size_t nel = ARRAY_SIZE(avrule->xperms->perms);
+		uint32_t buf32[nel];
+		uint8_t buf8;
+		unsigned int i;
+
+		if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
+			ERR(fp->handle,
+			    "module policy version %u does not support ioctl"
+			    " extended permissions rules and one was specified",
+			    p->policyvers);
+			return POLICYDB_ERROR;
+		}
+
+		if (p->target_platform != SEPOL_TARGET_SELINUX) {
+			ERR(fp->handle,
+			    "Target platform %s does not support ioctl"
+			    " extended permissions rules and one was specified",
+			    policydb_target_strings[p->target_platform]);
+			return POLICYDB_ERROR;
+		}
+
+		buf8 = avrule->xperms->specified;
+		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
+		if (items != 1)
+			return POLICYDB_ERROR;
+		buf8 = avrule->xperms->driver;
+		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
+		if (items != 1)
+			return POLICYDB_ERROR;
+		for (i = 0; i < nel; i++)
+			buf32[i] = cpu_to_le32(avrule->xperms->perms[i]);
+		items = put_entry(buf32, sizeof(uint32_t), nel, fp);
+		if (items != nel)
+			return POLICYDB_ERROR;
+	}
+
 	return POLICYDB_SUCCESS;
 }
 
-static int avrule_write_list(avrule_t * avrules, struct policy_file *fp)
+static int avrule_write_list(policydb_t *p, avrule_t * avrules,
+			     struct policy_file *fp)
 {
 	uint32_t buf[32], len;
 	avrule_t *avrule;
@@ -1682,7 +1746,7 @@
 
 	avrule = avrules;
 	while (avrule) {
-		if (avrule_write(avrule, fp))
+		if (avrule_write(p, avrule, fp))
 			return POLICYDB_ERROR;
 		avrule = avrule->next;
 	}
@@ -1870,7 +1934,7 @@
 		return POLICYDB_ERROR;
 	}
 	if (cond_write_list(p, decl->cond_list, fp) == -1 ||
-	    avrule_write_list(decl->avrules, fp) == -1 ||
+	    avrule_write_list(p, decl->avrules, fp) == -1 ||
 	    role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
 	    role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
 		return POLICYDB_ERROR;
diff --git a/libsepol/tests/Makefile b/libsepol/tests/Makefile
index 6ae8ad2..e7e305e 100644
--- a/libsepol/tests/Makefile
+++ b/libsepol/tests/Makefile
@@ -12,10 +12,10 @@
 # This is less than ideal, but it makes the tests easier to maintain by allowing source policies
 # to be loaded directly.
 CHECKPOLICY := ../../checkpolicy/
-CPPFLAGS += -I../include/ -I$(CHECKPOLICY)
+override CPPFLAGS += -I../include/ -I$(CHECKPOLICY)
 
 # test program object files
-objs := $(patsubst %.c,%.o,$(wildcard *.c))
+objs := $(patsubst %.c,%.o,$(sort $(wildcard *.c)))
 parserobjs := $(CHECKPOLICY)queue.o $(CHECKPOLICY)y.tab.o \
 	$(CHECKPOLICY)parse_util.o $(CHECKPOLICY)lex.yy.o \
 	$(CHECKPOLICY)policy_define.o $(CHECKPOLICY)module_compiler.o
diff --git a/libsepol/utils/Makefile b/libsepol/utils/Makefile
index 3b2fb77..fba1d8a 100644
--- a/libsepol/utils/Makefile
+++ b/libsepol/utils/Makefile
@@ -5,9 +5,9 @@
 CFLAGS ?= -Wall -Werror
 override CFLAGS += -I../include
 override LDFLAGS += -L../src
-LDLIBS += -lsepol
+override LDLIBS += -lsepol
 
-TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c)))
 
 all: $(TARGETS)
 
diff --git a/mcstrans/VERSION b/mcstrans/VERSION
index 5154b3f..1effb00 100644
--- a/mcstrans/VERSION
+++ b/mcstrans/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/mcstrans/src/Makefile b/mcstrans/src/Makefile
index 709e1e0..3f4a89c 100644
--- a/mcstrans/src/Makefile
+++ b/mcstrans/src/Makefile
@@ -4,6 +4,7 @@
 SBINDIR ?= $(DESTDIR)/sbin
 INITDIR ?= $(DESTDIR)/etc/rc.d/init.d
 SYSTEMDDIR ?= $(DESTDIR)/usr/lib/systemd
+LIBSEPOLA ?= $(LIBDIR)/libsepol.a
 
 PROG_SRC=mcstrans.c  mcscolor.c  mcstransd.c  mls_level.c
 PROG_OBJS= $(patsubst %.c,%.o,$(PROG_SRC))
@@ -15,7 +16,7 @@
 all: $(PROG)
 
 $(PROG): $(PROG_OBJS)
-	$(CC) $(LDFLAGS) -pie -o $@ $^ -lselinux -lcap -lpcre $(LIBDIR)/libsepol.a
+	$(CC) $(LDFLAGS) -pie -o $@ $^ -lselinux -lcap -lpcre $(LIBSEPOLA)
 
 %.o:  %.c 
 	$(CC) $(CFLAGS) -fPIE -c -o $@ $<
diff --git a/mcstrans/utils/Makefile b/mcstrans/utils/Makefile
index e6f329b..4d3cbfc 100644
--- a/mcstrans/utils/Makefile
+++ b/mcstrans/utils/Makefile
@@ -1,22 +1,22 @@
 # Installation directories.
 PREFIX ?= $(DESTDIR)/usr
 LIBDIR ?= $(PREFIX)/lib
-BINDIR ?= $(PREFIX)/sbin
+SBINDIR ?= $(PREFIX)/sbin
 LIBSEPOLA ?= $(LIBDIR)/libsepol.a
 
 CFLAGS ?= -Wall
 override CFLAGS += -I../src -D_GNU_SOURCE
-LDLIBS += -lselinux -lpcre
+override LDLIBS += -lselinux -lpcre
 
-TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c)))
 
 all: $(TARGETS)
 
 $(TARGETS): ../src/mcstrans.o ../src/mls_level.o $(LIBSEPOLA)
 
 install: all
-	-mkdir -p $(BINDIR)
-	install -m 755 $(TARGETS) $(BINDIR)
+	-mkdir -p $(SBINDIR)
+	install -m 755 $(TARGETS) $(SBINDIR)
 
 test:
 	./mlstrans-test-runner.py ../test/*.test
diff --git a/policycoreutils/VERSION b/policycoreutils/VERSION
index 5154b3f..1effb00 100644
--- a/policycoreutils/VERSION
+++ b/policycoreutils/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/policycoreutils/hll/pp/Makefile b/policycoreutils/hll/pp/Makefile
index 1ca6c9d..3401dcc 100644
--- a/policycoreutils/hll/pp/Makefile
+++ b/policycoreutils/hll/pp/Makefile
@@ -1,16 +1,15 @@
 # Installation directories.
 PREFIX ?= $(DESTDIR)/usr
 INCLUDEDIR ?= $(PREFIX)/include
-SBINDIR ?= $(PREFIX)/sbin
 MANDIR = $(PREFIX)/share/man
 LIBDIR ?= $(PREFIX)/lib
 LIBEXECDIR ?= $(PREFIX)/libexec
 HLLDIR ?= $(LIBEXECDIR)/selinux/hll
 
 CFLAGS ?= -Werror -Wall -W
-LDLIBS = -lsepol
+override LDLIBS += -lsepol
 
-PP_SRCS = $(wildcard *.c)
+PP_SRCS = $(sort $(wildcard *.c))
 PP_OBJS = $(patsubst %.c,%.o,$(PP_SRCS))
 
 all: pp
diff --git a/policycoreutils/load_policy/Makefile b/policycoreutils/load_policy/Makefile
index 6ab0f9d..b85833c 100644
--- a/policycoreutils/load_policy/Makefile
+++ b/policycoreutils/load_policy/Makefile
@@ -1,15 +1,14 @@
 # Installation directories.
 PREFIX ?= $(DESTDIR)/usr
 SBINDIR ?= $(DESTDIR)/sbin
-USRSBINDIR ?= $(PREFIX)/sbin
 MANDIR ?= $(PREFIX)/share/man
 LOCALEDIR ?= /usr/share/locale
 
 CFLAGS ?= -Werror -Wall -W
 override CFLAGS += $(LDFLAGS) -DUSE_NLS -DLOCALEDIR="\"$(LOCALEDIR)\"" -DPACKAGE="\"policycoreutils\""
-LDLIBS += -lsepol -lselinux
+override LDLIBS += -lsepol -lselinux
 
-TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c)))
 
 all: $(TARGETS)
 
@@ -18,8 +17,6 @@
 	install -m 755 $(TARGETS) $(SBINDIR)
 	test -d $(MANDIR)/man8 || install -m 755 -d $(MANDIR)/man8
 	install -m 644 load_policy.8 $(MANDIR)/man8/
-	-mkdir -p $(USRSBINDIR)
-	-ln -sf $(SBINDIR)/load_policy $(USRSBINDIR)/load_policy 
 
 clean:
 	-rm -f $(TARGETS) *.o 
diff --git a/policycoreutils/newrole/Makefile b/policycoreutils/newrole/Makefile
index bdefbb8..196af92 100644
--- a/policycoreutils/newrole/Makefile
+++ b/policycoreutils/newrole/Makefile
@@ -23,18 +23,18 @@
 CFLAGS ?= -Werror -Wall -W
 EXTRA_OBJS =
 override CFLAGS += -DVERSION=\"$(VERSION)\" -DUSE_NLS -DLOCALEDIR="\"$(LOCALEDIR)\"" -DPACKAGE="\"policycoreutils\""
-LDLIBS += -lselinux
+override LDLIBS += -lselinux
 ifeq ($(PAMH), y)
 	override CFLAGS += -DUSE_PAM
 	EXTRA_OBJS += hashtab.o
-	LDLIBS += -lpam -lpam_misc
+	override LDLIBS += -lpam -lpam_misc
 else
 	override CFLAGS += -D_XOPEN_SOURCE=500
-	LDLIBS += -lcrypt
+	override LDLIBS += -lcrypt
 endif
 ifeq ($(AUDITH), y)
 	override CFLAGS += -DUSE_AUDIT
-	LDLIBS += -laudit
+	override LDLIBS += -laudit
 endif
 ifeq ($(LSPP_PRIV),y)
 	override AUDIT_LOG_PRIV=y
@@ -50,7 +50,7 @@
 endif
 ifeq ($(IS_SUID),y)
 	MODE := 4555
-	LDLIBS += -lcap-ng
+	override LDLIBS += -lcap-ng
 else
 	MODE := 0555
 endif
diff --git a/policycoreutils/run_init/Makefile b/policycoreutils/run_init/Makefile
index 6f5ee13..921f0b0 100644
--- a/policycoreutils/run_init/Makefile
+++ b/policycoreutils/run_init/Makefile
@@ -10,20 +10,20 @@
 
 CFLAGS ?= -Werror -Wall -W
 override CFLAGS += -DUSE_NLS -DLOCALEDIR="\"$(LOCALEDIR)\"" -DPACKAGE="\"policycoreutils\""
-LDLIBS += -lselinux
+override LDLIBS += -lselinux
 ifeq ($(PAMH), y)
 	override CFLAGS += -DUSE_PAM
-	LDLIBS += -lpam -lpam_misc
+	override LDLIBS += -lpam -lpam_misc
 else
 	override CFLAGS += -D_XOPEN_SOURCE=500
-	LDLIBS += -lcrypt
+	override LDLIBS += -lcrypt
 endif
 ifeq ($(AUDITH), y)
 	override CFLAGS += -DUSE_AUDIT
-	LDLIBS += -laudit
+	override LDLIBS += -laudit
 endif
 
-TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c)))
 
 all: $(TARGETS)
 
diff --git a/policycoreutils/run_init/open_init_pty.c b/policycoreutils/run_init/open_init_pty.c
index 6e25ea3..150cb45 100644
--- a/policycoreutils/run_init/open_init_pty.c
+++ b/policycoreutils/run_init/open_init_pty.c
@@ -191,6 +191,28 @@
 	}
 }
 
+static void setfd_block(int fd)
+{
+	int fsflags = fcntl(fd, F_GETFL);
+
+	if (fsflags < 0) {
+		fprintf(stderr, "fcntl(%d, F_GETFL): %s\n", fd, strerror(errno));
+		exit(EX_IOERR);
+	}
+
+	if (fcntl(fd, F_SETFL, fsflags & ~O_NONBLOCK) < 0) {
+		fprintf(stderr, "fcntl(%d, F_SETFL, ... & ~O_NONBLOCK): %s\n", fd, strerror(errno));
+		exit(EX_IOERR);
+	}
+}
+
+static void setfd_atexit(void)
+{
+	setfd_block(STDIN_FILENO);
+	setfd_block(STDOUT_FILENO);
+	return;
+}
+
 static void sigchld_handler(int asig __attribute__ ((unused)))
 {
 }
@@ -280,6 +302,10 @@
 	setfd_nonblock(pty_master);
 	setfd_nonblock(STDIN_FILENO);
 	setfd_nonblock(STDOUT_FILENO);
+	if (atexit(setfd_atexit) < 0) {
+		perror("atexit()");
+		exit(EXIT_FAILURE);
+	}
 
 	if (isatty(STDIN_FILENO)) {
 		if (tty_semi_raw(STDIN_FILENO) < 0) {
diff --git a/policycoreutils/scripts/Makefile b/policycoreutils/scripts/Makefile
index 969e5c0..d9e86ff 100644
--- a/policycoreutils/scripts/Makefile
+++ b/policycoreutils/scripts/Makefile
@@ -1,7 +1,5 @@
 # Installation directories.
 PREFIX ?= $(DESTDIR)/usr
-BINDIR ?= $(PREFIX)/bin
-USRSBINDIR ?= $(PREFIX)/sbin
 SBINDIR ?= $(DESTDIR)/sbin
 MANDIR ?= $(PREFIX)/share/man
 LOCALEDIR ?= $(PREFIX)/share/locale
@@ -10,7 +8,7 @@
 all: fixfiles
 
 install: all
-	-mkdir -p $(BINDIR)
+	-mkdir -p $(SBINDIR)
 	install -m 755 fixfiles $(SBINDIR)
 	-mkdir -p $(MANDIR)/man8
 	install -m 644 fixfiles.8 $(MANDIR)/man8/
diff --git a/policycoreutils/scripts/fixfiles b/policycoreutils/scripts/fixfiles
index 0eeeea4..1aa330f 100755
--- a/policycoreutils/scripts/fixfiles
+++ b/policycoreutils/scripts/fixfiles
@@ -255,10 +255,10 @@
 	UNDEFINED=`get_undefined_type` || exit $?
 	UNLABELED=`get_unlabeled_type` || exit $?
 	find /tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) \( -type s -o -type p \) -delete
-	find /tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /tmp {} \;
-	find /var/tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /var/tmp {} \;
-	find /var/run \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /var/run {} \;
-	[ ! -e /var/lib/debug ] || find /var/lib/debug \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /lib {} \;
+	find /tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --no-dereference --reference /tmp {} \;
+	find /var/tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --no-dereference --reference /var/tmp {} \;
+	find /var/run \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --no-dereference --reference /var/run {} \;
+	[ ! -e /var/lib/debug ] || find /var/lib/debug \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --no-dereference --reference /lib {} \;
     ;;
 esac
 }
diff --git a/policycoreutils/secon/Makefile b/policycoreutils/secon/Makefile
index 1f074ff..8e491d7 100644
--- a/policycoreutils/secon/Makefile
+++ b/policycoreutils/secon/Makefile
@@ -9,7 +9,7 @@
 VERSION = $(shell cat ../VERSION)
 CFLAGS ?= $(WARNS) -O1
 override CFLAGS += -DVERSION=\"$(VERSION)\"
-LDLIBS = -lselinux
+override LDLIBS += -lselinux
 
 all: secon
 
diff --git a/policycoreutils/semodule/Makefile b/policycoreutils/semodule/Makefile
index 39ff6a9..fffb43a 100644
--- a/policycoreutils/semodule/Makefile
+++ b/policycoreutils/semodule/Makefile
@@ -6,13 +6,12 @@
 LIBDIR ?= $(PREFIX)/lib
 
 CFLAGS ?= -Werror -Wall -W
-LDLIBS = -lsepol -lselinux -lsemanage
+override LDLIBS += -lsepol -lselinux -lsemanage
 SEMODULE_OBJS = semodule.o
 
 all: semodule genhomedircon
 
 semodule: $(SEMODULE_OBJS)
-	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 
 genhomedircon:
 	ln -sf semodule genhomedircon
diff --git a/policycoreutils/sestatus/Makefile b/policycoreutils/sestatus/Makefile
index 8dbbc01..41ca683 100644
--- a/policycoreutils/sestatus/Makefile
+++ b/policycoreutils/sestatus/Makefile
@@ -7,11 +7,11 @@
 
 CFLAGS ?= -Werror -Wall -W
 override CFLAGS += -D_FILE_OFFSET_BITS=64
-LDLIBS = -lselinux
+override LDLIBS += -lselinux
 
 all: sestatus
 
-sestatus:  sestatus.o 
+sestatus: sestatus.o
 
 install: all
 	[ -d $(MANDIR)/man8 ] || mkdir -p $(MANDIR)/man8
@@ -24,7 +24,7 @@
 	install -m 644 sestatus.conf $(ETCDIR)
 
 clean:
-	rm -f sestatus *.o 
+	rm -f sestatus *.o
 
 indent:
 	../../scripts/Lindent $(wildcard *.[ch])
diff --git a/policycoreutils/setfiles/Makefile b/policycoreutils/setfiles/Makefile
index 4b8cd81..c08e2dd 100644
--- a/policycoreutils/setfiles/Makefile
+++ b/policycoreutils/setfiles/Makefile
@@ -8,21 +8,21 @@
 ABORT_ON_ERRORS=$(shell grep "^\#define ABORT_ON_ERRORS" setfiles.c | awk -S '{ print $$3 }')
 
 CFLAGS ?= -g -Werror -Wall -W
-LDLIBS = -lselinux -lsepol
+override LDLIBS += -lselinux -lsepol
 
 ifeq ($(AUDITH), y)
 	override CFLAGS += -DUSE_AUDIT
-	LDLIBS += -laudit
+	override LDLIBS += -laudit
 endif
 
 all: setfiles restorecon restorecon_xattr man
 
-setfiles:  setfiles.o restore.o
+setfiles: setfiles.o restore.o
 
 restorecon: setfiles
 	ln -sf setfiles restorecon
 
-restorecon_xattr:  restorecon_xattr.o restore.o
+restorecon_xattr: restorecon_xattr.o restore.o
 
 man:
 	@cp -af setfiles.8 setfiles.8.man
diff --git a/policycoreutils/setsebool/Makefile b/policycoreutils/setsebool/Makefile
index 3295963..bc254da 100644
--- a/policycoreutils/setsebool/Makefile
+++ b/policycoreutils/setsebool/Makefile
@@ -7,7 +7,7 @@
 BASHCOMPLETIONDIR ?= $(DESTDIR)/usr/share/bash-completion/completions
 
 CFLAGS ?= -Werror -Wall -W
-LDLIBS = -lsepol -lselinux -lsemanage
+override LDLIBS += -lsepol -lselinux -lsemanage
 SETSEBOOL_OBJS = setsebool.o
 
 BASHCOMPLETIONS=setsebool-bash-completion.sh 
diff --git a/python/VERSION b/python/VERSION
index 5154b3f..1effb00 100644
--- a/python/VERSION
+++ b/python/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/python/chcat/Makefile b/python/chcat/Makefile
index 0a52e8f..0fd12d6 100644
--- a/python/chcat/Makefile
+++ b/python/chcat/Makefile
@@ -1,8 +1,6 @@
 # Installation directories.
 PREFIX ?= $(DESTDIR)/usr
 BINDIR ?= $(PREFIX)/bin
-USRSBINDIR ?= $(PREFIX)/sbin
-SBINDIR ?= $(DESTDIR)/sbin
 MANDIR ?= $(PREFIX)/share/man
 LOCALEDIR ?= $(PREFIX)/share/locale
 
diff --git a/python/semanage/Makefile b/python/semanage/Makefile
index 60c36a3..132162b 100644
--- a/python/semanage/Makefile
+++ b/python/semanage/Makefile
@@ -5,8 +5,8 @@
 LIBDIR ?= $(PREFIX)/lib
 SBINDIR ?= $(PREFIX)/sbin
 MANDIR = $(PREFIX)/share/man
-PYLIBVER ?= $(shell $(PYTHON) -c 'import sys;print("python%d.%d" % sys.version_info[0:2])')
-PYTHONLIBDIR ?= $(LIBDIR)/$(PYLIBVER)
+PYTHONLIBDIR ?= $(shell $(PYTHON) -c "from distutils.sysconfig import *; print(get_python_lib(1))")
+PACKAGEDIR ?= $(DESTDIR)/$(PYTHONLIBDIR)
 BASHCOMPLETIONDIR ?= $(DESTDIR)/usr/share/bash-completion/completions
 
 TARGETS=semanage
@@ -20,8 +20,8 @@
 	-mkdir -p $(SBINDIR)
 	install -m 755 semanage $(SBINDIR)
 	install -m 644 *.8 $(MANDIR)/man8
-	test -d $(PYTHONLIBDIR)/site-packages || install -m 755 -d $(PYTHONLIBDIR)/site-packages
-	install -m 755 seobject.py $(PYTHONLIBDIR)/site-packages
+	test -d $(PACKAGEDIR) || install -m 755 -d $(PACKAGEDIR)
+	install -m 755 seobject.py $(PACKAGEDIR)
 	-mkdir -p $(BASHCOMPLETIONDIR)
 	install -m 644 $(BASHCOMPLETIONS) $(BASHCOMPLETIONDIR)/semanage
 
diff --git a/python/semanage/semanage b/python/semanage/semanage
index 9659aac..313537c 100644
--- a/python/semanage/semanage
+++ b/python/semanage/semanage
@@ -58,6 +58,12 @@
 usage_port = "semanage port [-h] [-n] [-N] [-S STORE] ["
 usage_port_dict = {' --add': ('-t TYPE', '-p PROTOCOL', '-r RANGE', '(', 'port_name', '|', 'port_range', ')'), ' --modify': ('-t TYPE', '-p PROTOCOL', '-r RANGE', '(', 'port_name', '|', 'port_range', ')'), ' --delete': ('-p PROTOCOL', '(', 'port_name', '|', 'port_range', ')'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)}
 
+usage_ibpkey = "semanage ibpkey [-h] [-n] [-N] [-s STORE] ["
+usage_ibpkey_dict = {' --add': ('-t TYPE', '-x SUBNET_PREFIX', '-r RANGE', '(', 'ibpkey_name', '|', 'pkey_range', ')'), ' --modify': ('-t TYPE', '-x SUBNET_PREFIX', '-r RANGE', '(', 'ibpkey_name', '|', 'pkey_range', ')'), ' --delete': ('-x SUBNET_PREFIX', '(', 'ibpkey_name', '|', 'pkey_range', ')'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)}
+
+usage_ibendport = "semanage ibendport [-h] [-n] [-N] [-s STORE] ["
+usage_ibendport_dict = {' --add': ('-t TYPE', '-z IBDEV_NAME', '-r RANGE', '(', 'port', ')'), ' --modify': ('-t TYPE', '-z IBDEV_NAME', '-r RANGE', '(', 'port', ')'), ' --delete': ('-z IBDEV_NAME', '-r RANGE''(', 'port', ')'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)}
+
 usage_node = "semanage node [-h] [-n] [-N] [-S STORE] ["
 usage_node_dict = {' --add': ('-M NETMASK', '-p PROTOCOL', '-t TYPE', '-r RANGE', 'node'), ' --modify': ('-M NETMASK', '-p PROTOCOL', '-t TYPE', '-r RANGE', 'node'), ' --delete': ('-M NETMASK', '-p PROTOCOL', 'node'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)}
 
@@ -145,6 +151,13 @@
     OBJECT = seobject.portRecords(store)
     return OBJECT
 
+def ibpkey_ini():
+    OBJECT = seobject.ibpkeyRecords(store)
+    return OBJECT
+
+def ibendport_ini():
+    OBJECT = seobject.ibendportRecords(store)
+    return OBJECT
 
 def module_ini():
     OBJECT = seobject.moduleRecords(store)
@@ -181,8 +194,7 @@
     return OBJECT
 
 # define dictonary for seobject OBEJCTS
-object_dict = {'login': login_ini, 'user': user_ini, 'port': port_ini, 'module': module_ini, 'interface': interface_ini, 'node': node_ini, 'fcontext': fcontext_ini, 'boolean': boolean_ini, 'permissive': permissive_ini, 'dontaudit': dontaudit_ini}
-
+object_dict = {'login': login_ini, 'user': user_ini, 'port': port_ini, 'module': module_ini, 'interface': interface_ini, 'node': node_ini, 'fcontext': fcontext_ini, 'boolean': boolean_ini, 'permissive': permissive_ini, 'dontaudit': dontaudit_ini, 'ibpkey': ibpkey_ini, 'ibendport': ibendport_ini}
 
 def generate_custom_usage(usage_text, usage_dict):
     # generate custom usage from given text and dictonary
@@ -292,6 +304,15 @@
     version for the specified node (ipv4|ipv6).
 '''))
 
+def parser_add_subnet_prefix(parser, name):
+    parser.add_argument('-x', '--subnet_prefix', help=_('''
+    Subnet prefix for  the specified infiniband ibpkey.
+'''))
+
+def parser_add_ibdev_name(parser, name):
+    parser.add_argument('-z', '--ibdev_name', help=_('''
+    Name for the specified infiniband end port.
+'''))
 
 def parser_add_modify(parser, name):
     parser.add_argument('-m', '--modify', dest='action', action='store_const', const='modify', help=_("Modify a record of the %s object type") % name)
@@ -511,6 +532,95 @@
     portParser.set_defaults(func=handlePort)
 
 
+
+def handlePkey(args):
+    ibpkey_args = {'list': [('ibpkey', 'type', 'subnet_prefix'), ('')], 'add': [('locallist'), ('type', 'ibpkey', 'subnet_prefix')], 'modify': [('localist'), ('ibpkey', 'subnet_prefix')], 'delete': [('locallist'), ('ibpkey', 'subnet_prefix')], 'extract': [('locallist', 'ibpkey', 'type', 'subnet prefix'), ('')], 'deleteall': [('locallist'), ('')]}
+
+    handle_opts(args, ibpkey_args, args.action)
+
+    OBJECT = object_dict['ibpkey']()
+    OBJECT.set_reload(args.noreload)
+
+    if args.action is "add":
+        OBJECT.add(args.ibpkey, args.subnet_prefix, args.range, args.type)
+    if args.action is "modify":
+        OBJECT.modify(args.ibpkey, args.subnet_prefix, args.range, args.type)
+    if args.action is "delete":
+        OBJECT.delete(args.ibpkey, args.subnet_prefix)
+    if args.action is "list":
+        OBJECT.list(args.noheading, args.locallist)
+    if args.action is "deleteall":
+        OBJECT.deleteall()
+    if args.action is "extract":
+        for i in OBJECT.customized():
+            print("ibpkey %s" % str(i))
+
+
+def setupPkeyParser(subparsers):
+    generated_usage = generate_custom_usage(usage_ibpkey, usage_ibpkey_dict)
+    ibpkeyParser = subparsers.add_parser('ibpkey', usage=generated_usage, help=_('Manage infiniband ibpkey type definitions'))
+    parser_add_locallist(ibpkeyParser, "ibpkey")
+    parser_add_noheading(ibpkeyParser, "ibpkey")
+    parser_add_noreload(ibpkeyParser, "ibpkey")
+    parser_add_store(ibpkeyParser, "ibpkey")
+
+    ibpkey_action = ibpkeyParser.add_mutually_exclusive_group(required=True)
+    parser_add_add(ibpkey_action, "ibpkey")
+    parser_add_delete(ibpkey_action, "ibpkey")
+    parser_add_modify(ibpkey_action, "ibpkey")
+    parser_add_list(ibpkey_action, "ibpkey")
+    parser_add_extract(ibpkey_action, "ibpkey")
+    parser_add_deleteall(ibpkey_action, "ibpkey")
+    parser_add_type(ibpkeyParser, "ibpkey")
+    parser_add_range(ibpkeyParser, "ibpkey")
+    parser_add_subnet_prefix(ibpkeyParser, "ibpkey")
+    ibpkeyParser.add_argument('ibpkey', nargs='?', default=None, help=_('pkey | pkey_range'))
+    ibpkeyParser.set_defaults(func=handlePkey)
+
+def handleIbendport(args):
+    ibendport_args = {'list': [('ibendport', 'type', 'ibdev_name'), ('')], 'add': [('locallist'), ('type', 'ibendport', 'ibdev_name'), ('')], 'modify': [('localist'), ('ibendport', 'ibdev_name')], 'delete': [('locallist'), ('ibendport', 'ibdev_name')], 'extract': [('locallist', 'ibendport', 'type', 'ibdev_name'), ('')], 'deleteall': [('locallist'), ('')]}
+
+    handle_opts(args, ibendport_args, args.action)
+
+    OBJECT = object_dict['ibendport']()
+    OBJECT.set_reload(args.noreload)
+
+    if args.action is "add":
+        OBJECT.add(args.ibendport, args.ibdev_name, args.range, args.type)
+    if args.action is "modify":
+        OBJECT.modify(args.ibendport, args.ibdev_name, args.range, args.type)
+    if args.action is "delete":
+        OBJECT.delete(args.ibendport, args.ibdev_name)
+    if args.action is "list":
+        OBJECT.list(args.noheading, args.locallist)
+    if args.action is "deleteall":
+        OBJECT.deleteall()
+    if args.action is "extract":
+        for i in OBJECT.customized():
+            print("ibendport %s" % str(i))
+
+
+def setupIbendportParser(subparsers):
+    generated_usage = generate_custom_usage(usage_ibendport, usage_ibendport_dict)
+    ibendportParser = subparsers.add_parser('ibendport', usage=generated_usage, help=_('Manage infiniband end port type definitions'))
+    parser_add_locallist(ibendportParser, "ibendport")
+    parser_add_noheading(ibendportParser, "ibendport")
+    parser_add_noreload(ibendportParser, "ibendport")
+    parser_add_store(ibendportParser, "ibendport")
+
+    ibendport_action = ibendportParser.add_mutually_exclusive_group(required=True)
+    parser_add_add(ibendport_action, "ibendport")
+    parser_add_delete(ibendport_action, "ibendport")
+    parser_add_modify(ibendport_action, "ibendport")
+    parser_add_list(ibendport_action, "ibendport")
+    parser_add_extract(ibendport_action, "ibendport")
+    parser_add_deleteall(ibendport_action, "ibendport")
+    parser_add_type(ibendportParser, "ibendport")
+    parser_add_range(ibendportParser, "ibendport")
+    parser_add_ibdev_name(ibendportParser, "ibendport")
+    ibendportParser.add_argument('ibendport', nargs='?', default=None, help=_('ibendport'))
+    ibendportParser.set_defaults(func=handleIbendport)
+
 def handleInterface(args):
     interface_args = {'list': [('interface'), ('')], 'add': [('locallist'), ('type', 'interface')], 'modify': [('locallist'), ('type', 'interface')], 'delete': [('locallist'), ('interface')], 'extract': [('locallist', 'interface', 'type'), ('')], 'deleteall': [('locallist'), ('')]}
 
@@ -849,6 +959,8 @@
     setupLoginParser(subparsers)
     setupUserParser(subparsers)
     setupPortParser(subparsers)
+    setupPkeyParser(subparsers)
+    setupIbendportParser(subparsers)
     setupInterfaceParser(subparsers)
     setupModuleParser(subparsers)
     setupNodeParser(subparsers)
diff --git a/python/semanage/semanage-ibendport.8 b/python/semanage/semanage-ibendport.8
new file mode 100644
index 0000000..0a29eae
--- /dev/null
+++ b/python/semanage/semanage-ibendport.8
@@ -0,0 +1,66 @@
+.TH "semanage-ibendport" "8" "20170508" "" ""
+.SH "NAME"
+.B semanage\-ibendport \- SELinux Policy Management ibendport mapping tool
+.SH "SYNOPSIS"
+.B semanage ibendport [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add \-t TYPE \-z IBDEV_NAME \-r RANGE port | \-\-delete \-z IBDEV_NAME port | \-\-deleteall  | \-\-extract  | \-\-list [\-C] | \-\-modify \-t TYPE \-z IBDEV_NAME \-r RANGE port ]
+
+.SH "DESCRIPTION"
+semanage is used to configure certain elements of SELinux policy without requiring modification to or recompilation from policy sources.  semanage ibendport controls the ibendport number to ibendport type definitions.
+
+.SH "OPTIONS"
+.TP
+.I  \-h, \-\-help
+show this help message and exit
+.TP
+.I   \-n, \-\-noheading
+Do not print heading when listing the specified object type
+.TP
+.I   \-N, \-\-noreload
+Do not reload policy after commit
+.TP
+.I   \-S STORE, \-\-store STORE
+Select an alternate SELinux Policy Store to manage
+.TP
+.I   \-C, \-\-locallist
+List local customizations
+.TP
+.I   \-a, \-\-add
+Add a record of the specified object type
+.TP
+.I   \-d, \-\-delete
+Delete a record of the specified object type
+.TP
+.I   \-m, \-\-modify
+Modify a record of the specified object type
+.TP
+.I   \-l, \-\-list
+List records of the specified object type
+.TP
+.I   \-E, \-\-extract
+Extract customizable commands, for use within a transaction
+.TP
+.I   \-D, \-\-deleteall
+Remove all local customizations
+.TP
+.I   \-t TYPE, \-\-type TYPE
+SELinux type for the object
+.TP
+.I   \-r RANGE, \-\-range RANGE
+MLS/MCS Security Range (MLS/MCS Systems only) SELinux Range for SELinux login mapping defaults to the SELinux user record range. SELinux Range for SELinux user defaults to s0.
+.TP
+.I \-z IBDEV_NAME, \-\-ibdev_name IBDEV_NAME
+The name of the infiniband device for the port to be labeled.  (ex. mlx5_0)
+
+.SH EXAMPLE
+.nf
+List all ibendport definitions
+# semanage ibendport \-l
+Label mlx4_0 port 2.
+# semanage ibendport \-a \-t allowed_ibendport_t \-z mlx4_0 2
+
+.SH "SEE ALSO"
+.BR selinux (8),
+.BR semanage (8)
+
+.SH "AUTHOR"
+This man page was written by Daniel Jurgens <danielj@mellanox.com>
diff --git a/python/semanage/semanage-ibpkey.8 b/python/semanage/semanage-ibpkey.8
new file mode 100644
index 0000000..51f455a
--- /dev/null
+++ b/python/semanage/semanage-ibpkey.8
@@ -0,0 +1,66 @@
+.TH "semanage-ibpkey" "8" "20170508" "" ""
+.SH "NAME"
+.B semanage\-ibpkey \- SELinux Policy Management ibpkey mapping tool
+.SH "SYNOPSIS"
+.B semanage ibpkey [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add \-t TYPE \-x SUBNET_PREFIX \-r RANGE ibpkey_name | ibpkey_range | \-\-delete \-x SUBNET_PREFIX ibpkey_name | ibpkey_range | \-\-deleteall  | \-\-extract  | \-\-list [\-C] | \-\-modify \-t TYPE \-x SUBNET_PREFIX \-r RANGE ibpkey_name | ibpkey_range ]
+
+.SH "DESCRIPTION"
+semanage is used to configure certain elements of SELinux policy without requiring modification to or recompilation from policy sources.  semanage ibpkey controls the ibpkey number to ibpkey type definitions.
+
+.SH "OPTIONS"
+.TP
+.I  \-h, \-\-help
+show this help message and exit
+.TP
+.I   \-n, \-\-noheading
+Do not print heading when listing the specified object type
+.TP
+.I   \-N, \-\-noreload
+Do not reload policy after commit
+.TP
+.I   \-S STORE, \-\-store STORE
+Select an alternate SELinux Policy Store to manage
+.TP
+.I   \-C, \-\-locallist
+List local customizations
+.TP
+.I   \-a, \-\-add
+Add a record of the specified object type
+.TP
+.I   \-d, \-\-delete
+Delete a record of the specified object type
+.TP
+.I   \-m, \-\-modify
+Modify a record of the specified object type
+.TP
+.I   \-l, \-\-list
+List records of the specified object type
+.TP
+.I   \-E, \-\-extract
+Extract customizable commands, for use within a transaction
+.TP
+.I   \-D, \-\-deleteall
+Remove all local customizations
+.TP
+.I   \-t TYPE, \-\-type TYPE
+SELinux type for the object
+.TP
+.I   \-r RANGE, \-\-range RANGE
+MLS/MCS Security Range (MLS/MCS Systems only) SELinux Range for SELinux login mapping defaults to the SELinux user record range. SELinux Range for SELinux user defaults to s0.
+.TP
+.I \-x SUBNET_PREFIX, \-\-subnet_prefix SUBNET_PREFIX
+Subnet prefix for the specified pkey or range of pkeys.
+
+.SH EXAMPLE
+.nf
+List all ibpkey definitions
+# semanage ibpkey \-l
+Label pkey 0x8FFF (limited membership default pkey) as a default pkey type
+# semanage ibpkey \-a \-t default_ibpkey_t \-x fe80:: 0x8FFF
+
+.SH "SEE ALSO"
+.BR selinux (8),
+.BR semanage (8)
+
+.SH "AUTHOR"
+This man page was written by Daniel Jurgens <danielj@mellanox.com>
diff --git a/python/semanage/semanage.8 b/python/semanage/semanage.8
index abc4736..0bdb90f 100644
--- a/python/semanage/semanage.8
+++ b/python/semanage/semanage.8
@@ -3,7 +3,7 @@
 semanage \- SELinux Policy Management tool
 
 .SH "SYNOPSIS"
-.B semanage                {import,export,login,user,port,interface,module,node,fcontext,boolean,permissive,dontaudit}
+.B semanage                {import,export,login,user,port,interface,module,node,fcontext,boolean,permissive,dontaudit,ibpkey,ibendport}
                 ...
 .B positional arguments:
 
@@ -43,6 +43,12 @@
 .B    dontaudit
 Disable/Enable dontaudit rules in policy
 
+.B    ibpkey
+Manage infiniband pkey type definitions
+
+.B    ibendport
+Manage infiniband end port type definitions
+
 .SH "DESCRIPTION"
 semanage is used to configure certain elements of
 SELinux policy without requiring modification to or recompilation
@@ -50,9 +56,9 @@
 to SELinux user identities (which controls the initial security context
 assigned to Linux users when they login and bounds their authorized role set)
 as well as security context mappings for various kinds of objects, such
-as network ports, interfaces, and nodes (hosts) as well as the file
-context mapping. See the EXAMPLES section below for some examples
-of common usage.  Note that the semanage login command deals with the
+as network ports, interfaces, infiniband pkeys and endports, and nodes (hosts)
+as well as the file context mapping. See the EXAMPLES section below for some
+examples of common usage.  Note that the semanage login command deals with the
 mapping from Linux usernames (logins) to SELinux user identities,
 while the semanage user command deals with the mapping from SELinux
 user identities to authorized role sets.  In most cases, only the
@@ -79,6 +85,8 @@
 .BR semanage-permissive (8),
 .BR semanage-port (8),
 .BR semanage-user (8)
+.BR semanage-ibkey (8),
+.BR semanage-ibendport (8),
 
 .SH "AUTHOR"
 This man page was written by Daniel Walsh <dwalsh@redhat.com>
diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index 7a54373..70fd192 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -32,6 +32,7 @@
 from semanage import *
 PROGNAME = "policycoreutils"
 import sepolicy
+import setools
 from IPy import IP
 
 try:
@@ -1309,6 +1310,499 @@
                 rec += ", %s" % p
             print(rec)
 
+class ibpkeyRecords(semanageRecords):
+    try:
+        q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibpkey_type"])
+        valid_types = sorted(str(t) for t in q.results())
+    except:
+        valid_types = []
+
+    def __init__(self, store=""):
+        semanageRecords.__init__(self, store)
+
+    def __genkey(self, pkey, subnet_prefix):
+        if subnet_prefix == "":
+            raise ValueError(_("Subnet Prefix is required"))
+
+        pkeys = pkey.split("-")
+        if len(pkeys) == 1:
+            high = low = int(pkeys[0], 0)
+        else:
+            low = int(pkeys[0], 0)
+            high = int(pkeys[1], 0)
+
+        if high > 65535:
+            raise ValueError(_("Invalid Pkey"))
+
+        (rc, k) = semanage_ibpkey_key_create(self.sh, subnet_prefix, low, high)
+        if rc < 0:
+            raise ValueError(_("Could not create a key for %s/%s") % (subnet_prefix, pkey))
+        return (k, subnet_prefix, low, high)
+
+    def __add(self, pkey, subnet_prefix, serange, type):
+        if is_mls_enabled == 1:
+            if serange == "":
+                serange = "s0"
+            else:
+                serange = untranslate(serange)
+
+        if type == "":
+            raise ValueError(_("Type is required"))
+
+        if type not in self.valid_types:
+            raise ValueError(_("Type %s is invalid, must be a ibpkey type") % type)
+
+        (k, subnet_prefix, low, high) = self.__genkey(pkey, subnet_prefix)
+
+        (rc, exists) = semanage_ibpkey_exists(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not check if ibpkey %s/%s is defined") % (subnet_prefix, pkey))
+        if exists:
+            raise ValueError(_("ibpkey %s/%s already defined") % (subnet_prefix, pkey))
+
+        (rc, p) = semanage_ibpkey_create(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not create ibpkey for %s/%s") % (subnet_prefix, pkey))
+
+        semanage_ibpkey_set_subnet_prefix(self.sh, p, subnet_prefix)
+        semanage_ibpkey_set_range(p, low, high)
+        (rc, con) = semanage_context_create(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not create context for %s/%s") % (subnet_prefix, pkey))
+
+        rc = semanage_context_set_user(self.sh, con, "system_u")
+        if rc < 0:
+            raise ValueError(_("Could not set user in ibpkey context for %s/%s") % (subnet_prefix, pkey))
+
+        rc = semanage_context_set_role(self.sh, con, "object_r")
+        if rc < 0:
+            raise ValueError(_("Could not set role in ibpkey context for %s/%s") % (subnet_prefix, pkey))
+
+        rc = semanage_context_set_type(self.sh, con, type)
+        if rc < 0:
+            raise ValueError(_("Could not set type in ibpkey context for %s/%s") % (subnet_prefix, pkey))
+
+        if (is_mls_enabled == 1) and (serange != ""):
+            rc = semanage_context_set_mls(self.sh, con, serange)
+            if rc < 0:
+                raise ValueError(_("Could not set mls fields in ibpkey context for %s/%s") % (subnet_prefix, pkey))
+
+        rc = semanage_ibpkey_set_con(self.sh, p, con)
+        if rc < 0:
+            raise ValueError(_("Could not set ibpkey context for %s/%s") % (subnet_prefix, pkey))
+
+        rc = semanage_ibpkey_modify_local(self.sh, k, p)
+        if rc < 0:
+            raise ValueError(_("Could not add ibpkey %s/%s") % (subnet_prefix, pkey))
+
+        semanage_context_free(con)
+        semanage_ibpkey_key_free(k)
+        semanage_ibpkey_free(p)
+
+    def add(self, pkey, subnet_prefix, serange, type):
+        self.begin()
+        self.__add(pkey, subnet_prefix, serange, type)
+        self.commit()
+
+    def __modify(self, pkey, subnet_prefix, serange, setype):
+        if serange == "" and setype == "":
+            if is_mls_enabled == 1:
+                raise ValueError(_("Requires setype or serange"))
+            else:
+                raise ValueError(_("Requires setype"))
+
+        if setype and setype not in self.valid_types:
+            raise ValueError(_("Type %s is invalid, must be a ibpkey type") % setype)
+
+        (k, subnet_prefix, low, high) = self.__genkey(pkey, subnet_prefix)
+
+        (rc, exists) = semanage_ibpkey_exists(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not check if ibpkey %s/%s is defined") % (subnet_prefix, pkey))
+        if not exists:
+            raise ValueError(_("ibpkey %s/%s is not defined") % (subnet_prefix, pkey))
+
+        (rc, p) = semanage_ibpkey_query(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not query ibpkey %s/%s") % (subnet_prefix, pkey))
+
+        con = semanage_ibpkey_get_con(p)
+
+        if (is_mls_enabled == 1) and (serange != ""):
+            semanage_context_set_mls(self.sh, con, untranslate(serange))
+        if setype != "":
+            semanage_context_set_type(self.sh, con, setype)
+
+        rc = semanage_ibpkey_modify_local(self.sh, k, p)
+        if rc < 0:
+            raise ValueError(_("Could not modify ibpkey %s/%s") % (subnet_prefix, pkey))
+
+        semanage_ibpkey_key_free(k)
+        semanage_ibpkey_free(p)
+
+    def modify(self, pkey, subnet_prefix, serange, setype):
+        self.begin()
+        self.__modify(pkey, subnet_prefix, serange, setype)
+        self.commit()
+
+    def deleteall(self):
+        (rc, plist) = semanage_ibpkey_list_local(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not list the ibpkeys"))
+
+        self.begin()
+
+        for ibpkey in plist:
+            (rc, subnet_prefix) = semanage_ibpkey_get_subnet_prefix(self.sh, ibpkey)
+            low = semanage_ibpkey_get_low(ibpkey)
+            high = semanage_ibpkey_get_high(ibpkey)
+            pkey_str = "%s-%s" % (low, high)
+            (k, subnet_prefix, low, high) = self.__genkey(pkey_str, subnet_prefix)
+            if rc < 0:
+                raise ValueError(_("Could not create a key for %s") % pkey_str)
+
+            rc = semanage_ibpkey_del_local(self.sh, k)
+            if rc < 0:
+                raise ValueError(_("Could not delete the ibpkey %s") % pkey_str)
+            semanage_ibpkey_key_free(k)
+
+        self.commit()
+
+    def __delete(self, pkey, subnet_prefix):
+        (k, subnet_prefix, low, high) = self.__genkey(pkey, subnet_prefix)
+        (rc, exists) = semanage_ibpkey_exists(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not check if ibpkey %s/%s is defined") % (subnet_prefix, pkey))
+        if not exists:
+            raise ValueError(_("ibpkey %s/%s is not defined") % (subnet_prefix, pkey))
+
+        (rc, exists) = semanage_ibpkey_exists_local(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not check if ibpkey %s/%s is defined") % (subnet_prefix, pkey))
+        if not exists:
+            raise ValueError(_("ibpkey %s/%s is defined in policy, cannot be deleted") % (subnet_prefix, pkey))
+
+        rc = semanage_ibpkey_del_local(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not delete ibpkey %s/%s") % (subnet_prefix, pkey))
+
+        semanage_ibpkey_key_free(k)
+
+    def delete(self, pkey, subnet_prefix):
+        self.begin()
+        self.__delete(pkey, subnet_prefix)
+        self.commit()
+
+    def get_all(self, locallist=0):
+        ddict = {}
+        if locallist:
+            (rc, self.plist) = semanage_ibpkey_list_local(self.sh)
+        else:
+            (rc, self.plist) = semanage_ibpkey_list(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not list ibpkeys"))
+
+        for ibpkey in self.plist:
+            con = semanage_ibpkey_get_con(ibpkey)
+            ctype = semanage_context_get_type(con)
+            if ctype == "reserved_ibpkey_t":
+                continue
+            level = semanage_context_get_mls(con)
+            (rc, subnet_prefix) = semanage_ibpkey_get_subnet_prefix(self.sh, ibpkey)
+            low = semanage_ibpkey_get_low(ibpkey)
+            high = semanage_ibpkey_get_high(ibpkey)
+            ddict[(low, high, subnet_prefix)] = (ctype, level)
+        return ddict
+
+    def get_all_by_type(self, locallist=0):
+        ddict = {}
+        if locallist:
+            (rc, self.plist) = semanage_ibpkey_list_local(self.sh)
+        else:
+            (rc, self.plist) = semanage_ibpkey_list(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not list ibpkeys"))
+
+        for ibpkey in self.plist:
+            con = semanage_ibpkey_get_con(ibpkey)
+            ctype = semanage_context_get_type(con)
+            (rc, subnet_prefix) = semanage_ibpkey_get_subnet_prefix(self.sh, ibpkey)
+            low = semanage_ibpkey_get_low(ibpkey)
+            high = semanage_ibpkey_get_high(ibpkey)
+            if (ctype, subnet_prefix) not in ddict.keys():
+                ddict[(ctype, subnet_prefix)] = []
+            if low == high:
+                ddict[(ctype, subnet_prefix)].append("0x%x" % low)
+            else:
+                ddict[(ctype, subnet_prefix)].append("0x%x-0x%x" % (low, high))
+        return ddict
+
+    def customized(self):
+        l = []
+        ddict = self.get_all(True)
+        keys = ddict.keys()
+        keys.sort()
+        for k in keys:
+            if k[0] == k[1]:
+                l.append("-a -t %s -x %s %s" % (ddict[k][0], k[2], k[0]))
+            else:
+                l.append("-a -t %s -x %s %s-%s" % (ddict[k][0], k[2], k[0], k[1]))
+        return l
+
+    def list(self, heading=1, locallist=0):
+        ddict = self.get_all_by_type(locallist)
+        keys = ddict.keys()
+        if len(keys) == 0:
+            return
+        keys.sort()
+
+        if heading:
+            print("%-30s %-18s %s\n" % (_("SELinux IB Pkey Type"), _("Subnet_Prefix"), _("Pkey Number")))
+        for i in keys:
+            rec = "%-30s %-18s " % i
+            rec += "%s" % ddict[i][0]
+            for p in ddict[i][1:]:
+                rec += ", %s" % p
+            print(rec)
+
+class ibendportRecords(semanageRecords):
+    try:
+        q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibendport_type"])
+        valid_types = set(str(t) for t in q.results())
+    except:
+        valid_types = []
+
+    def __init__(self, store=""):
+        semanageRecords.__init__(self, store)
+
+    def __genkey(self, ibendport, ibdev_name):
+        if ibdev_name == "":
+            raise ValueError(_("IB device name is required"))
+
+        port = int(ibendport)
+
+        if port > 255 or port < 1:
+            raise ValueError(_("Invalid Port Number"))
+
+        (rc, k) = semanage_ibendport_key_create(self.sh, ibdev_name, port)
+        if rc < 0:
+            raise ValueError(_("Could not create a key for ibendport %s/%s") % (ibdev_name, ibendport))
+        return (k, ibdev_name, port)
+
+    def __add(self, ibendport, ibdev_name, serange, type):
+        if is_mls_enabled == 1:
+            if serange == "":
+                serange = "s0"
+            else:
+                serange = untranslate(serange)
+
+        if type == "":
+            raise ValueError(_("Type is required"))
+
+        if type not in self.valid_types:
+            raise ValueError(_("Type %s is invalid, must be an ibendport type") % type)
+        (k, ibendport, port) = self.__genkey(ibendport, ibdev_name)
+
+        (rc, exists) = semanage_ibendport_exists(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not check if ibendport %s/%s is defined") % (ibdev_name, port))
+        if exists:
+            raise ValueError(_("ibendport %s/%s already defined") % (ibdev_name, port))
+
+        (rc, p) = semanage_ibendport_create(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not create ibendport for %s/%s") % (ibdev_name, port))
+
+        semanage_ibendport_set_ibdev_name(self.sh, p, ibdev_name)
+        semanage_ibendport_set_port(p, port)
+        (rc, con) = semanage_context_create(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not create context for %s/%s") % (ibdev_name, port))
+
+        rc = semanage_context_set_user(self.sh, con, "system_u")
+        if rc < 0:
+            raise ValueError(_("Could not set user in ibendport context for %s/%s") % (ibdev_name, port))
+
+        rc = semanage_context_set_role(self.sh, con, "object_r")
+        if rc < 0:
+            raise ValueError(_("Could not set role in ibendport context for %s/%s") % (ibdev_name, port))
+
+        rc = semanage_context_set_type(self.sh, con, type)
+        if rc < 0:
+            raise ValueError(_("Could not set type in ibendport context for %s/%s") % (ibdev_name, port))
+
+        if (is_mls_enabled == 1) and (serange != ""):
+            rc = semanage_context_set_mls(self.sh, con, serange)
+            if rc < 0:
+                raise ValueError(_("Could not set mls fields in ibendport context for %s/%s") % (ibdev_name, port))
+
+        rc = semanage_ibendport_set_con(self.sh, p, con)
+        if rc < 0:
+            raise ValueError(_("Could not set ibendport context for %s/%s") % (ibdev_name, port))
+
+        rc = semanage_ibendport_modify_local(self.sh, k, p)
+        if rc < 0:
+            raise ValueError(_("Could not add ibendport %s/%s") % (ibdev_name, port))
+
+        semanage_context_free(con)
+        semanage_ibendport_key_free(k)
+        semanage_ibendport_free(p)
+
+    def add(self, ibendport, ibdev_name, serange, type):
+        self.begin()
+        self.__add(ibendport, ibdev_name, serange, type)
+        self.commit()
+
+    def __modify(self, ibendport, ibdev_name, serange, setype):
+        if serange == "" and setype == "":
+            if is_mls_enabled == 1:
+                raise ValueError(_("Requires setype or serange"))
+            else:
+                raise ValueError(_("Requires setype"))
+
+        if setype and setype not in self.valid_types:
+            raise ValueError(_("Type %s is invalid, must be an ibendport type") % setype)
+
+        (k, ibdev_name, port) = self.__genkey(ibendport, ibdev_name)
+
+        (rc, exists) = semanage_ibendport_exists(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not check if ibendport %s/%s is defined") % (ibdev_name, ibendport))
+        if not exists:
+            raise ValueError(_("ibendport %s/%s is not defined") % (ibdev_name, ibendport))
+
+        (rc, p) = semanage_ibendport_query(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not query ibendport %s/%s") % (ibdev_name, ibendport))
+
+        con = semanage_ibendport_get_con(p)
+
+        if (is_mls_enabled == 1) and (serange != ""):
+            semanage_context_set_mls(self.sh, con, untranslate(serange))
+        if setype != "":
+            semanage_context_set_type(self.sh, con, setype)
+
+        rc = semanage_ibendport_modify_local(self.sh, k, p)
+        if rc < 0:
+            raise ValueError(_("Could not modify ibendport %s/%s") % (ibdev_name, ibendport))
+
+        semanage_ibendport_key_free(k)
+        semanage_ibendport_free(p)
+
+    def modify(self, ibendport, ibdev_name, serange, setype):
+        self.begin()
+        self.__modify(ibendport, ibdev_name, serange, setype)
+        self.commit()
+
+    def deleteall(self):
+        (rc, plist) = semanage_ibendport_list_local(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not list the ibendports"))
+
+        self.begin()
+
+        for ibendport in plist:
+            (rc, ibdev_name) = semanage_ibendport_get_ibdev_name(self.sh, ibendport)
+            port = semanage_ibendport_get_port(ibendport)
+            (k, ibdev_name, port) = self.__genkey(str(port), ibdev_name)
+            if rc < 0:
+                raise ValueError(_("Could not create a key for %s/%d") % (ibdevname, port))
+
+            rc = semanage_ibendport_del_local(self.sh, k)
+            if rc < 0:
+                raise ValueError(_("Could not delete the ibendport %s/%d") % (ibdev_name, port))
+            semanage_ibendport_key_free(k)
+
+        self.commit()
+
+    def __delete(self, ibendport, ibdev_name):
+        (k, ibdev_name, port) = self.__genkey(ibendport, ibdev_name)
+        (rc, exists) = semanage_ibendport_exists(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not check if ibendport %s/%s is defined") % (ibdev_name, ibendport))
+        if not exists:
+            raise ValueError(_("ibendport %s/%s is not defined") % (ibdev_name, ibendport))
+
+        (rc, exists) = semanage_ibendport_exists_local(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not check if ibendport %s/%s is defined") % (ibdev_name, ibendport))
+        if not exists:
+            raise ValueError(_("ibendport %s/%s is defined in policy, cannot be deleted") % (ibdev_name, ibendport))
+
+        rc = semanage_ibendport_del_local(self.sh, k)
+        if rc < 0:
+            raise ValueError(_("Could not delete ibendport %s/%s") % (ibdev_name, ibendport))
+
+        semanage_ibendport_key_free(k)
+
+    def delete(self, ibendport, ibdev_name):
+        self.begin()
+        self.__delete(ibendport, ibdev_name)
+        self.commit()
+
+    def get_all(self, locallist=0):
+        ddict = {}
+        if locallist:
+            (rc, self.plist) = semanage_ibendport_list_local(self.sh)
+        else:
+            (rc, self.plist) = semanage_ibendport_list(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not list ibendports"))
+
+        for ibendport in self.plist:
+            con = semanage_ibendport_get_con(ibendport)
+            ctype = semanage_context_get_type(con)
+            if ctype == "reserved_ibendport_t":
+                continue
+            level = semanage_context_get_mls(con)
+            (rc, ibdev_name) = semanage_ibendport_get_ibdev_name(self.sh, ibendport)
+            port = semanage_ibendport_get_port(ibendport)
+            ddict[(port, ibdev_name)] = (ctype, level)
+        return ddict
+
+    def get_all_by_type(self, locallist=0):
+        ddict = {}
+        if locallist:
+            (rc, self.plist) = semanage_ibendport_list_local(self.sh)
+        else:
+            (rc, self.plist) = semanage_ibendport_list(self.sh)
+        if rc < 0:
+            raise ValueError(_("Could not list ibendports"))
+
+        for ibendport in self.plist:
+            con = semanage_ibendport_get_con(ibendport)
+            ctype = semanage_context_get_type(con)
+            (rc, ibdev_name) = semanage_ibendport_get_ibdev_name(self.sh, ibendport)
+            port = semanage_ibendport_get_port(ibendport)
+            if (ctype, ibdev_name) not in ddict.keys():
+                ddict[(ctype, ibdev_name)] = []
+            ddict[(ctype, ibdev_name)].append("0x%x" % port)
+        return ddict
+
+    def customized(self):
+        l = []
+        ddict = self.get_all(True)
+        keys = ddict.keys()
+        keys.sort()
+        for k in keys:
+            l.append("-a -t %s -x %s %s" % (ddict[k][0], k[2], k[0]))
+        return l
+
+    def list(self, heading=1, locallist=0):
+        ddict = self.get_all_by_type(locallist)
+        keys = ddict.keys()
+        if len(keys) == 0:
+            return
+        keys.sort()
+
+        if heading:
+            print("%-30s %-18s %s\n" % (_("SELinux IB End Port Type"), _("IB Device Name"), _("Port Number")))
+        for i in keys:
+            rec = "%-30s %-18s " % i
+            rec += "%s" % ddict[i][0]
+            for p in ddict[i][1:]:
+                rec += ", %s" % p
+            print(rec)
 
 class nodeRecords(semanageRecords):
     try:
diff --git a/python/sepolicy/Makefile b/python/sepolicy/Makefile
index 647c540..5a56e6c 100644
--- a/python/sepolicy/Makefile
+++ b/python/sepolicy/Makefile
@@ -2,10 +2,8 @@
 
 # Installation directories.
 PREFIX ?= $(DESTDIR)/usr
-SYSCONFDIR ?= $(DESTDIR)/etc/sysconfig
 LIBDIR ?= $(PREFIX)/lib
 BINDIR ?= $(PREFIX)/bin
-SBINDIR ?= $(PREFIX)/sbin
 DATADIR ?= $(PREFIX)/share
 MANDIR ?= $(PREFIX)/share/man
 LOCALEDIR ?= /usr/share/locale
diff --git a/python/sepolicy/sepolicy.py b/python/sepolicy/sepolicy.py
index 5bf9b52..141f64e 100755
--- a/python/sepolicy/sepolicy.py
+++ b/python/sepolicy/sepolicy.py
@@ -241,19 +241,13 @@
 
     return usage_text
 
-
-def numcmp(val1, val2):
+# expects formats:
+# "22 (sshd_t)", "80, 8080 (httpd_t)", "all ports (port_type)"
+def port_string_to_num(val):
     try:
-        v1 = int(val1.split(",")[0].split("-")[0])
-        v2 = int(val2.split(",")[0].split("-")[0])
-        if v1 > v2:
-            return 1
-        if v1 == v2:
-            return 0
-        if v1 < v2:
-            return -1
+        return int(val.split(" ")[0].split(",")[0].split("-")[0])
     except:
-        return cmp(val1, val2)
+        return 99999999
 
 
 def _print_net(src, protocol, perm):
@@ -273,7 +267,7 @@
                     port_strings.append("%s (%s) %s" % (", ".join(recs), t, boolean_text))
                 else:
                     port_strings.append("%s (%s)" % (", ".join(recs), t))
-        port_strings.sort(numcmp)
+        port_strings.sort(key=lambda param: port_string_to_num(param))
         for p in port_strings:
             print("\t" + p)
 
diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
index 8fa2c2a..0374234 100644
--- a/python/sepolicy/sepolicy/__init__.py
+++ b/python/sepolicy/sepolicy/__init__.py
@@ -99,6 +99,7 @@
 fcdict = None
 methods = []
 all_types = None
+all_types_info = None
 user_types = None
 role_allows = None
 portrecs = None
@@ -113,6 +114,8 @@
 all_attributes = None
 booleans = None
 booleans_dict = None
+all_allow_rules = None
+all_transitions = None
 
 
 def get_installed_policy(root="/"):
@@ -168,10 +171,10 @@
             q.name = name
 
         return ({
-            'aliases': map(str, x.aliases()),
+            'aliases': list(map(str, x.aliases())),
             'name': str(x),
             'permissive': bool(x.ispermissive),
-            'attributes': map(str, x.attributes())
+            'attributes': list(map(str, x.attributes()))
         } for x in q.results())
 
     elif setype == ROLE:
@@ -181,8 +184,8 @@
 
         return ({
             'name': str(x),
-            'roles': map(str, x.expand()),
-            'types': map(str, x.types()),
+            'roles': list(map(str, x.expand())),
+            'types': list(map(str, x.types())),
         } for x in q.results())
 
     elif setype == ATTRIBUTE:
@@ -192,7 +195,7 @@
 
         return ({
             'name': str(x),
-            'types': map(str, x.expand()),
+            'types': list(map(str, x.expand())),
         } for x in q.results())
 
     elif setype == PORT:
@@ -204,10 +207,17 @@
             elif len(ports) == 1:
                 q.ports = (ports[0], ports[0])
 
+        if _pol.mls:
+            return ({
+                'high': x.ports.high,
+                'protocol': str(x.protocol),
+                'range': str(x.context.range_),
+                'type': str(x.context.type_),
+                'low': x.ports.low,
+            } for x in q.results())
         return ({
             'high': x.ports.high,
             'protocol': str(x.protocol),
-            'range': str(x.context.range_),
             'type': str(x.context.type_),
             'low': x.ports.low,
         } for x in q.results())
@@ -217,11 +227,16 @@
         if name:
             q.name = name
 
+        if _pol.mls:
+            return ({
+                'range': str(x.mls_range),
+                'name': str(x),
+                'roles': list(map(str, x.roles)),
+                'level': str(x.mls_level),
+            } for x in q.results())
         return ({
-            'range': str(x.mls_range),
             'name': str(x),
-            'roles': map(str, x.roles),
-            'level': str(x.mls_level),
+            'roles': list(map(str, x.roles)),
         } for x in q.results())
 
     elif setype == BOOLEAN:
@@ -362,17 +377,26 @@
 def get_conditionals(src, dest, tclass, perm):
     tdict = {}
     tlist = []
-    if dest.endswith("_t"):
-        allows = search([ALLOW], {SOURCE: src, TARGET: dest, CLASS: tclass, PERMS: perm})
-    else:
-        # to include attribute
-        allows = search([ALLOW], {SOURCE: src, CLASS: tclass, PERMS: perm})
-        for i in allows:
-            if i['target'] == dest:
-                allows = []
-                allows.append(i)
+    src_list = [src]
+    dest_list = [dest]
+    # add assigned attributes
     try:
-        for i in map(lambda y: (y), filter(lambda x: set(perm).issubset(x[PERMS]) and x['boolean'], allows)):
+        src_list += list(filter(lambda x: x['name'] == src, get_all_types_info()))[0]['attributes']
+    except:
+        pass
+    try:
+        dest_list += list(filter(lambda x: x['name'] == dest, get_all_types_info()))[0]['attributes']
+    except:
+        pass
+    allows = map(lambda y: y, filter(lambda x:
+                x['source'] in src_list and
+                x['target'] in dest_list and
+                set(perm).issubset(x[PERMS]) and
+                'boolean' in x,
+                get_all_allow_rules()))
+
+    try:
+        for i in allows:
             tdict.update({'source': i['source'], 'boolean': i['boolean']})
             if tdict not in tlist:
                 tlist.append(tdict)
@@ -561,9 +585,10 @@
     fc += fd.readlines()
     fd.close()
     fcdict = {}
-    fd = open(fc_path + ".local", "r")
-    fc += fd.readlines()
-    fd.close()
+    if os.path.exists(fc_path + ".local"):
+        fd = open(fc_path + ".local", "r")
+        fc += fd.readlines()
+        fd.close()
 
     for i in fc:
         rec = i.split()
@@ -734,6 +759,11 @@
         all_types = [x['name'] for x in info(TYPE)]
     return all_types
 
+def get_all_types_info():
+    global all_types_info
+    if all_types_info is None:
+        all_types_info = list(info(TYPE))
+    return all_types_info
 
 def get_user_types():
     global user_types
@@ -938,7 +968,7 @@
     if f.endswith("_db_t"):
         return txt + "treat the files as %s database content." % prettyprint(f, "_db_t")
     if f.endswith("_ra_content_t"):
-        return txt + "treat the files as %s read/append content." % prettyprint(f, "_ra_conten_t")
+        return txt + "treat the files as %s read/append content." % prettyprint(f, "_ra_content_t")
     if f.endswith("_cert_t"):
         return txt + "treat the files as %s certificate data." % prettyprint(f, "_cert_t")
     if f.endswith("_key_t"):
@@ -1018,12 +1048,23 @@
         short_name = domainname + "_"
     return (domainname, short_name)
 
+def get_all_allow_rules():
+    global all_allow_rules
+    if not all_allow_rules:
+        all_allow_rules = search([ALLOW])
+    return all_allow_rules
+
+def get_all_transitions():
+    global all_transitions
+    if not all_transitions:
+        all_transitions = list(search([TRANSITION]))
+    return all_transitions
 
 def get_bools(setype):
     bools = []
     domainbools = []
     domainname, short_name = gen_short_name(setype)
-    for i in map(lambda x: x['boolean'], filter(lambda x: 'boolean' in x, search([ALLOW], {'source': setype}))):
+    for i in map(lambda x: x['boolean'], filter(lambda x: 'boolean' in x and x['source'] == setype, get_all_allow_rules())):
         for b in i:
             if not isinstance(b, tuple):
                 continue
diff --git a/python/sepolicy/sepolicy/interface.py b/python/sepolicy/sepolicy/interface.py
index 8956f39..c64122e 100644
--- a/python/sepolicy/sepolicy/interface.py
+++ b/python/sepolicy/sepolicy/interface.py
@@ -171,7 +171,7 @@
 
 
 def get_interface_compile_format_text(interfaces_dict, interface):
-    from templates import test_module
+    from .templates import test_module
     param_tmp = []
     for i in interfaces_dict[interface][0]:
         param_tmp.append(test_module.dict_values[i])
@@ -181,7 +181,7 @@
 
 
 def generate_compile_te(interface, idict, name="compiletest"):
-    from templates import test_module
+    from .templates import test_module
     te = ""
     te += re.sub("TEMPLATETYPE", name, test_module.te_test_module)
     te += get_interface_compile_format_text(idict, interface)
diff --git a/python/sepolicy/sepolicy/manpage.py b/python/sepolicy/sepolicy/manpage.py
index a5e36cf..ed8cb71 100755
--- a/python/sepolicy/sepolicy/manpage.py
+++ b/python/sepolicy/sepolicy/manpage.py
@@ -84,7 +84,8 @@
 
     for d in allusers_info:
         allusers.append(d['name'])
-        users_range[d['name'].split("_")[0]] = d['range']
+        if 'range' in d:
+            users_range[d['name'].split("_")[0]] = d['range']
 
     for u in allusers:
         if u not in ["system_u", "root", "unconfined_u"]:
@@ -192,7 +193,7 @@
         self.old_path = path + "/"
         self.new_path = self.old_path + self.os_version + "/"
 
-        if self.os_version in fedora_releases or rhel_releases:
+        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)
@@ -262,7 +263,7 @@
 </pre>
 	""")
         fd.close()
-        print("%s has been created") % index
+        print("%s has been created" % index)
 
     def _gen_body(self):
         html = self.new_path + self.os_version + ".html"
@@ -333,7 +334,7 @@
 """ % domainname_body)
 
         fd.close()
-        print("%s has been created") % html
+        print("%s has been created" % html)
 
     def _gen_css(self):
         style_css = self.old_path + "style.css"
@@ -396,7 +397,7 @@
 """)
 
         fd.close()
-        print("%s has been created") % style_css
+        print("%s has been created" % style_css)
 
 
 class ManPage:
@@ -807,6 +808,7 @@
         self.fd.write(r"""
 .I The following file types are defined for %(domainname)s:
 """ % {'domainname': self.domainname})
+        flist.sort()
         for f in flist:
             self.fd.write("""
 
@@ -920,8 +922,7 @@
 .B "sepolicy manpage".
 
 .SH "SEE ALSO"
-selinux(8), %s(8), semanage(8), restorecon(8), chcon(1), sepolicy(8)
-""" % (self.domainname))
+selinux(8), %s(8), semanage(8), restorecon(8), chcon(1), sepolicy(8)""" % (self.domainname))
 
         if self.booltext != "":
             self.fd.write(", setsebool(8)")
@@ -938,7 +939,11 @@
         return True
 
     def _entrypoints(self):
-        entrypoints = [x['target'] for x in sepolicy.search([sepolicy.ALLOW], {'source': self.type, 'permlist': ['entrypoint'], 'class': 'file'})]
+        entrypoints = [x['target'] for x in filter(lambda y:
+            y['source'] == self.type and y['class'] == 'file' and 'entrypoint' in y['permlist'],
+            sepolicy.get_all_allow_rules()
+        )]
+
         if len(entrypoints) == 0:
             return
 
@@ -969,7 +974,10 @@
 %s""" % ", ".join(paths))
 
     def _mcs_types(self):
-        mcs_constrained_type = next(sepolicy.info(sepolicy.ATTRIBUTE, "mcs_constrained_type"))
+        try:
+            mcs_constrained_type = next(sepolicy.info(sepolicy.ATTRIBUTE, "mcs_constrained_type"))
+        except StopIteration:
+            return
         if self.type not in mcs_constrained_type['types']:
             return
         self.fd.write ("""
@@ -980,15 +988,23 @@
 """ % {'type': self.domainname})
 
     def _writes(self):
-        permlist = sepolicy.search([sepolicy.ALLOW], {'source': self.type, 'permlist': ['open', 'write'], 'class': 'file'})
+        # add assigned attributes
+        src_list = [self.type]
+        try:
+            src_list += list(filter(lambda x: x['name'] == self.type, sepolicy.get_all_types_info()))[0]['attributes']
+        except:
+            pass
+
+        permlist = list(filter(lambda x:
+            x['source'] in src_list and
+            set(['open', 'write']).issubset(x['permlist']) and
+            x['class'] == 'file',
+            sepolicy.get_all_allow_rules()))
         if permlist is None or len(permlist) == 0:
             return
 
         all_writes = []
         attributes = ["proc_type", "sysctl_type"]
-        for i in permlist:
-            if not i['target'].endswith("_t"):
-                attributes.append(i['target'])
 
         for i in permlist:
             if self._valid_write(i['target'], attributes):
@@ -1187,7 +1203,12 @@
 """ % ",".join(ports))
 
     def _home_exec(self):
-        permlist = sepolicy.search([sepolicy.ALLOW], {'source': self.type, 'target': 'user_home_type', 'class': 'file', 'permlist': ['ioctl', 'read', 'getattr', 'execute', 'execute_no_trans', 'open']})
+        permlist = list(filter(lambda x:
+            x['source'] == self.type and
+            x['target'] == 'user_home_type' and
+            x['class'] == 'file' and
+            set(['ioctl', 'read', 'getattr', 'execute', 'execute_no_trans', 'open']).issubset(set(x['permlist'])),
+            sepolicy.get_all_allow_rules()))
         self.fd.write("""
 .SH HOME_EXEC
 """)
diff --git a/python/sepolicy/sepolicy/transition.py b/python/sepolicy/sepolicy/transition.py
index ad53cef..7dea805 100755
--- a/python/sepolicy/sepolicy/transition.py
+++ b/python/sepolicy/sepolicy/transition.py
@@ -30,7 +30,9 @@
 
 
 def _get_trans(src):
-    return sepolicy.search([sepolicy.TRANSITION], {sepolicy.SOURCE: src, sepolicy.CLASS: "process"})
+    src_list = [src] + list(filter(lambda x: x['name'] == src, sepolicy.get_all_types_info()))[0]['attributes']
+    trans_list = list(filter(lambda x: x['source'] in src_list and x['class'] == 'process', sepolicy.get_all_transitions()))
+    return trans_list
 
 
 class setrans:
@@ -53,8 +55,8 @@
         if not self.dest:
             self.sdict[source]["map"] = trans
         else:
-            self.sdict[source]["map"] = map(lambda y: y, filter(lambda x: x["transtype"] == self.dest, trans))
-            self.sdict[source]["child"] = map(lambda y: y["transtype"], filter(lambda x: x["transtype"] not in [self.dest, source], trans))
+            self.sdict[source]["map"] = list(map(lambda y: y, filter(lambda x: x["transtype"] == self.dest, trans)))
+            self.sdict[source]["child"] = list(map(lambda y: y["transtype"], filter(lambda x: x["transtype"] not in [self.dest, source], trans)))
             for s in self.sdict[source]["child"]:
                 self._process(s)
 
diff --git a/python/sepolicy/test_sepolicy.py b/python/sepolicy/test_sepolicy.py
index 304e56f..6d60d6f 100644
--- a/python/sepolicy/test_sepolicy.py
+++ b/python/sepolicy/test_sepolicy.py
@@ -60,7 +60,7 @@
         self.assertSuccess(p.returncode, err)
 
     def test_transition_s(self):
-        "Verify sepolicy transition -l works"
+        "Verify sepolicy transition -s works"
         p = Popen(['sepolicy', 'transition', '-s', 'httpd_t'], stdout=PIPE)
         out, err = p.communicate()
         self.assertSuccess(p.returncode, err)
diff --git a/restorecond/Makefile b/restorecond/Makefile
index b1df89f..ada94ae 100644
--- a/restorecond/Makefile
+++ b/restorecond/Makefile
@@ -29,7 +29,7 @@
 endif
 export PCRE_CFLAGS PCRE_LDLIBS
 
-LDLIBS += -lselinux $(PCRE_LDLIBS) $(DBUSLIB)
+override LDLIBS += -lselinux $(PCRE_LDLIBS) $(DBUSLIB)
 
 all: restorecond
 
diff --git a/restorecond/VERSION b/restorecond/VERSION
index 5154b3f..1effb00 100644
--- a/restorecond/VERSION
+++ b/restorecond/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/sandbox/Makefile b/sandbox/Makefile
index b12fb77..05c3d65 100644
--- a/sandbox/Makefile
+++ b/sandbox/Makefile
@@ -10,7 +10,7 @@
 LOCALEDIR ?= /usr/share/locale
 SHAREDIR ?= $(PREFIX)/share/sandbox
 override CFLAGS += -DPACKAGE="\"policycoreutils\"" -Wall -Werror -Wextra -W
-LDLIBS += -lselinux -lcap-ng
+override LDLIBS += -lselinux -lcap-ng
 SEUNSHARE_OBJS = seunshare.o
 
 all: sandbox seunshare sandboxX.sh start
diff --git a/sandbox/VERSION b/sandbox/VERSION
index 5154b3f..1effb00 100644
--- a/sandbox/VERSION
+++ b/sandbox/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/secilc/Makefile b/secilc/Makefile
index 1e36c6e..1cac53e 100644
--- a/secilc/Makefile
+++ b/secilc/Makefile
@@ -4,8 +4,6 @@
 LIBDIR ?= $(PREFIX)/lib
 INCLUDEDIR ?= $(PREFIX)/include
 
-LDLIBS = -lsepol
-
 SECILC = secilc
 SECILC_SRCS := secilc.c
 SECILC_OBJS := $(patsubst %.c,%.o,$(SECILC_SRCS))
@@ -21,6 +19,7 @@
 CFLAGS ?= -Wall -Wshadow -Wextra -Wundef -Wmissing-format-attribute -Wcast-align -Wstrict-prototypes -Wpointer-arith -Wunused
 
 override CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
+override LDLIBS += -lsepol
 
 all: $(SECILC) $(SECIL2CONF) man
 
diff --git a/secilc/VERSION b/secilc/VERSION
index 5154b3f..1effb00 100644
--- a/secilc/VERSION
+++ b/secilc/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/secilc/docs/Makefile b/secilc/docs/Makefile
index 52c7435..c0fa6b7 100644
--- a/secilc/docs/Makefile
+++ b/secilc/docs/Makefile
@@ -23,6 +23,7 @@
 	cil_sid_statements.md \
 	cil_type_statements.md \
 	cil_user_statements.md \
+	cil_infiniband_statements.md \
 	cil_xen_statements.md
 
 PANDOC_FILE_LIST = $(addprefix $(TMPDIR)/,$(FILE_LIST))
diff --git a/secilc/docs/README.md b/secilc/docs/README.md
index aada78f..3f1838e 100644
--- a/secilc/docs/README.md
+++ b/secilc/docs/README.md
@@ -144,6 +144,10 @@
   * [selinuxuser](cil_user_statements.md#selinuxuser)
   * [selinuxuserdefault](cil_user_statements.md#selinuxuserdefault)
 
+* [Infiniband Statements](cil_infiniband_statements.md#infiniband-statements)
+  * [ibpkeycon](cil_infiniband_statements.md#ibpkeycon)
+  * [ibendportcon](cil_infiniband_statements.md#ibendportcon)
+
 * [Xen Statements](cil_xen_statements.md#xen-statements)
   * [iomemcon](cil_xen_statements.md#iomemcon)
   * [ioportcon](cil_xen_statements.md#ioportcon)
diff --git a/secilc/docs/cil_infiniband_statements.md b/secilc/docs/cil_infiniband_statements.md
new file mode 100644
index 0000000..ba1d710
--- /dev/null
+++ b/secilc/docs/cil_infiniband_statements.md
@@ -0,0 +1,89 @@
+Infiniband Statements
+=====================
+
+To support access control for InfiniBand (IB) partitions and subnet management, security contexts are provided for: Partition Keys (Pkey) that are 16 bit numbers assigned to subnets and their IB end ports. An overview of the SELinux IB implementation can be found at: [http://marc.info/?l=selinux&m=149519833917911&w=2](http://marc.info/?l=selinux&m=149519833917911&w=2).
+
+ibpkeycon
+---------
+
+Label IB partition keys. This may be a single key or a range.
+
+**Statement definition:**
+
+    (ibpkeycon subnet pkey|(pkey_low pkey_high)  context_id)
+
+**Where:**
+
+<table>
+<colgroup>
+<col width="25%" />
+<col width="75%" />
+</colgroup>
+<tbody>
+<tr class="odd">
+<td align="left"><p><code>ibpkeycon</code></p></td>
+<td align="left"><p>The <code>ibpkeycon</code> keyword.</p></td>
+</tr>
+<tr class="even">
+<td align="left"><p><code>subnet</code></p>
+<td align="left"><p>IP address in IPv6 format.</p>
+</tr>
+<tr class="odd">
+<td align="left"><p><code>pkey | (pkey_low pkey_high)</code></p>
+<td align="left"><p>A single partition key or a range of partition keys.</p>
+</tr>
+<tr class="even">
+<td align="left"><p><code>context_id</code></p></td>
+<td align="left"><p>A previously declared <code>context</code> identifier or an anonymous security context (<code>user role type levelrange</code>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</p></td>
+</tr>
+</tbody>
+</table>
+
+**Example:**
+
+An anonymous context for a partition key range of `0x0-0x10` assigned to an IPv6 subnet:
+
+    (ibpkeycon fe80:: (0 0x10) (system_u system_r kernel_t (low (s3 (cats01 cats02)))))
+
+
+ibendportcon
+------------
+
+Label IB end ports.
+
+**Statement definition:**
+
+    (ibendportcon device_id port context_id)
+
+**Where:**
+
+<table>
+<colgroup>
+<col width="27%" />
+<col width="72%" />
+</colgroup>
+<tbody>
+<tr class="odd">
+<td align="left"><p><code>ibendportcon</code></p></td>
+<td align="left"><p>The <code>ibendportcon</code> keyword.</p></td>
+</tr>
+<tr class="even">
+<td align="left"><p><code>device_id</code></p>
+<td align="left"><p>A single device identifier.</p>
+</tr>
+<tr class="odd">
+<td align="left"><p><code>port</code></p>
+<td align="left"><p>A single port number.</p>
+</tr>
+<tr class="even">
+<td align="left"><p><code>context_id</code></p></td>
+<td align="left"><p>A previously declared <code>context</code> identifier or an anonymous security context (<code>user role type levelrange</code>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</p></td>
+</tr>
+</tbody>
+</table>
+
+**Example:**
+
+A named context for device `mlx5_0` on port `1`:
+
+    (ibendportcon mlx5_0 1 system_u_bin_t_l2h)
diff --git a/secilc/test/policy.cil b/secilc/test/policy.cil
index 2078399..4c37ecc 100644
--- a/secilc/test/policy.cil
+++ b/secilc/test/policy.cil
@@ -282,6 +282,12 @@
 	(pcidevicecon 345 system_u_bin_t_l2h)
 	(devicetreecon "/this is/a/path" system_u_bin_t_l2h)
 
+	; InfiniBand
+	(ibpkeycon fe80:: (0 0x10) system_u_bin_t_l2h)
+	(ibpkeycon fe80::7629:afff:fe0f:8e5d (15 25) (system_u system_r kernel_t (low (s3 (cats01 cats02)))))
+	(ibendportcon mlx5_0 1 system_u_bin_t_l2h)
+	(ibendportcon mlx4_3 5 (system_u system_r kernel_t (low (s3 (cats01 cats02)))))
+
 	(constrain (files (read)) (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2))))
 	(constrain char_w (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2))))
 
diff --git a/semodule-utils/VERSION b/semodule-utils/VERSION
index 5154b3f..1effb00 100644
--- a/semodule-utils/VERSION
+++ b/semodule-utils/VERSION
@@ -1 +1 @@
-2.6
+2.7
diff --git a/semodule-utils/semodule_expand/Makefile b/semodule-utils/semodule_expand/Makefile
index 22e3579..072f213 100644
--- a/semodule-utils/semodule_expand/Makefile
+++ b/semodule-utils/semodule_expand/Makefile
@@ -6,7 +6,7 @@
 MANDIR ?= $(PREFIX)/share/man
 
 CFLAGS ?= -Werror -Wall -W
-LDLIBS = -lsepol
+override LDLIBS += -lsepol
 
 all: semodule_expand
 
diff --git a/semodule-utils/semodule_link/Makefile b/semodule-utils/semodule_link/Makefile
index 1e4e278..cc4687b 100644
--- a/semodule-utils/semodule_link/Makefile
+++ b/semodule-utils/semodule_link/Makefile
@@ -6,7 +6,7 @@
 LIBDIR ?= $(PREFIX)/lib
 
 CFLAGS ?= -Werror -Wall -W
-LDLIBS = -lsepol
+override LDLIBS += -lsepol
 
 all: semodule_link
 
diff --git a/semodule-utils/semodule_package/Makefile b/semodule-utils/semodule_package/Makefile
index 5b0d2cc..96dd7c4 100644
--- a/semodule-utils/semodule_package/Makefile
+++ b/semodule-utils/semodule_package/Makefile
@@ -6,7 +6,7 @@
 MANDIR ?= $(PREFIX)/share/man
 
 CFLAGS ?= -Werror -Wall -W
-LDLIBS = -lsepol
+override LDLIBS += -lsepol
 
 all: semodule_package semodule_unpackage