All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] SELinux user space support for Infiniband RDMA
@ 2017-05-09 20:50 Dan Jurgens
  2017-05-09 20:50 ` [PATCH 1/9] checkpolicy: Add support for ibpkeycon labels Dan Jurgens
                   ` (8 more replies)
  0 siblings, 9 replies; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Infiniband applications access HW from user-space -- traffic is generated
directly by HW, bypassing the kernel. Consequently, Infiniband Partitions,
which are associated directly with HW transport endpoints, are a natural
choice for enforcing granular mandatory access control for Infiniband. QPs
may only send or receives packets tagged with the corresponding partition
key (PKey). The PKey is not a cryptographic key; it's a 16 bit number
identifying the partition.

Every Infiniband fabric is controlled by a central Subnet Manager (SM).
The SM provisions the partitions by assigning each port with the
partitions it can access. In addition, the SM tags each port with a subnet
prefix, which identifies the subnet. Determining which users are allowed
to access which partition keys on a given subnet forms an effective policy
for isolating users on the fabric. Any application that attempts to send
traffic on a given subnet is automatically subject to the policy,
regardless of which device and port it uses. SM software configures the
subnet through a privileged Subnet Management Interface (SMI), which is
presented by each Infiniband port. Thus, the SMI must also be controlled
to prevent unauthorized changes to fabric configuration and partitioning. 

To support access control for IB partitions and subnet management,
security contexts must be provided for two new types of objects - PKeys
and IB end ports.

A PKey label consists of a subnet prefix and a range of PKey values and is
similar to the labeling mechanism for netports. Each Infiniband port can
reside on a different subnet. So labeling the PKey values for specific
subnet prefixes provides the user maximum flexibility, as PKey values may
be determined independently for different subnets. There is a single
access vector for PKeys called "access".

An Infiniband port is labeled by device name and port number. There is a
single access vector for IB end ports called "manage_subnet".

This series adds support for parsing the new labeling mechanisms and
generating the policy. It also adds support for runtime labling of PKeys
and IB end ports via semanage.

This series is quite large, but most of the code is very similar to
existing code for the other *con labels.

Example label syntax:
ibpkeycon fe80:: 0xFFFF gen_context(system_u:object_r:default_ibpkey_t,s0)
ibpkeycon fe80:: 0-0x10 gen_context(system_u:object_r:public_ibpkey_t,s0)

ibendportcon mlx5_0 1 gen_context(system_u:object_r:opensm_ibendport_t,s0)

Example semanage commands:
semanage ibpkey -l
semanage ibpkey -a -t default_ibpkey_t -x fe80:: 0x8FFF
semanage ibpkey -D

semanage ibendport -l
semanage ibendport -a -t opensm_ibendport_t -z mlx4_0 2
semanage ibenpdort -d -z mlx4_0 2

Daniel Jurgens (9):
  checkpolicy: Add support for ibpeycon labels
  libsepol: Add ibpey ocontext handling
  libsepol: Add Infiniband Pkey handling to CIL
  checkpolicy: Add support for ibendportcon labels
  libsepol: Add ibendport ocontext handling
  libsepol: Add IB end port handling to CIL
  semanage: Update semanage to allow runtime labeling of Infiniband
    Pkeys
  semanage: Update semanage to allow runtime labeling of ibendports
  semanage: Update man pages for infiniband

 checkpolicy/checkpolicy.c                        |   47 ++
 checkpolicy/policy_define.c                      |  180 ++++++++
 checkpolicy/policy_define.h                      |    2 +
 checkpolicy/policy_parse.y                       |   27 ++-
 checkpolicy/policy_scan.l                        |    5 +
 libsemanage/include/semanage/ibendport_record.h  |   62 +++
 libsemanage/include/semanage/ibendports_local.h  |   36 ++
 libsemanage/include/semanage/ibendports_policy.h |   28 ++
 libsemanage/include/semanage/ibpey_record.h     |   76 ++++
 libsemanage/include/semanage/ibpkeys_local.h     |   36 ++
 libsemanage/include/semanage/ibpkeys_policy.h    |   28 ++
 libsemanage/include/semanage/semanage.h          |    6 +
 libsemanage/src/direct_api.c                     |   57 +++-
 libsemanage/src/handle.h                         |   50 ++-
 libsemanage/src/ibendport_internal.h             |   48 +++
 libsemanage/src/ibendport_record.c               |  154 +++++++
 libsemanage/src/ibendports_file.c                |  157 +++++++
 libsemanage/src/ibendports_local.c               |  153 +++++++
 libsemanage/src/ibendports_policy.c              |   55 +++
 libsemanage/src/ibendports_policydb.c            |   62 +++
 libsemanage/src/ibpkey_internal.h                |   52 +++
 libsemanage/src/ibpkey_record.c                  |  187 ++++++++
 libsemanage/src/ibpkeys_file.c                   |  181 ++++++++
 libsemanage/src/ibpkeys_local.c                  |  182 ++++++++
 libsemanage/src/ibpkeys_policy.c                 |   52 +++
 libsemanage/src/ibpkeys_policydb.c               |   62 +++
 libsemanage/src/libsemanage.map                  |    2 +
 libsemanage/src/policy_components.c              |    9 +-
 libsemanage/src/semanage_store.c                 |    2 +
 libsemanage/src/semanage_store.h                 |    2 +
 libsemanage/src/semanageswig.i                   |    6 +
 libsemanage/src/semanageswig_python.i            |   86 ++++
 libsemanage/utils/semanage_migrate_store         |    4 +-
 libsepol/VERSION                                 |    2 +-
 libsepol/cil/src/cil.c                           |   37 ++
 libsepol/cil/src/cil_binary.c                    |   68 +++
 libsepol/cil/src/cil_binary.h                    |   24 +
 libsepol/cil/src/cil_build_ast.c                 |  151 +++++++
 libsepol/cil/src/cil_build_ast.h                 |    4 +
 libsepol/cil/src/cil_copy_ast.c                  |   51 +++
 libsepol/cil/src/cil_copy_ast.h                  |    1 +
 libsepol/cil/src/cil_flavor.h                    |    2 +
 libsepol/cil/src/cil_internal.h                  |   20 +
 libsepol/cil/src/cil_policy.c                    |   31 ++
 libsepol/cil/src/cil_post.c                      |   87 ++++
 libsepol/cil/src/cil_post.h                      |    2 +
 libsepol/cil/src/cil_reset_ast.c                 |   19 +
 libsepol/cil/src/cil_resolve_ast.c               |   55 +++
 libsepol/cil/src/cil_resolve_ast.h               |    1 +
 libsepol/cil/src/cil_tree.c                      |   29 ++-
 libsepol/cil/src/cil_verify.c                    |   46 ++
 libsepol/include/sepol/ibendport_record.h        |   68 +++
 libsepol/include/sepol/ibendports.h              |   45 ++
 libsepol/include/sepol/ibpkey_record.h           |   75 ++++
 libsepol/include/sepol/ibpkeys.h                 |   44 ++
 libsepol/include/sepol/policydb/policydb.h       |   37 ++-
 libsepol/include/sepol/policydb/services.h       |   21 +
 libsepol/include/sepol/sepol.h                   |    4 +
 libsepol/src/expand.c                            |   17 +
 libsepol/src/ibendport_internal.h                |   20 +
 libsepol/src/ibendport_record.c                  |  299 +++++++++++++
 libsepol/src/ibendports.c                        |  255 +++++++++++
 libsepol/src/ibpkey_internal.h                   |   21 +
 libsepol/src/ibpkey_record.c                     |  474 +++++++++++++++++++++
 libsepol/src/ibpkeys.c                           |  264 ++++++++++++
 libsepol/src/libsepol.map.in                     |    2 +
 libsepol/src/module_to_cil.c                     |   54 +++
 libsepol/src/policydb.c                          |   64 +++
 libsepol/src/services.c                          |   98 +++++
 libsepol/src/write.c                             |   30 ++
 python/semanage/semanage                         |  116 +++++-
 python/semanage/semanage-ibendport.8             |   66 +++
 python/semanage/semanage-ibpkey.8                |   66 +++
 python/semanage/semanage.8                       |   16 +-
 python/semanage/seobject.py                      |  491 ++++++++++++++++++++++
 75 files changed, 5336 insertions(+), 37 deletions(-)
 create mode 100644 libsemanage/include/semanage/ibendport_record.h
 create mode 100644 libsemanage/include/semanage/ibendports_local.h
 create mode 100644 libsemanage/include/semanage/ibendports_policy.h
 create mode 100644 libsemanage/include/semanage/ibpkey_record.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_local.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_policy.h
 create mode 100644 libsemanage/src/ibendport_internal.h
 create mode 100644 libsemanage/src/ibendport_record.c
 create mode 100644 libsemanage/src/ibendports_file.c
 create mode 100644 libsemanage/src/ibendports_local.c
 create mode 100644 libsemanage/src/ibendports_policy.c
 create mode 100644 libsemanage/src/ibendports_policydb.c
 create mode 100644 libsemanage/src/ibpkey_internal.h
 create mode 100644 libsemanage/src/ibpkey_record.c
 create mode 100644 libsemanage/src/ibpkeys_file.c
 create mode 100644 libsemanage/src/ibpkeys_local.c
 create mode 100644 libsemanage/src/ibpkeys_policy.c
 create mode 100644 libsemanage/src/ibpkeys_policydb.c
 create mode 100644 libsepol/include/sepol/ibendport_record.h
 create mode 100644 libsepol/include/sepol/ibendports.h
 create mode 100644 libsepol/include/sepol/ibpkey_record.h
 create mode 100644 libsepol/include/sepol/ibpkeys.h
 create mode 100644 libsepol/src/ibendport_internal.h
 create mode 100644 libsepol/src/ibendport_record.c
 create mode 100644 libsepol/src/ibendports.c
 create mode 100644 libsepol/src/ibpkey_internal.h
 create mode 100644 libsepol/src/ibpkey_record.c
 create mode 100644 libsepol/src/ibpkeys.c
 create mode 100644 python/semanage/semanage-ibendport.8
 create mode 100644 python/semanage/semanage-ibpkey.8

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 1/9] checkpolicy: Add support for ibpkeycon labels
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  2017-05-10 18:22   ` Stephen Smalley
  2017-05-09 20:50 ` [PATCH 2/9] libsepol: Add ibpkey ocontext handling Dan Jurgens
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Add checkpolicy support for scanning and parsing ibpkeycon labels. Also
create a new ocontext for Infiniband Pkeys and define a new policydb
version for infiniband support.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 checkpolicy/policy_define.c                |  110 ++++++++++++++++++++++++++++
 checkpolicy/policy_define.h                |    1 +
 checkpolicy/policy_parse.y                 |   15 ++++-
 checkpolicy/policy_scan.l                  |    3 +
 libsepol/include/sepol/policydb/policydb.h |   32 +++++---
 5 files changed, 148 insertions(+), 13 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 949ca71..6f92bc5 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.
@@ -4975,6 +4976,115 @@ int define_port_context(unsigned int low, unsigned int high)
 	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;
+	}
+
+#ifdef DARWIN
+	memcpy(&newc->u.ibpkey.subnet_prefix[0], &subnet_prefix.s6_addr[0],
+	       sizeof(newc->u.ibpkey.subnet_prefix));
+#else
+	memcpy(&newc->u.ibpkey.subnet_prefix[0], &subnet_prefix.s6_addr32[0],
+	       sizeof(newc->u.ibpkey.subnet_prefix));
+#endif
+
+	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 &&
+		    !memcmp(&c->u.ibpkey.subnet_prefix[0],
+			    &newc->u.ibpkey.subnet_prefix[0],
+			    sizeof(c->u.ibpkey.subnet_prefix))) {
+			yyerror2("duplicate ibpkeycon entry for %d-%d ",
+				 low, high);
+			rc = -1;
+			goto out;
+		}
+		if (low2 <= low && high2 >= high &&
+		    !memcmp(&c->u.ibpkey.subnet_prefix[0],
+			    &newc->u.ibpkey.subnet_prefix[0],
+			    sizeof(c->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_netif_context(void)
 {
 	ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 964baae..b019b1a 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -43,6 +43,7 @@ int define_level(void);
 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_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 3b6a2f8..f50eab1 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.
@@ -134,6 +135,7 @@ typedef int (* require_func_t)(int pass);
 %token TARGET
 %token SAMEUSER
 %token FSCON PORTCON NETIFCON NODECON 
+%token IBPKEYCON
 %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
 %token FSUSEXATTR FSUSETASK FSUSETRANS
 %token GENFSCON
@@ -169,7 +171,7 @@ base_policy             : { if (define_policy(pass, 0) == -1) return -1; }
 			  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
 			;
 classes			: class_def 
 			| classes class_def
@@ -708,6 +710,17 @@ port_context_def	: PORTCON identifier number security_context_def
 			| 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_netif_contexts      : netif_contexts 
                         |
                         ;
diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
index 2f7f221..07352cb 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.
@@ -181,6 +182,8 @@ INCOMP |
 incomp				{ return(INCOMP);}
 fscon |
 FSCON                           { return(FSCON);}
+ibpkeycon |
+IBPKEYCON			{ return(IBPKEYCON);}
 portcon |
 PORTCON				{ return(PORTCON);}
 netifcon |                     
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 4336a3f..5ecc623 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
@@ -354,6 +355,11 @@ typedef struct ocontext {
 			uint32_t low_ioport;
 			uint32_t high_ioport;
 		} ioport;
+		struct {
+			uint32_t subnet_prefix[4];
+			uint16_t low_pkey;
+			uint16_t high_pkey;
+		} ibpkey;
 	} u;
 	union {
 		uint32_t sclass;	/* security class for genfs */
@@ -382,14 +388,14 @@ typedef struct genfs {
 #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 */
 
 /* object context array indices for Xen */
 #define OCON_XEN_ISID  	    0    /* initial SIDs */
@@ -400,7 +406,7 @@ typedef struct genfs {
 #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   8
 
 /* section: module information */
 
@@ -722,10 +728,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
 #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
 
 /* 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
@@ -743,10 +750,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
 #define MOD_POLICYDB_VERSION_TUNABLE_SEP	14
 #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_CONSTRAINT_NAMES	17
+#define MOD_POLICYDB_VERSION_INFINIBAND		18
 
 #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
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 2/9] libsepol: Add ibpkey ocontext handling
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
  2017-05-09 20:50 ` [PATCH 1/9] checkpolicy: Add support for ibpkeycon labels Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  2017-05-10 18:55   ` Stephen Smalley
  2017-05-11 15:19   ` James Carter
  2017-05-09 20:50 ` [PATCH 3/9] libsepol: Add Infiniband Pkey handling to CIL Dan Jurgens
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Add support for reading, writing, and copying Infinabinda Pkey ocontext
data. Also add support for querying a Pkey sid to checkpolicy.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 checkpolicy/checkpolicy.c                  |   27 +++++++++++++
 libsepol/include/sepol/policydb/services.h |   11 +++++
 libsepol/src/expand.c                      |    9 ++++
 libsepol/src/libsepol.map.in               |    1 +
 libsepol/src/module_to_cil.c               |   39 ++++++++++++++++++
 libsepol/src/policydb.c                    |   47 ++++++++++++++++++++++
 libsepol/src/services.c                    |   59 ++++++++++++++++++++++++++++
 libsepol/src/write.c                       |   16 +++++++
 8 files changed, 209 insertions(+), 0 deletions(-)

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 534fc22..0f12347 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,7 @@ int main(int argc, char **argv)
 	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");
 #ifdef EQUIVTYPES
 	printf("z)  Show equivalent types\n");
 #endif
@@ -1220,6 +1222,31 @@ int main(int argc, char **argv)
 				    "\nNo validatetrans expressions found.\n");
 			}
 			break;
+		case 'k':
+			{
+				char *p;
+				int len;
+				struct in6_addr addr6;
+				unsigned int pkey;
+
+				printf("subnet prefix?  ");
+				FGETS(ans, sizeof(ans), stdin);
+				ans[strlen(ans) - 1] = 0;
+				p = (char *)&addr6;
+				len = sizeof(addr6);
+
+				if (inet_pton(AF_INET6, ans, p) < 1) {
+					printf("error parsing subnet prefix\n");
+					break;
+				}
+
+				printf("pkey? ");
+				FGETS(ans, sizeof(ans), stdin);
+				pkey = atoi(ans);
+				sepol_ibpkey_sid(0, 0, p, len, pkey, &ssid);
+				printf("sid %d\n", ssid);
+			}
+			break;
 #ifdef EQUIVTYPES
 		case 'z':
 			identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h b/libsepol/include/sepol/policydb/services.h
index 9162149..2d7aed1 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -188,6 +188,17 @@ extern int sepol_port_sid(uint16_t domain,
 			  uint16_t port, sepol_security_id_t * out_sid);
 
 /*
+ * Return the SID of the ibpkey specified by
+ * `domain', `type', `subnet prefix', and `pkey'.
+ */
+extern int sepol_ibpkey_sid(uint16_t domain,
+			  uint16_t type,
+			  void *subnet_prefix_p,
+			  size_t splen,
+			  uint16_t pkey,
+			  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/src/expand.c b/libsepol/src/expand.c
index 54bf781..c45ecbe 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
@@ -2217,6 +2218,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
 					return -1;
 				}
 				break;
+			case OCON_IBPKEY:
+				n->u.ibpkey.subnet_prefix[0] = c->u.ibpkey.subnet_prefix[0];
+				n->u.ibpkey.subnet_prefix[1] = c->u.ibpkey.subnet_prefix[1];
+				n->u.ibpkey.subnet_prefix[2] = c->u.ibpkey.subnet_prefix[2];
+				n->u.ibpkey.subnet_prefix[3] = c->u.ibpkey.subnet_prefix[3];
+				n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey;
+				n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey;
+			break;
 			case OCON_PORT:
 				n->u.port.protocol = c->u.port.protocol;
 				n->u.port.low_port = c->u.port.low_port;
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index 4042640..36225d1 100644
--- a/libsepol/src/libsepol.map.in
+++ b/libsepol/src/libsepol.map.in
@@ -6,6 +6,7 @@ LIBSEPOL_1.0 {
 	sepol_context_*; sepol_mls_*; sepol_check_context;
 	sepol_iface_*; 
 	sepol_port_*;
+	sepol_ibpkey_*;
 	sepol_node_*;
 	sepol_user_*; sepol_genusers; sepol_set_delusers;
 	sepol_msg_*; sepol_debug;
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index ac095c3..db3f9c8 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
@@ -2583,6 +2584,7 @@ static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *i
 		"policy",
 		"scmp_packet",
 		"devnull",
+		"ibpkey",
 		NULL
 	};
 
@@ -2645,6 +2647,42 @@ exit:
 	return rc;
 }
 
+static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb,
+					struct ocontext *ibpkeycons)
+{
+	int rc = -1;
+	struct ocontext *ibpkeycon;
+	char subnet_prefix[INET6_ADDRSTRLEN];
+	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;
+
+		if (inet_ntop(AF_INET6, &ibpkeycon->u.ibpkey.subnet_prefix,
+			      subnet_prefix, 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, low);
+		else
+			cil_printf("(ibpkeycon %s (%i %i) ", subnet_prefix, 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;
@@ -2878,6 +2916,7 @@ static int ocontexts_to_cil(struct policydb *pdb)
 		ocontext_selinux_node_to_cil,
 		ocontext_selinux_fsuse_to_cil,
 		ocontext_selinux_node6_to_cil,
+		ocontext_selinux_ibpkey_to_cil,
 	};
 	static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = {
 		ocontext_xen_isid_to_cil,
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 7093b29..8b76c6a 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
@@ -185,6 +186,21 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .ocon_num = OCON_NODE6 + 1,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
+
+	{
+	 .type = POLICY_KERN,
+	 .version = POLICYDB_VERSION_XPERMS_IOCTL,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_NODE6 + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
+	 .type = POLICY_KERN,
+	 .version = POLICYDB_VERSION_INFINIBAND,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_IBPKEY + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
 	{
 	 .type = POLICY_BASE,
 	 .version = MOD_POLICYDB_VERSION_BASE,
@@ -284,6 +300,13 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
+	 .type = POLICY_BASE,
+	 .version = MOD_POLICYDB_VERSION_INFINIBAND,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_IBPKEY + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
 	 .type = POLICY_MOD,
 	 .version = MOD_POLICYDB_VERSION_BASE,
 	 .sym_num = SYM_NUM,
@@ -381,6 +404,13 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .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
@@ -2782,6 +2812,23 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
 				    (&c->context[1], p, fp))
 					return -1;
 				break;
+			case OCON_IBPKEY:
+				rc = next_entry(buf, fp, sizeof(uint32_t) * 6);
+				if (rc < 0)
+					return -1;
+
+				c->u.ibpkey.subnet_prefix[0] = buf[0];
+				c->u.ibpkey.subnet_prefix[1] = buf[1];
+				c->u.ibpkey.subnet_prefix[2] = buf[2];
+				c->u.ibpkey.subnet_prefix[3] = buf[3];
+
+				c->u.ibpkey.low_pkey = le32_to_cpu(buf[4]);
+				c->u.ibpkey.high_pkey = le32_to_cpu(buf[5]);
+
+				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)
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 03fb120..39903d1 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
@@ -1910,6 +1911,64 @@ int hidden sepol_fs_sid(char *name,
 	return rc;
 }
 
+static int match_subnet_prefix(uint32_t *input, uint32_t *subnet_prefix)
+{
+	int i, fail = 0;
+
+	for (i = 0; i < 4; i++)
+		if (subnet_prefix[i] != input[i]) {
+			fail = 1;
+			break;
+		}
+
+	return !fail;
+}
+
+/*
+ * Return the SID of the ibpkey specified by
+ * `domain', `type', `subnet prefix', and `pkey number'.
+ */
+int hidden sepol_ibpkey_sid(uint16_t domain __attribute__ ((unused)),
+			  uint16_t type __attribute__ ((unused)),
+			  void *subnet_prefix_p,
+			  size_t splen,
+			  uint16_t pkey, sepol_security_id_t *out_sid)
+{
+	ocontext_t *c;
+	int rc = 0;
+
+	if (splen != sizeof(uint64_t)) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	c = policydb->ocontexts[OCON_IBPKEY];
+	while (c) {
+		if (c->u.ibpkey.low_pkey <= pkey &&
+		    c->u.ibpkey.high_pkey >= pkey &&
+		    match_subnet_prefix(subnet_prefix_p,
+					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 port specified by
  * `domain', `type', `protocol', and `port'.
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index e75b9ab..fa1b7d1 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
@@ -1410,6 +1411,21 @@ static int ocontext_write_selinux(struct policydb_compat_info *info,
 				if (context_write(p, &c->context[1], fp))
 					return POLICYDB_ERROR;
 				break;
+			case OCON_IBPKEY:
+				 /* The subnet prefix is in network order */
+				for (j = 0; j < 4; j++)
+					buf[j] = c->u.ibpkey.subnet_prefix[j];
+
+				buf[4] = cpu_to_le32(c->u.ibpkey.low_pkey);
+				buf[5] = cpu_to_le32(c->u.ibpkey.high_pkey);
+
+				items = put_entry(buf, sizeof(uint32_t), 6, fp);
+				if (items != 6)
+					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;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 3/9] libsepol: Add Infiniband Pkey handling to CIL
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
  2017-05-09 20:50 ` [PATCH 1/9] checkpolicy: Add support for ibpkeycon labels Dan Jurgens
  2017-05-09 20:50 ` [PATCH 2/9] libsepol: Add ibpkey ocontext handling Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  2017-05-09 20:50 ` [PATCH 4/9] checkpolicy: Add support for ibendportcon labels Dan Jurgens
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Add Infiniband pkey parsing, symbol table management, and policy
generation to CIL.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 libsepol/cil/src/cil.c             |   19 ++++++++
 libsepol/cil/src/cil_binary.c      |   39 ++++++++++++++++
 libsepol/cil/src/cil_binary.h      |   12 +++++
 libsepol/cil/src/cil_build_ast.c   |   86 ++++++++++++++++++++++++++++++++++++
 libsepol/cil/src/cil_build_ast.h   |    2 +
 libsepol/cil/src/cil_copy_ast.c    |   26 +++++++++++
 libsepol/cil/src/cil_copy_ast.h    |    1 +
 libsepol/cil/src/cil_flavor.h      |    1 +
 libsepol/cil/src/cil_internal.h    |   11 +++++
 libsepol/cil/src/cil_policy.c      |   16 +++++++
 libsepol/cil/src/cil_post.c        |   45 +++++++++++++++++++
 libsepol/cil/src/cil_post.h        |    1 +
 libsepol/cil/src/cil_reset_ast.c   |    9 ++++
 libsepol/cil/src/cil_resolve_ast.c |   27 +++++++++++
 libsepol/cil/src/cil_resolve_ast.h |    1 +
 libsepol/cil/src/cil_tree.c        |   16 ++++++-
 libsepol/cil/src/cil_verify.c      |   23 ++++++++++
 17 files changed, 334 insertions(+), 1 deletions(-)

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index a64c528..6b51b8f 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -187,6 +187,7 @@ static void cil_init_keys(void)
 	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_PORTCON = cil_strpool_add("portcon");
 	CIL_KEY_NODECON = cil_strpool_add("nodecon");
 	CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -256,6 +257,7 @@ void cil_db_init(struct cil_db **db)
 	cil_sort_init(&(*db)->genfscon);
 	cil_sort_init(&(*db)->filecon);
 	cil_sort_init(&(*db)->nodecon);
+	cil_sort_init(&(*db)->ibpkeycon);
 	cil_sort_init(&(*db)->portcon);
 	cil_sort_init(&(*db)->pirqcon);
 	cil_sort_init(&(*db)->iomemcon);
@@ -307,6 +309,7 @@ void cil_db_destroy(struct cil_db **db)
 	cil_sort_destroy(&(*db)->genfscon);
 	cil_sort_destroy(&(*db)->filecon);
 	cil_sort_destroy(&(*db)->nodecon);
+	cil_sort_destroy(&(*db)->ibpkeycon);
 	cil_sort_destroy(&(*db)->portcon);
 	cil_sort_destroy(&(*db)->pirqcon);
 	cil_sort_destroy(&(*db)->iomemcon);
@@ -724,6 +727,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
 	case CIL_FILECON:
 		cil_destroy_filecon(*data);
 		break;
+	case CIL_IBPKEYCON:
+		cil_destroy_ibpkeycon(*data);
+		break;
 	case CIL_PORTCON:
 		cil_destroy_portcon(*data);
 		break;
@@ -1091,6 +1097,8 @@ const char * cil_node_to_string(struct cil_tree_node *node)
 		return CIL_KEY_FSUSE;
 	case CIL_FILECON:
 		return CIL_KEY_FILECON;
+	case CIL_IBPKEYCON:
+		return CIL_KEY_IBPKEYCON;
 	case CIL_PORTCON:
 		return CIL_KEY_PORTCON;
 	case CIL_NODECON:
@@ -2240,6 +2248,17 @@ void cil_filecon_init(struct cil_filecon **filecon)
 	(*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..75398ff 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3218,6 +3218,40 @@ exit:
 	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;
@@ -3848,6 +3882,11 @@ int __cil_contexts_to_policydb(policydb_t *pdb, const struct cil_db *db)
 		goto exit;
 	}
 
+	rc = cil_ibpkeycon_to_policydb(pdb, db->ibpkeycon);
+	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..a03d250 100644
--- a/libsepol/cil/src/cil_binary.h
+++ b/libsepol/cil/src/cil_binary.h
@@ -330,6 +330,18 @@ int cil_sepol_level_define(policydb_t *pdb, struct cil_sens *cil_sens);
 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 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 4b03dc3..4ca88c1 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -4187,6 +4187,89 @@ void cil_destroy_filecon(struct cil_filecon *filecon)
 	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 (!db || !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[] = {
@@ -6143,6 +6226,9 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
 	} 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_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 5466203..64da477 100644
--- a/libsepol/cil/src/cil_build_ast.h
+++ b/libsepol/cil/src/cil_build_ast.h
@@ -173,6 +173,8 @@ int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, stru
 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_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 2d085dd..5c55983 100644
--- a/libsepol/cil/src/cil_copy_ast.c
+++ b/libsepol/cil/src/cil_copy_ast.c
@@ -1181,6 +1181,29 @@ int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, __attribute__((
 	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_portcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
 {
 	struct cil_portcon *orig = data;
@@ -1890,6 +1913,9 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
 	case CIL_NODECON:
 		copy_func = &cil_copy_nodecon;
 		break;
+	case CIL_IBPKEYCON:
+		copy_func = &cil_copy_ibpkeycon;
+		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_netifcon(struct cil_db *db, void *data, void **copy, symtab_t *symt
 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 cd08b97..242154d 100644
--- a/libsepol/cil/src/cil_flavor.h
+++ b/libsepol/cil/src/cil_flavor.h
@@ -112,6 +112,7 @@ enum cil_flavor {
 	CIL_HANDLEUNKNOWN,
 	CIL_MLS,
 	CIL_SRC_INFO,
+	CIL_IBPKEYCON,
 
 /*
  *          boolean  constraint  set  catset
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index efa2cd6..de2a8df 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -202,6 +202,7 @@ char *CIL_KEY_VALIDATETRANS;
 char *CIL_KEY_MLSVALIDATETRANS;
 char *CIL_KEY_CONTEXT;
 char *CIL_KEY_FILECON;
+char *CIL_KEY_IBPKEYCON;
 char *CIL_KEY_PORTCON;
 char *CIL_KEY_NODECON;
 char *CIL_KEY_GENFSCON;
@@ -285,6 +286,7 @@ struct cil_db {
 	struct cil_sort *genfscon;
 	struct cil_sort *filecon;
 	struct cil_sort *nodecon;
+	struct cil_sort *ibpkeycon;
 	struct cil_sort *portcon;
 	struct cil_sort *pirqcon;
 	struct cil_sort *iomemcon;
@@ -728,6 +730,14 @@ enum cil_protocol {
 	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;
@@ -997,6 +1007,7 @@ void cil_catset_init(struct cil_catset **catset);
 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_policy.c b/libsepol/cil/src/cil_policy.c
index 77179e6..35a0a29 100644
--- a/libsepol/cil/src/cil_policy.c
+++ b/libsepol/cil/src/cil_policy.c
@@ -1714,6 +1714,21 @@ static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int m
 	}
 }
 
+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_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls)
 {
 	unsigned i;
@@ -1942,6 +1957,7 @@ void cil_gen_policy(FILE *out, struct cil_db *db)
 	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_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 e32a8fc..8b6608a 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -154,6 +154,28 @@ int cil_post_filecon_compare(const void *a, const void *b)
 	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;
@@ -401,6 +423,9 @@ static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *fini
 	case CIL_NODECON:
 		db->nodecon->count++;
 		break;
+	case CIL_IBPKEYCON:
+		db->ibpkeycon->count++;
+		break;
 	case CIL_PORTCON:
 		db->portcon->count++;
 		break;
@@ -535,6 +560,17 @@ static int __cil_post_db_array_helper(struct cil_tree_node *node, uint32_t *fini
 		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;
@@ -1610,6 +1646,14 @@ static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finish
 		}
 		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_PORTCON: {
 		struct cil_portcon *portcon = node->data;
 		rc = __evaluate_levelrange_expression(portcon->context->range, db);
@@ -1969,6 +2013,7 @@ static int cil_post_db(struct cil_db *db)
 
 	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->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..fe7f3a5 100644
--- a/libsepol/cil/src/cil_post.h
+++ b/libsepol/cil/src/cil_post.h
@@ -38,6 +38,7 @@ struct fc_data {
 
 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_genfscon_compare(const void *a, const void *b);
 int cil_post_netifcon_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 de00679..d366ae3 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_filecon(struct cil_filecon *filecon)
 	}
 }
 
+static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
+{
+	if (!ibpkeycon->context)
+		cil_reset_context(ibpkeycon->context);
+}
+
 static void cil_reset_portcon(struct cil_portcon *portcon)
 {
 	if (portcon->context_str == NULL) {
@@ -489,6 +495,9 @@ int __cil_reset_node(struct cil_tree_node *node,  __attribute__((unused)) uint32
 	case CIL_FILECON:
 		cil_reset_filecon(node->data);
 		break;
+	case CIL_IBPKEYCON:
+		cil_reset_ibpkeycon(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 6da44ba..1df41da 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -1875,6 +1875,30 @@ int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args)
 	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;
@@ -3516,6 +3540,9 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
 		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;
diff --git a/libsepol/cil/src/cil_resolve_ast.h b/libsepol/cil/src/cil_resolve_ast.h
index 1175f97..0506a3d 100644
--- a/libsepol/cil/src/cil_resolve_ast.h
+++ b/libsepol/cil/src/cil_resolve_ast.h
@@ -74,6 +74,7 @@ int cil_resolve_constrain(struct cil_tree_node *current, void *extra_args);
 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_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);
diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
index 9ff9d4b..4703e5f 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:
  * 
@@ -1398,6 +1398,20 @@ void cil_tree_print_node(struct cil_tree_node *node)
 			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:");
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 47dcfaa..108da33 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -1080,6 +1080,26 @@ exit:
 	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 +1472,9 @@ int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *ex
 		case CIL_NODECON:
 			rc = __cil_verify_nodecon(db, node);
 			break;
+		case CIL_IBPKEYCON:
+			rc = __cil_verify_ibpkeycon(db, node);
+			break;
 		case CIL_PORTCON:
 			rc = __cil_verify_portcon(db, node);
 			break;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 4/9] checkpolicy: Add support for ibendportcon labels
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
                   ` (2 preceding siblings ...)
  2017-05-09 20:50 ` [PATCH 3/9] libsepol: Add Infiniband Pkey handling to CIL Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  2017-05-10 19:00   ` Stephen Smalley
  2017-05-09 20:50 ` [PATCH 5/9] libsepol: Add ibendport ocontext handling Dan Jurgens
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Add checkpolicy support for scanning and parsing ibendportcon labels.
Also create a new ocontext for IB end ports.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 checkpolicy/policy_define.c                |   70 ++++++++++++++++++++++++++++
 checkpolicy/policy_define.h                |    1 +
 checkpolicy/policy_parse.y                 |   14 +++++-
 checkpolicy/policy_scan.l                  |    2 +
 libsepol/include/sepol/policydb/policydb.h |    7 ++-
 5 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 6f92bc5..2926f18 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -5085,6 +5085,76 @@ out:
 	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;
+	}
+
+	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 subnet management interface device name.");
+		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 &&
+		    !strncmp(c->u.ibendport.dev_name,
+			     newc->u.ibendport.dev_name,
+			     64)) {
+			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 b019b1a..3282aed 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -44,6 +44,7 @@ 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 f50eab1..35b7a33 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -136,6 +136,7 @@ typedef int (* require_func_t)(int pass);
 %token SAMEUSER
 %token FSCON PORTCON NETIFCON NODECON 
 %token IBPKEYCON
+%token IBENDPORTCON
 %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
 %token FSUSEXATTR FSUSETASK FSUSETRANS
 %token GENFSCON
@@ -171,7 +172,7 @@ base_policy             : { if (define_policy(pass, 0) == -1) return -1; }
 			  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 opt_ibpkey_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
@@ -697,7 +698,7 @@ fs_contexts		: fs_context_def
 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
                         |
@@ -721,6 +722,15 @@ ibpkey_context_def	: IBPKEYCON ipv6_addr number security_context_def
 			| 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 07352cb..f38dd22 100644
--- a/checkpolicy/policy_scan.l
+++ b/checkpolicy/policy_scan.l
@@ -184,6 +184,8 @@ fscon |
 FSCON                           { return(FSCON);}
 ibpkeycon |
 IBPKEYCON			{ return(IBPKEYCON);}
+ibendportcon |
+IBENDPORTCON			{ return(IBENDPORTCON);}
 portcon |
 PORTCON				{ return(PORTCON);}
 netifcon |                     
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 5ecc623..326a7bb 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -360,6 +360,10 @@ typedef struct ocontext {
 			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 */
@@ -396,6 +400,7 @@ typedef struct genfs {
 #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 */
@@ -406,7 +411,7 @@ typedef struct genfs {
 #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   8
+#define OCON_NUM   9
 
 /* section: module information */
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 5/9] libsepol: Add ibendport ocontext handling
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
                   ` (3 preceding siblings ...)
  2017-05-09 20:50 ` [PATCH 4/9] checkpolicy: Add support for ibendportcon labels Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  2017-05-10 19:09   ` Stephen Smalley
  2017-05-11 15:20   ` James Carter
  2017-05-09 20:50 ` [PATCH 6/9] libsepol: Add IB end port handling to CIL Dan Jurgens
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Add support for reading, writing, and copying IB end port ocontext data.
Also add support for querying a IB end port sid to checkpolicy.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 checkpolicy/checkpolicy.c                  |   20 ++++++++++++++
 libsepol/include/sepol/policydb/services.h |   10 +++++++
 libsepol/src/expand.c                      |    8 +++++
 libsepol/src/libsepol.map.in               |    1 +
 libsepol/src/module_to_cil.c               |   15 ++++++++++
 libsepol/src/policydb.c                    |   21 +++++++++++++-
 libsepol/src/services.c                    |   39 ++++++++++++++++++++++++++++
 libsepol/src/write.c                       |   14 ++++++++++
 8 files changed, 126 insertions(+), 2 deletions(-)

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 0f12347..72431d6 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -701,6 +701,7 @@ int main(int argc, char **argv)
 	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
@@ -1247,6 +1248,25 @@ int main(int argc, char **argv)
 				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(0, 0, name, port, &ssid);
+			printf("sid %d\n", ssid);
+			free(name);
+			break;
 #ifdef EQUIVTYPES
 		case 'z':
 			identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h b/libsepol/include/sepol/policydb/services.h
index 2d7aed1..aa8d718 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -199,6 +199,16 @@ extern int sepol_ibpkey_sid(uint16_t domain,
 			  sepol_security_id_t *out_sid);
 
 /*
+ * Return the SID of the ibendport specified by
+ * `domain', `type', `dev_name', and `port'.
+ */
+extern int sepol_ibendport_sid(uint16_t domain,
+			       uint16_t type,
+			       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/src/expand.c b/libsepol/src/expand.c
index c45ecbe..061945e 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -2226,6 +2226,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
 				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;
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index 36225d1..dd1fec2 100644
--- a/libsepol/src/libsepol.map.in
+++ b/libsepol/src/libsepol.map.in
@@ -7,6 +7,7 @@ LIBSEPOL_1.0 {
 	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/module_to_cil.c b/libsepol/src/module_to_cil.c
index db3f9c8..4b9f2c8 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -2585,6 +2585,7 @@ static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *i
 		"scmp_packet",
 		"devnull",
 		"ibpkey",
+		"ibendport",
 		NULL
 	};
 
@@ -2763,6 +2764,19 @@ exit:
 	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)
 {
@@ -2917,6 +2931,7 @@ static int ocontexts_to_cil(struct policydb *pdb)
 		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,
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 8b76c6a..6c9f2f9 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -198,7 +198,7 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .type = POLICY_KERN,
 	 .version = POLICYDB_VERSION_INFINIBAND,
 	 .sym_num = SYM_NUM,
-	 .ocon_num = OCON_IBPKEY + 1,
+	 .ocon_num = OCON_IBENDPORT + 1,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
@@ -303,7 +303,7 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .type = POLICY_BASE,
 	 .version = MOD_POLICYDB_VERSION_INFINIBAND,
 	 .sym_num = SYM_NUM,
-	 .ocon_num = OCON_IBPKEY + 1,
+	 .ocon_num = OCON_IBENDPORT + 1,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
@@ -2829,6 +2829,23 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
 				    (&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]);
+				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)
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 39903d1..d4a068a 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -1970,6 +1970,45 @@ out:
 }
 
 /*
+ * Return the SID of the subnet management interface specified by
+ * `domain', `type', `device name', and `port'.
+ */
+int hidden sepol_ibendport_sid(uint16_t domain __attribute__ ((unused)),
+			       uint16_t type __attribute__ ((unused)),
+			       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 &&
+		    !strncmp(dev_name, c->u.ibendport.dev_name, 64))
+			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 fa1b7d1..e3ff389 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -1426,6 +1426,20 @@ static int ocontext_write_selinux(struct policydb_compat_info *info,
 				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;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 6/9] libsepol: Add IB end port handling to CIL
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
                   ` (4 preceding siblings ...)
  2017-05-09 20:50 ` [PATCH 5/9] libsepol: Add ibendport ocontext handling Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  2017-05-11 15:07   ` James Carter
  2017-05-09 20:50 ` [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys Dan Jurgens
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Add IB end port parsing, symbol table management, and policy generation
to CIL.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 libsepol/cil/src/cil.c             |   18 ++++++++++
 libsepol/cil/src/cil_binary.c      |   29 ++++++++++++++++
 libsepol/cil/src/cil_binary.h      |   12 +++++++
 libsepol/cil/src/cil_build_ast.c   |   65 ++++++++++++++++++++++++++++++++++++
 libsepol/cil/src/cil_build_ast.h   |    2 +
 libsepol/cil/src/cil_copy_ast.c    |   25 ++++++++++++++
 libsepol/cil/src/cil_flavor.h      |    1 +
 libsepol/cil/src/cil_internal.h    |    9 +++++
 libsepol/cil/src/cil_policy.c      |   15 ++++++++
 libsepol/cil/src/cil_post.c        |   42 +++++++++++++++++++++++
 libsepol/cil/src/cil_post.h        |    1 +
 libsepol/cil/src/cil_reset_ast.c   |   10 +++++
 libsepol/cil/src/cil_resolve_ast.c |   28 +++++++++++++++
 libsepol/cil/src/cil_tree.c        |   13 +++++++
 libsepol/cil/src/cil_verify.c      |   23 +++++++++++++
 15 files changed, 293 insertions(+), 0 deletions(-)

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 6b51b8f..f3849ef 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -188,6 +188,7 @@ static void cil_init_keys(void)
 	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");
@@ -258,6 +259,7 @@ void cil_db_init(struct cil_db **db)
 	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);
@@ -310,6 +312,7 @@ void cil_db_destroy(struct cil_db **db)
 	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);
@@ -733,6 +736,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
 	case CIL_PORTCON:
 		cil_destroy_portcon(*data);
 		break;
+	case CIL_IBENDPORTCON:
+		cil_destroy_ibendportcon(*data);
+		break;
 	case CIL_NODECON:
 		cil_destroy_nodecon(*data);
 		break;
@@ -1099,6 +1105,8 @@ const char * cil_node_to_string(struct cil_tree_node *node)
 		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:
@@ -1832,6 +1840,16 @@ void cil_netifcon_init(struct cil_netifcon **netifcon)
 	(*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));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 75398ff..fb65698 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3323,6 +3323,30 @@ exit:
 	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;
@@ -3887,6 +3911,11 @@ int __cil_contexts_to_policydb(policydb_t *pdb, const struct cil_db *db)
 		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 a03d250..5367feb 100644
--- a/libsepol/cil/src/cil_binary.h
+++ b/libsepol/cil/src/cil_binary.h
@@ -342,6 +342,18 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st
 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 4ca88c1..ede19a2 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -4598,6 +4598,68 @@ void cil_destroy_netifcon(struct cil_netifcon *netifcon)
 	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 (!db || !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->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[] = {
@@ -6229,6 +6291,9 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
 	} 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 64da477..a31f6a4 100644
--- a/libsepol/cil/src/cil_build_ast.h
+++ b/libsepol/cil/src/cil_build_ast.h
@@ -175,6 +175,8 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru
 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 5c55983..665fe77 100644
--- a/libsepol/cil/src/cil_copy_ast.c
+++ b/libsepol/cil/src/cil_copy_ast.c
@@ -1204,6 +1204,28 @@ int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, __attribute__
 	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 +1938,9 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
 	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_flavor.h b/libsepol/cil/src/cil_flavor.h
index 242154d..04f4abd 100644
--- a/libsepol/cil/src/cil_flavor.h
+++ b/libsepol/cil/src/cil_flavor.h
@@ -113,6 +113,7 @@ enum cil_flavor {
 	CIL_MLS,
 	CIL_SRC_INFO,
 	CIL_IBPKEYCON,
+	CIL_IBENDPORTCON,
 
 /*
  *          boolean  constraint  set  catset
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index de2a8df..9d403f6 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -203,6 +203,7 @@ 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;
@@ -287,6 +288,7 @@ struct cil_db {
 	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;
@@ -780,6 +782,12 @@ struct cil_netifcon {
 	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;
@@ -965,6 +973,7 @@ int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_s
 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);
diff --git a/libsepol/cil/src/cil_policy.c b/libsepol/cil/src/cil_policy.c
index 35a0a29..2196ae8 100644
--- a/libsepol/cil/src/cil_policy.c
+++ b/libsepol/cil/src/cil_policy.c
@@ -1729,6 +1729,20 @@ static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int
 	}
 }
 
+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;
@@ -1958,6 +1972,7 @@ void cil_gen_policy(FILE *out, struct cil_db *db)
 	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 8b6608a..25ee90c 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -217,6 +217,25 @@ int cil_post_netifcon_compare(const void *a, const void *b)
 	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;
@@ -426,6 +445,9 @@ static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *fini
 	case CIL_IBPKEYCON:
 		db->ibpkeycon->count++;
 		break;
+	case CIL_IBENDPORTCON:
+		db->ibendportcon->count++;
+		break;
 	case CIL_PORTCON:
 		db->portcon->count++;
 		break;
@@ -516,6 +538,17 @@ static int __cil_post_db_array_helper(struct cil_tree_node *node, uint32_t *fini
 		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;
@@ -1654,6 +1687,14 @@ static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finish
 			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);
@@ -2014,6 +2055,7 @@ static int cil_post_db(struct cil_db *db)
 	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 fe7f3a5..3d54154 100644
--- a/libsepol/cil/src/cil_post.h
+++ b/libsepol/cil/src/cil_post.h
@@ -40,6 +40,7 @@ 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 d366ae3..ff67913 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -326,6 +326,13 @@ static void cil_reset_netifcon(struct cil_netifcon *netifcon)
 	}
 }
 
+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) {
@@ -498,6 +505,9 @@ int __cil_reset_node(struct cil_tree_node *node,  __attribute__((unused)) uint32
 	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 1df41da..69ce786 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -2038,6 +2038,31 @@ exit:
 	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;
@@ -3555,6 +3580,9 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
 		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;
diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
index 4703e5f..599f756 100644
--- a/libsepol/cil/src/cil_tree.c
+++ b/libsepol/cil/src/cil_tree.c
@@ -1495,6 +1495,19 @@ void cil_tree_print_node(struct cil_tree_node *node)
 			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 108da33..1036d73 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -1012,6 +1012,26 @@ exit:
 	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;
@@ -1475,6 +1495,9 @@ int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *ex
 		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;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
                   ` (5 preceding siblings ...)
  2017-05-09 20:50 ` [PATCH 6/9] libsepol: Add IB end port handling to CIL Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  2017-05-10 19:26   ` Stephen Smalley
  2017-05-09 20:50 ` [PATCH 8/9] semanage: Update semanage to allow runtime labeling of ibendports Dan Jurgens
  2017-05-09 20:50 ` [PATCH 9/9] semanage: Update man pages for infiniband Dan Jurgens
  8 siblings, 1 reply; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Update libsepol and libsemanage to work with pkey records. Add local
storage for new and modified pkey records in pkeys.local. Update semanage
to parse the pkey command options to add, modify, and delete pkeys.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 libsemanage/include/semanage/ibpkey_record.h  |   76 ++++
 libsemanage/include/semanage/ibpkeys_local.h  |   36 ++
 libsemanage/include/semanage/ibpkeys_policy.h |   28 ++
 libsemanage/include/semanage/semanage.h       |    3 +
 libsemanage/src/direct_api.c                  |   29 ++-
 libsemanage/src/handle.h                      |   36 ++-
 libsemanage/src/ibpkey_internal.h             |   52 +++
 libsemanage/src/ibpkey_record.c               |  187 ++++++++++
 libsemanage/src/ibpkeys_file.c                |  181 ++++++++++
 libsemanage/src/ibpkeys_local.c               |  182 ++++++++++
 libsemanage/src/ibpkeys_policy.c              |   52 +++
 libsemanage/src/ibpkeys_policydb.c            |   62 ++++
 libsemanage/src/libsemanage.map               |    1 +
 libsemanage/src/policy_components.c           |    5 +-
 libsemanage/src/semanage_store.c              |    1 +
 libsemanage/src/semanage_store.h              |    1 +
 libsemanage/src/semanageswig.i                |    3 +
 libsemanage/src/semanageswig_python.i         |   43 +++
 libsemanage/utils/semanage_migrate_store      |    3 +-
 libsepol/VERSION                              |    2 +-
 libsepol/include/sepol/ibpkey_record.h        |   75 ++++
 libsepol/include/sepol/ibpkeys.h              |   44 +++
 libsepol/include/sepol/sepol.h                |    2 +
 libsepol/src/ibpkey_internal.h                |   21 ++
 libsepol/src/ibpkey_record.c                  |  474 +++++++++++++++++++++++++
 libsepol/src/ibpkeys.c                        |  264 ++++++++++++++
 python/semanage/semanage                      |   60 +++-
 python/semanage/seobject.py                   |  253 +++++++++++++
 28 files changed, 2159 insertions(+), 17 deletions(-)
 create mode 100644 libsemanage/include/semanage/ibpkey_record.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_local.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_policy.h
 create mode 100644 libsemanage/src/ibpkey_internal.h
 create mode 100644 libsemanage/src/ibpkey_record.c
 create mode 100644 libsemanage/src/ibpkeys_file.c
 create mode 100644 libsemanage/src/ibpkeys_local.c
 create mode 100644 libsemanage/src/ibpkeys_policy.c
 create mode 100644 libsemanage/src/ibpkeys_policydb.c
 create mode 100644 libsepol/include/sepol/ibpkey_record.h
 create mode 100644 libsepol/include/sepol/ibpkeys.h
 create mode 100644 libsepol/src/ibpkey_internal.h
 create mode 100644 libsepol/src/ibpkey_record.c
 create mode 100644 libsepol/src/ibpkeys.c

diff --git a/libsemanage/include/semanage/ibpkey_record.h b/libsemanage/include/semanage/ibpkey_record.h
new file mode 100644
index 0000000..45fe59e
--- /dev/null
+++ b/libsemanage/include/semanage/ibpkey_record.h
@@ -0,0 +1,76 @@
+/* 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>
+
+#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 int semanage_ibpkey_get_subnet_prefix_bytes(semanage_handle_t *handle,
+						   const semanage_ibpkey_t *ibpkey,
+						   char **subnet_prefix,
+						   size_t *subnet_prefix_sz);
+
+extern int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle,
+					     semanage_ibpkey_t *ibpkey,
+					     const char *subnet_prefix);
+
+extern int semanage_ibpkey_set_subnet_prefix_bytes(semanage_handle_t *handle,
+						   semanage_ibpkey_t *ibpkey,
+						   const char *subnet_prefix,
+						   size_t subnet_prefix_sz);
+
+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..cebf3f4 100644
--- a/libsemanage/include/semanage/semanage.h
+++ b/libsemanage/include/semanage/semanage.h
@@ -33,6 +33,7 @@
 #include <semanage/context_record.h>
 #include <semanage/iface_record.h>
 #include <semanage/port_record.h>
+#include <semanage/ibpkey_record.h>
 #include <semanage/node_record.h>
 
 /* Dbase */
@@ -47,6 +48,8 @@
 #include <semanage/seusers_policy.h>
 #include <semanage/ports_local.h>
 #include <semanage/ports_policy.h>
+#include <semanage/ibpkeys_local.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/direct_api.c b/libsemanage/src/direct_api.c
index f4b0416..f190b0c 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -40,6 +40,7 @@
 #include "user_internal.h"
 #include "seuser_internal.h"
 #include "port_internal.h"
+#include "ibpkey_internal.h"
 #include "iface_internal.h"
 #include "boolean_internal.h"
 #include "fcontext_internal.h"
@@ -224,6 +225,14 @@ int semanage_direct_connect(semanage_handle_t * sh)
 				 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;
+
 	/* Object databases: local modifications + policy */
 	if (user_base_policydb_dbase_init(sh,
 					  semanage_user_base_dbase_policy(sh)) <
@@ -248,6 +257,9 @@ int semanage_direct_connect(semanage_handle_t * sh)
 	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 (iface_policydb_dbase_init(sh, semanage_iface_dbase_policy(sh)) < 0)
 		goto err;
 
@@ -320,6 +332,7 @@ static int semanage_direct_disconnect(semanage_handle_t * sh)
 	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));
 	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 +344,7 @@ static int semanage_direct_disconnect(semanage_handle_t * sh)
 	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));
 	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 +1158,15 @@ static int semanage_direct_commit(semanage_handle_t * sh)
 
 	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;
 	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 *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 +1180,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)
 
 	/* 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);
 	seusers_modified = seusers->dtable->is_modified(seusers->dbase);
 	fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase);
 
@@ -1285,7 +1302,7 @@ rebuild:
 	 * 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
 		bools->dtable->is_modified(bools->dbase) |
 		ifaces->dtable->is_modified(ifaces->dbase) |
 		nodes->dtable->is_modified(nodes->dbase) |
@@ -1431,6 +1448,7 @@ rebuild:
 	/* 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 *) pifaces->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pbools->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pnodes->dbase, out);
@@ -1479,6 +1497,12 @@ rebuild:
 			goto cleanup;
 	}
 
+	/* Validate local ibpkeys for overlap */
+	if (do_rebuild || ibpkeys_modified) {
+		retval = semanage_ibpkey_validate_local(sh);
+		if (retval < 0)
+			goto cleanup;
+	}
 	/* ================== Write non-policydb components ========= */
 
 	/* Commit changes to components */
@@ -1558,6 +1582,7 @@ cleanup:
 	/* 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 *) pifaces->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pnodes->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pbools->dbase);
diff --git a/libsemanage/src/handle.h b/libsemanage/src/handle.h
index 64175c4..306727a 100644
--- a/libsemanage/src/handle.h
+++ b/libsemanage/src/handle.h
@@ -79,7 +79,7 @@ struct semanage_handle {
 	struct semanage_policy_table *funcs;
 
 	/* Object databases */
-#define DBASE_COUNT      19
+#define DBASE_COUNT      21
 
 /* Local modifications */
 #define DBASE_LOCAL_USERS_BASE  0
@@ -91,20 +91,22 @@ struct semanage_handle {
 #define DBASE_LOCAL_FCONTEXTS	6
 #define DBASE_LOCAL_SEUSERS     7
 #define DBASE_LOCAL_NODES       8
+#define DBASE_LOCAL_IBPKEYS     9
 
 /* 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  10
+#define DBASE_POLICY_USERS_EXTRA 11
+#define DBASE_POLICY_USERS       12
+#define DBASE_POLICY_PORTS       13
+#define DBASE_POLICY_INTERFACES  14
+#define DBASE_POLICY_BOOLEANS    15
+#define DBASE_POLICY_FCONTEXTS   16
+#define DBASE_POLICY_SEUSERS     17
+#define DBASE_POLICY_NODES       18
+#define DBASE_POLICY_IBPKEYS     19
 
 /* Active kernel policy */
-#define DBASE_ACTIVE_BOOLEANS    18
+#define DBASE_ACTIVE_BOOLEANS    20
 	dbase_config_t dbase[DBASE_COUNT];
 };
 
@@ -134,6 +136,12 @@ static inline
 }
 
 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_iface_dbase_local(semanage_handle_t * handle)
 {
 	return &handle->dbase[DBASE_LOCAL_INTERFACES];
@@ -190,6 +198,12 @@ static inline
 }
 
 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_iface_dbase_policy(semanage_handle_t * handle)
 {
 	return &handle->dbase[DBASE_POLICY_INTERFACES];
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..d170c40
--- /dev/null
+++ b/libsemanage/src/ibpkey_record.c
@@ -0,0 +1,187 @@
+/* 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)
+
+int semanage_ibpkey_get_subnet_prefix_bytes(semanage_handle_t *handle,
+					    const semanage_ibpkey_t *ibpkey,
+					    char **subnet_prefix,
+					    size_t *subnet_prefix_sz)
+{
+	return sepol_ibpkey_get_subnet_prefix_bytes(handle->sepolh, ibpkey, subnet_prefix, subnet_prefix_sz);
+}
+
+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)
+
+int semanage_ibpkey_set_subnet_prefix_bytes(semanage_handle_t *handle,
+					    semanage_ibpkey_t *ibpkey,
+					    const char *subnet_prefix,
+					    size_t subnet_prefix_sz)
+{
+	return sepol_ibpkey_set_subnet_prefix_bytes(handle->sepolh, ibpkey, subnet_prefix, subnet_prefix_sz);
+}
+
+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..e016db0
--- /dev/null
+++ b/libsemanage/src/ibpkeys_local.c
@@ -0,0 +1,182 @@
+/* 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 "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;
+	char *subnet_prefix;
+	char *subnet_prefix2;
+	char *subnet_prefix_str;
+	char *subnet_prefix_str2;
+	int low, high;
+	int low2, high2;
+	size_t subnet_prefix_sz, subnet_prefix2_sz;
+
+	/* 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) {
+		int stop = 0;
+
+		if (STATUS_SUCCESS !=
+				semanage_ibpkey_get_subnet_prefix_bytes(handle,
+								      ibpkeys[i],
+								      &subnet_prefix,
+								      &subnet_prefix_sz)) {
+			ERR(handle, "Couldn't get subnet prefix");
+			goto err;
+		}
+		if (STATUS_SUCCESS != semanage_ibpkey_get_subnet_prefix(handle,
+								      ibpkeys[i],
+								      &subnet_prefix_str)) {
+			ERR(handle, "Couldn't get subnet prefix string");
+			goto err;
+		}
+
+		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_bytes(handle,
+								      ibpkeys[j],
+								      &subnet_prefix2,
+								      &subnet_prefix2_sz)) {
+				ERR(handle, "Couldn't get subnet prefix");
+				goto err;
+			}
+			if (STATUS_SUCCESS !=
+				semanage_ibpkey_get_subnet_prefix(handle,
+								ibpkeys[j],
+								&subnet_prefix_str2)) {
+				ERR(handle, "Couldn't get subnet prefix string");
+				goto err;
+			}
+			low2 = semanage_ibpkey_get_low(ibpkeys[j]);
+			high2 = semanage_ibpkey_get_high(ibpkeys[j]);
+
+			if (subnet_prefix_sz == subnet_prefix2_sz)
+				stop = !memcmp(subnet_prefix, subnet_prefix2, subnet_prefix_sz);
+		} while (!stop);
+
+		/* 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..041b1ce 100644
--- a/libsemanage/src/libsemanage.map
+++ b/libsemanage/src/libsemanage.map
@@ -18,6 +18,7 @@ LIBSEMANAGE_1.0 {
 	  semanage_root;
 	  semanage_user_*; semanage_bool_*; semanage_seuser_*;
 	  semanage_iface_*; semanage_port_*; semanage_context_*;
+	  semanage_ibpkey_*;
 	  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/policy_components.c b/libsemanage/src/policy_components.c
index d31bd48..136c5a7 100644
--- a/libsemanage/src/policy_components.c
+++ b/libsemanage/src/policy_components.c
@@ -137,12 +137,14 @@ int semanage_base_merge_components(semanage_handle_t * handle)
 
 		{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},
 	};
 	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 +220,7 @@ int semanage_commit_components(semanage_handle_t * handle)
 		semanage_seuser_dbase_policy(handle),
 		semanage_bool_dbase_active(handle),
 		semanage_node_dbase_local(handle),
+		semanage_ibpkey_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..f61f3b2 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -99,6 +99,7 @@ static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
 	"/homedir_template",
 	"/file_contexts.template",
 	"/commit_num",
+	"/pkeys.local",
 	"/ports.local",
 	"/interfaces.local",
 	"/nodes.local",
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index 0b96fbe..c7bcf44 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -44,6 +44,7 @@ enum semanage_sandbox_defs {
 	SEMANAGE_HOMEDIR_TMPL,
 	SEMANAGE_FC_TMPL,
 	SEMANAGE_COMMIT_NUM_FILE,
+	SEMANAGE_IBPKEYS_LOCAL,
 	SEMANAGE_PORTS_LOCAL,
 	SEMANAGE_INTERFACES_LOCAL,
 	SEMANAGE_NODES_LOCAL,
diff --git a/libsemanage/src/semanageswig.i b/libsemanage/src/semanageswig.i
index 583b7d8..d3ca795 100644
--- a/libsemanage/src/semanageswig.i
+++ b/libsemanage/src/semanageswig.i
@@ -39,6 +39,9 @@
 %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/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..40932d8 100644
--- a/libsemanage/src/semanageswig_python.i
+++ b/libsemanage/src/semanageswig_python.i
@@ -437,6 +437,49 @@
 	$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;
+}
+
 /** node typemaps **/
 
 /* the wrapper will setup this parameter for passing... the resulting python functions
diff --git a/libsemanage/utils/semanage_migrate_store b/libsemanage/utils/semanage_migrate_store
index 0ebd285..325de47 100755
--- a/libsemanage/utils/semanage_migrate_store
+++ b/libsemanage/utils/semanage_migrate_store
@@ -253,7 +253,8 @@ if __name__ == "__main__":
 		"preserve_tunables",
 		"policy.kern",
 		"file_contexts",
-		"homedir_template"]
+		"homedir_template",
+                "pkeys.local"]
 
 
 	create_dir(newroot_path(), 0o755)
diff --git a/libsepol/VERSION b/libsepol/VERSION
index 5154b3f..e70b452 100644
--- a/libsepol/VERSION
+++ b/libsepol/VERSION
@@ -1 +1 @@
-2.6
+2.6.0
diff --git a/libsepol/include/sepol/ibpkey_record.h b/libsepol/include/sepol/ibpkey_record.h
new file mode 100644
index 0000000..815582b
--- /dev/null
+++ b/libsepol/include/sepol/ibpkey_record.h
@@ -0,0 +1,75 @@
+#ifndef _SEPOL_IBPKEY_RECORD_H_
+#define _SEPOL_IBPKEY_RECORD_H_
+
+#include <stddef.h>
+#include <sepol/context_record.h>
+#include <sepol/handle.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+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,
+				  const char **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 int sepol_ibpkey_get_subnet_prefix_bytes(sepol_handle_t *handle,
+					      const sepol_ibpkey_t *ibpkey,
+					      char **buffer, size_t *bsize);
+
+extern int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
+			sepol_ibpkey_t *ibpkey, const char *subnet_prefix);
+
+extern int sepol_ibpkey_set_subnet_prefix_bytes(sepol_handle_t *handle,
+					      sepol_ibpkey_t *ibpkey,
+					      const char *subnet_prefix,
+					      size_t subnet_prefix_sz);
+
+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);
+
+__END_DECLS
+#endif
diff --git a/libsepol/include/sepol/ibpkeys.h b/libsepol/include/sepol/ibpkeys.h
new file mode 100644
index 0000000..4ab0a8a
--- /dev/null
+++ b/libsepol/include/sepol/ibpkeys.h
@@ -0,0 +1,44 @@
+#ifndef _SEPOL_IBPKEYS_H_
+#define _SEPOL_IBPKEYS_H_
+
+#include <sepol/handle.h>
+#include <sepol/policydb.h>
+#include <sepol/ibpkey_record.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/* 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);
+
+__END_DECLS
+#endif
diff --git a/libsepol/include/sepol/sepol.h b/libsepol/include/sepol/sepol.h
index 513f77d..540f01d 100644
--- a/libsepol/include/sepol/sepol.h
+++ b/libsepol/include/sepol/sepol.h
@@ -11,12 +11,14 @@ extern "C" {
 #include <sepol/user_record.h>
 #include <sepol/context_record.h>
 #include <sepol/iface_record.h>
+#include <sepol/ibpkey_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/ports.h>
 #include <sepol/nodes.h>
 #include <sepol/users.h>
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..6fd9116
--- /dev/null
+++ b/libsepol/src/ibpkey_record.c
@@ -0,0 +1,474 @@
+#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 */
+	char *subnet_prefix;
+	size_t subnet_prefix_sz;
+
+	/* Low - High range. Same for single ibpkeys. */
+	int low, high;
+
+	/* Context */
+	sepol_context_t *con;
+};
+
+struct sepol_ibpkey_key {
+	/* Subnet prefix */
+	char *subnet_prefix;
+	size_t subnet_prefix_sz;
+
+	/* 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,
+				      char *subnet_prefix_bytes)
+{
+	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;
+	}
+
+#ifdef DARWIN
+	memcpy(subnet_prefix_bytes, in_addr.s6_addr, 16);
+#else
+	memcpy(subnet_prefix_bytes, in_addr.s6_addr32, 16);
+#endif
+
+	return STATUS_SUCCESS;
+}
+
+static int ibpkey_alloc_subnet_prefix(sepol_handle_t *handle,
+				      char **subnet_prefix,
+				      size_t *subnet_prefix_sz)
+{
+	char *tmp_subnet_prefix = malloc(16);
+	size_t tmp_subnet_prefix_sz = 16;
+
+	if (!tmp_subnet_prefix)
+		goto omem;
+
+	*subnet_prefix = tmp_subnet_prefix;
+	*subnet_prefix_sz = tmp_subnet_prefix_sz;
+	return STATUS_SUCCESS;
+
+omem:
+	ERR(handle, "out of memory");
+	return STATUS_ERR;
+}
+
+/* Converts a numeric representation (subnet_prefix_bytes)
+ * to a string representation (subnet_prefix_str)
+ */
+
+static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle,
+				       char *subnet_prefix_bytes,
+				       char *subnet_prefix_str)
+{
+	struct in6_addr addr;
+
+	memset(&addr, 0, sizeof(struct in6_addr));
+#ifdef DARWIN
+	memcpy(&addr.s6_addr[0], subnet_prefix_bytes, 16);
+#else
+	memcpy(&addr.s6_addr32[0], subnet_prefix_bytes, 16);
+#endif
+	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_alloc_subnet_prefix(handle, &tmp_key->subnet_prefix, &tmp_key->subnet_prefix_sz) < 0)
+		goto err;
+	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,
+			     const char **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->subnet_prefix);
+	free(key);
+}
+
+int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key)
+{
+	int rc;
+
+	if (ibpkey->subnet_prefix_sz < key->subnet_prefix_sz)
+		return -1;
+	else if (ibpkey->subnet_prefix_sz > key->subnet_prefix_sz)
+		return 1;
+
+	rc = memcmp(ibpkey->subnet_prefix, key->subnet_prefix, ibpkey->subnet_prefix_sz);
+
+	if (ibpkey->low == key->low &&
+	    ibpkey->high == key->high &&
+	    !rc)
+		return 0;
+
+	if (ibpkey->low < key->low)
+		return -1;
+
+	else if (key->low < ibpkey->low)
+		return 1;
+
+	else if (ibpkey->high < key->high)
+		return -1;
+
+	else if (key->high < ibpkey->high)
+		return 1;
+	else
+		return rc;
+}
+
+int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2)
+{
+	int rc;
+
+	if (ibpkey->subnet_prefix_sz < ibpkey2->subnet_prefix_sz)
+		return -1;
+	else if (ibpkey->subnet_prefix_sz > ibpkey2->subnet_prefix_sz)
+		return 1;
+
+	rc = memcmp(ibpkey->subnet_prefix, ibpkey2->subnet_prefix, ibpkey->subnet_prefix_sz);
+
+	if (ibpkey->low == ibpkey2->low &&
+	    ibpkey->high == ibpkey2->high &&
+	    !rc)
+		return 0;
+
+	if (ibpkey->low < ibpkey2->low)
+		return -1;
+
+	else if (ibpkey2->low < ibpkey->low)
+		return 1;
+
+	else if (ibpkey->high < ibpkey2->high)
+		return -1;
+
+	else if (ibpkey2->high < ibpkey->high)
+		return 1;
+	else
+		return rc;
+}
+
+/* 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 */
+int sepol_ibpkey_get_subnet_prefix_bytes(sepol_handle_t *handle,
+					 const sepol_ibpkey_t *ibpkey,
+					 char **buffer, size_t *bsize)
+{
+	char *tmp_buf = malloc(ibpkey->subnet_prefix_sz);
+
+	if (!tmp_buf) {
+		ERR(handle, "out of memory, could not get subnet prefix bytes");
+		return STATUS_ERR;
+	}
+
+	memcpy(tmp_buf, ibpkey->subnet_prefix, ibpkey->subnet_prefix_sz);
+	*buffer = tmp_buf;
+	*bsize = ibpkey->subnet_prefix_sz;
+	return STATUS_SUCCESS;
+}
+
+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)
+{
+	char *tmp = NULL;
+	size_t tmp_sz;
+
+	if (ibpkey_alloc_subnet_prefix(handle, &tmp, &tmp_sz) < 0)
+		goto err;
+
+	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, tmp) < 0)
+		goto err;
+
+	free(ibpkey->subnet_prefix);
+	ibpkey->subnet_prefix = tmp;
+	ibpkey->subnet_prefix_sz = tmp_sz;
+	return STATUS_SUCCESS;
+
+err:
+	free(tmp);
+	ERR(handle, "could not set ibpkey subnet prefix to %s", subnet_prefix);
+	return STATUS_ERR;
+}
+
+hidden_def(sepol_ibpkey_set_subnet_prefix)
+
+int sepol_ibpkey_set_subnet_prefix_bytes(sepol_handle_t *handle,
+					 sepol_ibpkey_t *ibpkey,
+					 const char *subnet_prefix,
+					 size_t subnet_prefix_sz)
+{
+	char *tmp_subnet_prefix = malloc(subnet_prefix_sz);
+
+	if (!tmp_subnet_prefix) {
+		ERR(handle, "out of memory, could not set ibpkey subnet prefix");
+		return STATUS_ERR;
+	}
+
+	memcpy(tmp_subnet_prefix, subnet_prefix, subnet_prefix_sz);
+	free(ibpkey->subnet_prefix);
+	ibpkey->subnet_prefix = tmp_subnet_prefix;
+	ibpkey->subnet_prefix_sz = subnet_prefix_sz;
+	return STATUS_SUCCESS;
+}
+
+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 = NULL;
+	tmp_ibpkey->subnet_prefix_sz = 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 = malloc(ibpkey->subnet_prefix_sz);
+	if (!new_ibpkey->subnet_prefix)
+		goto omem;
+
+	memcpy(new_ibpkey->subnet_prefix, ibpkey->subnet_prefix, ibpkey->subnet_prefix_sz);
+	new_ibpkey->subnet_prefix_sz = ibpkey->subnet_prefix_sz;
+	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;
+
+omem:
+	ERR(handle, "out of memory");
+
+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;
+
+	free(ibpkey->subnet_prefix);
+	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..625ecfd
--- /dev/null
+++ b/libsepol/src/ibpkeys.c
@@ -0,0 +1,264 @@
+#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);
+	size_t subnet_prefix_bsize = 0;
+
+	tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey));
+	if (!tmp_ibpkey)
+		goto omem;
+
+	if (sepol_ibpkey_get_subnet_prefix_bytes(handle,
+					       data,
+					       &subnet_prefix_buf,
+					       &subnet_prefix_bsize) < 0)
+		goto err;
+
+	memcpy(tmp_ibpkey->u.ibpkey.subnet_prefix, subnet_prefix_buf, subnet_prefix_bsize);
+
+	free(subnet_prefix_buf);
+	subnet_prefix_buf = NULL;
+
+	/* 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)
+{
+	int low = ibpkey->u.ibpkey.low_pkey;
+	int high = ibpkey->u.ibpkey.high_pkey;
+	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;
+
+	if (sepol_ibpkey_set_subnet_prefix_bytes(handle, tmp_record,
+					       (const char *)&ibpkey->u.ibpkey.subnet_prefix, 16) < 0)
+		goto err;
+
+	sepol_ibpkey_set_range(tmp_record, low, high);
+
+	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;
+
+	handle = NULL;
+	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;
+	const char *subnet_prefix;
+
+	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
+
+	head = policydb->ocontexts[OCON_IBPKEY];
+	for (c = head; c; c = c->next) {
+		unsigned int *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 &&
+		    (!memcmp(subnet_prefix, subnet_prefix2, 16))) {
+			*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;
+	const char *subnet_prefix;
+
+	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
+
+	head = policydb->ocontexts[OCON_IBPKEY];
+	for (c = head; c; c = c->next) {
+		unsigned int *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 &&
+		    (!memcmp(subnet_prefix, subnet_prefix2, 16))) {
+			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: %s 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;
+	const char *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: %s 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/python/semanage/semanage b/python/semanage/semanage
index 9659aac..11b56e2 100644
--- a/python/semanage/semanage
+++ b/python/semanage/semanage
@@ -58,6 +58,9 @@ usage_user_dict = {' --add': ('(', '-L LEVEL', '-R ROLES', '-r RANGE', '-s SEUSE
 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_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 +148,9 @@ def port_ini():
     OBJECT = seobject.portRecords(store)
     return OBJECT
 
+def ibpkey_ini():
+    OBJECT = seobject.ibpkeyRecords(store)
+    return OBJECT
 
 def module_ini():
     OBJECT = seobject.moduleRecords(store)
@@ -181,7 +187,7 @@ def dontaudit_ini():
     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}
 
 
 def generate_custom_usage(usage_text, usage_dict):
@@ -292,6 +298,11 @@ def parser_add_proto(parser, name):
     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_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 +522,52 @@ def setupPortParser(subparsers):
     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 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 +906,7 @@ def createCommandParser():
     setupLoginParser(subparsers)
     setupUserParser(subparsers)
     setupPortParser(subparsers)
+    setupPkeyParser(subparsers)
     setupInterfaceParser(subparsers)
     setupModuleParser(subparsers)
     setupNodeParser(subparsers)
diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index 7a54373..02ad9f3 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -1309,6 +1309,259 @@ class portRecords(semanageRecords):
                 rec += ", %s" % p
             print(rec)
 
+class ibpkeyRecords(semanageRecords):
+    try:
+        valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "ibpkey_type"))[0]["types"])
+    except RuntimeError:
+        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_pkey_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 nodeRecords(semanageRecords):
     try:
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 8/9] semanage: Update semanage to allow runtime labeling of ibendports
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
                   ` (6 preceding siblings ...)
  2017-05-09 20:50 ` [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  2017-05-14 12:16   ` Jason Zaman
  2017-05-09 20:50 ` [PATCH 9/9] semanage: Update man pages for infiniband Dan Jurgens
  8 siblings, 1 reply; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Update libsepol and libsemanage to work with ibendport records. Add local
storage for new and modified ibendport records in ibendports.local.
Update semanage to parse the ibendport command options to add, modify,
and delete them.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 libsemanage/include/semanage/ibendport_record.h  |   62 +++++
 libsemanage/include/semanage/ibendports_local.h  |   36 +++
 libsemanage/include/semanage/ibendports_policy.h |   28 ++
 libsemanage/include/semanage/semanage.h          |    3 +
 libsemanage/src/direct_api.c                     |   42 +++-
 libsemanage/src/handle.h                         |   38 ++-
 libsemanage/src/ibendport_internal.h             |   48 ++++
 libsemanage/src/ibendport_record.c               |  154 +++++++++++
 libsemanage/src/ibendports_file.c                |  157 +++++++++++
 libsemanage/src/ibendports_local.c               |  153 +++++++++++
 libsemanage/src/ibendports_policy.c              |   55 ++++
 libsemanage/src/ibendports_policydb.c            |   62 +++++
 libsemanage/src/libsemanage.map                  |    1 +
 libsemanage/src/policy_components.c              |    4 +
 libsemanage/src/semanage_store.c                 |    1 +
 libsemanage/src/semanage_store.h                 |    1 +
 libsemanage/src/semanageswig.i                   |    3 +
 libsemanage/src/semanageswig_python.i            |   43 +++
 libsemanage/utils/semanage_migrate_store         |    3 +-
 libsepol/include/sepol/ibendport_record.h        |   68 +++++
 libsepol/include/sepol/ibendports.h              |   45 ++++
 libsepol/include/sepol/sepol.h                   |    2 +
 libsepol/src/ibendport_internal.h                |   20 ++
 libsepol/src/ibendport_record.c                  |  299 ++++++++++++++++++++++
 libsepol/src/ibendports.c                        |  255 ++++++++++++++++++
 python/semanage/semanage                         |   58 ++++-
 python/semanage/seobject.py                      |  238 +++++++++++++++++
 27 files changed, 1857 insertions(+), 22 deletions(-)
 create mode 100644 libsemanage/include/semanage/ibendport_record.h
 create mode 100644 libsemanage/include/semanage/ibendports_local.h
 create mode 100644 libsemanage/include/semanage/ibendports_policy.h
 create mode 100644 libsemanage/src/ibendport_internal.h
 create mode 100644 libsemanage/src/ibendport_record.c
 create mode 100644 libsemanage/src/ibendports_file.c
 create mode 100644 libsemanage/src/ibendports_local.c
 create mode 100644 libsemanage/src/ibendports_policy.c
 create mode 100644 libsemanage/src/ibendports_policydb.c
 create mode 100644 libsepol/include/sepol/ibendport_record.h
 create mode 100644 libsepol/include/sepol/ibendports.h
 create mode 100644 libsepol/src/ibendport_internal.h
 create mode 100644 libsepol/src/ibendport_record.c
 create mode 100644 libsepol/src/ibendports.c

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/semanage.h b/libsemanage/include/semanage/semanage.h
index cebf3f4..0489014 100644
--- a/libsemanage/include/semanage/semanage.h
+++ b/libsemanage/include/semanage/semanage.h
@@ -34,6 +34,7 @@
 #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 */
@@ -49,6 +50,8 @@
 #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>
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index f190b0c..68c1868 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -41,6 +41,7 @@
 #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"
@@ -226,11 +227,19 @@ int semanage_direct_connect(semanage_handle_t * sh)
 		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)
+				   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 */
@@ -260,6 +269,9 @@ int semanage_direct_connect(semanage_handle_t * sh)
 	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;
 
@@ -333,6 +345,7 @@ static int semanage_direct_disconnect(semanage_handle_t * 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));
@@ -345,6 +358,7 @@ static int semanage_direct_disconnect(semanage_handle_t * 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));
@@ -1158,7 +1172,8 @@ static int semanage_direct_commit(semanage_handle_t * sh)
 
 	int do_rebuild, do_write_kernel, do_install;
 	int fcontexts_modified, ports_modified, seusers_modified,
-		disable_dontaudit, preserve_tunables, ibpkeys_modified;
+		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);
@@ -1167,6 +1182,8 @@ static int semanage_direct_commit(semanage_handle_t * 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);
@@ -1181,6 +1198,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)
 	/* 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);
 
@@ -1302,7 +1320,8 @@ rebuild:
 	 * that live under /etc/selinux (kernel policy, seusers, file contexts)
 	 * will be modified.
 	 */
-	do_write_kernel = do_rebuild | ports_modified | ibpkeys_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) |
@@ -1449,6 +1468,7 @@ rebuild:
 	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);
@@ -1503,6 +1523,13 @@ rebuild:
 		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 */
@@ -1583,6 +1610,7 @@ cleanup:
 	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/handle.h b/libsemanage/src/handle.h
index 306727a..889871d 100644
--- a/libsemanage/src/handle.h
+++ b/libsemanage/src/handle.h
@@ -79,7 +79,7 @@ struct semanage_handle {
 	struct semanage_policy_table *funcs;
 
 	/* Object databases */
-#define DBASE_COUNT      21
+#define DBASE_COUNT      23
 
 /* Local modifications */
 #define DBASE_LOCAL_USERS_BASE  0
@@ -92,21 +92,23 @@ struct semanage_handle {
 #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  10
-#define DBASE_POLICY_USERS_EXTRA 11
-#define DBASE_POLICY_USERS       12
-#define DBASE_POLICY_PORTS       13
-#define DBASE_POLICY_INTERFACES  14
-#define DBASE_POLICY_BOOLEANS    15
-#define DBASE_POLICY_FCONTEXTS   16
-#define DBASE_POLICY_SEUSERS     17
-#define DBASE_POLICY_NODES       18
-#define DBASE_POLICY_IBPKEYS     19
+#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    20
+#define DBASE_ACTIVE_BOOLEANS    22
 	dbase_config_t dbase[DBASE_COUNT];
 };
 
@@ -142,6 +144,12 @@ static inline
 }
 
 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];
@@ -204,6 +212,12 @@ static inline
 }
 
 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/libsemanage.map b/libsemanage/src/libsemanage.map
index 041b1ce..0203669 100644
--- a/libsemanage/src/libsemanage.map
+++ b/libsemanage/src/libsemanage.map
@@ -19,6 +19,7 @@ LIBSEMANAGE_1.0 {
 	  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/policy_components.c b/libsemanage/src/policy_components.c
index 136c5a7..896ac51 100644
--- a/libsemanage/src/policy_components.c
+++ b/libsemanage/src/policy_components.c
@@ -140,6 +140,9 @@ int semanage_base_merge_components(semanage_handle_t * handle)
 
 		{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]);
 
@@ -221,6 +224,7 @@ int semanage_commit_components(semanage_handle_t * 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 f61f3b2..5642772 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -100,6 +100,7 @@ static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
 	"/file_contexts.template",
 	"/commit_num",
 	"/pkeys.local",
+	"/ibendports.local",
 	"/ports.local",
 	"/interfaces.local",
 	"/nodes.local",
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index c7bcf44..fcaa505 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -45,6 +45,7 @@ enum semanage_sandbox_defs {
 	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 d3ca795..ebf39cf 100644
--- a/libsemanage/src/semanageswig.i
+++ b/libsemanage/src/semanageswig.i
@@ -42,6 +42,9 @@
 %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 40932d8..8604b8a 100644
--- a/libsemanage/src/semanageswig_python.i
+++ b/libsemanage/src/semanageswig_python.i
@@ -480,6 +480,49 @@
 	$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/utils/semanage_migrate_store b/libsemanage/utils/semanage_migrate_store
index 325de47..9a9fac2 100755
--- a/libsemanage/utils/semanage_migrate_store
+++ b/libsemanage/utils/semanage_migrate_store
@@ -254,7 +254,8 @@ if __name__ == "__main__":
 		"policy.kern",
 		"file_contexts",
 		"homedir_template",
-                "pkeys.local"]
+                "pkeys.local",
+                "ibendports.local"]
 
 
 	create_dir(newroot_path(), 0o755)
diff --git a/libsepol/include/sepol/ibendport_record.h b/libsepol/include/sepol/ibendport_record.h
new file mode 100644
index 0000000..e30b252
--- /dev/null
+++ b/libsepol/include/sepol/ibendport_record.h
@@ -0,0 +1,68 @@
+#ifndef _SEPOL_IBENDPORT_RECORD_H_
+#define _SEPOL_IBENDPORT_RECORD_H_
+
+#include <stddef.h>
+#include <sepol/context_record.h>
+#include <sepol/handle.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+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);
+
+__END_DECLS
+#endif
diff --git a/libsepol/include/sepol/ibendports.h b/libsepol/include/sepol/ibendports.h
new file mode 100644
index 0000000..4a89e0c
--- /dev/null
+++ b/libsepol/include/sepol/ibendports.h
@@ -0,0 +1,45 @@
+#ifndef _SEPOL_IBENDPORTS_H_
+#define _SEPOL_IBENDPORTS_H_
+
+#include <sepol/handle.h>
+#include <sepol/policydb.h>
+#include <sepol/ibendport_record.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/* 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);
+
+__END_DECLS
+#endif
diff --git a/libsepol/include/sepol/sepol.h b/libsepol/include/sepol/sepol.h
index 540f01d..540609a 100644
--- a/libsepol/include/sepol/sepol.h
+++ b/libsepol/include/sepol/sepol.h
@@ -12,6 +12,7 @@ extern "C" {
 #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>
@@ -19,6 +20,7 @@ extern "C" {
 #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/ibendport_internal.h b/libsepol/src/ibendport_internal.h
new file mode 100644
index 0000000..6c3df93
--- /dev/null
+++ b/libsepol/src/ibendport_internal.h
@@ -0,0 +1,20 @@
+#ifndef _SEPOL_IBENDPORT_INTERNAL_H_
+#define _SEPOL_IBENDPORT_INTERNAL_H_
+
+#include <sepol/ibendport_record.h>
+#include <sepol/ibendports.h>
+#include "dso.h"
+
+#define IB_DEVICE_NAME_MAX 64
+
+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..3f302fe
--- /dev/null
+++ b/libsepol/src/ibendport_record.c
@@ -0,0 +1,299 @@
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include "ibendport_internal.h"
+#include "context_internal.h"
+#include "debug.h"
+
+#define IB_DEVICE_NAME_MAX 64
+
+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 = strncmp(ibendport->ibdev_name, key->ibdev_name, IB_DEVICE_NAME_MAX);
+
+	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 = strncmp(ibendport->ibdev_name, ibendport2->ibdev_name, IB_DEVICE_NAME_MAX);
+
+	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..636503b
--- /dev/null
+++ b/libsepol/src/ibendports.c
@@ -0,0 +1,255 @@
+#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;
+
+	handle = NULL;
+	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 &&
+		    (!strncmp(ibdev_name, ibdev_name2, IB_DEVICE_NAME_MAX))) {
+			*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 &&
+		    (!strncmp(ibdev_name, ibdev_name2, IB_DEVICE_NAME_MAX))) {
+			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/python/semanage/semanage b/python/semanage/semanage
index 11b56e2..313537c 100644
--- a/python/semanage/semanage
+++ b/python/semanage/semanage
@@ -61,6 +61,9 @@ usage_port_dict = {' --add': ('-t TYPE', '-p PROTOCOL', '-r RANGE', '(', 'port_n
 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': ('',)}
 
@@ -152,6 +155,10 @@ 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)
     return OBJECT
@@ -187,8 +194,7 @@ def dontaudit_ini():
     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, 'ibpkey': ibpkey_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
@@ -303,6 +309,10 @@ def parser_add_subnet_prefix(parser, name):
     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)
@@ -567,6 +577,49 @@ def setupPkeyParser(subparsers):
     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'), ('')]}
@@ -907,6 +960,7 @@ def createCommandParser():
     setupUserParser(subparsers)
     setupPortParser(subparsers)
     setupPkeyParser(subparsers)
+    setupIbendportParser(subparsers)
     setupInterfaceParser(subparsers)
     setupModuleParser(subparsers)
     setupNodeParser(subparsers)
diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index 02ad9f3..895becd 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -1563,6 +1563,244 @@ class ibpkeyRecords(semanageRecords):
                 rec += ", %s" % p
             print rec
 
+class ibendportRecords(semanageRecords):
+    try:
+        valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "ibendport_type"))[0]["types"])
+    except RuntimeError:
+        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:
         valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "node_type"))[0]["types"])
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 9/9] semanage: Update man pages for infiniband
  2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
                   ` (7 preceding siblings ...)
  2017-05-09 20:50 ` [PATCH 8/9] semanage: Update semanage to allow runtime labeling of ibendports Dan Jurgens
@ 2017-05-09 20:50 ` Dan Jurgens
  8 siblings, 0 replies; 28+ messages in thread
From: Dan Jurgens @ 2017-05-09 20:50 UTC (permalink / raw)
  To: selinux

From: Daniel Jurgens <danielj@mellanox.com>

Update the main man page and add specific pages for ibpkeys and
ibendports.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 python/semanage/semanage-ibendport.8 |   66 ++++++++++++++++++++++++++++++++++
 python/semanage/semanage-ibpkey.8    |   66 ++++++++++++++++++++++++++++++++++
 python/semanage/semanage.8           |   16 ++++++--
 3 files changed, 144 insertions(+), 4 deletions(-)
 create mode 100644 python/semanage/semanage-ibendport.8
 create mode 100644 python/semanage/semanage-ibpkey.8

diff --git a/python/semanage/semanage-ibendport.8 b/python/semanage/semanage-ibendport.8
new file mode 100644
index 0000000..c3753a2
--- /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 Walsh <dwalsh@redhat.com>
diff --git a/python/semanage/semanage-ibpkey.8 b/python/semanage/semanage-ibpkey.8
new file mode 100644
index 0000000..2da4f54
--- /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 Walsh <dwalsh@redhat.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 @@ Manage process type enforcement mode
 .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 @@ from policy sources.  This includes the mapping from Linux usernames
 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 @@ List help information
 .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>
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 1/9] checkpolicy: Add support for ibpkeycon labels
  2017-05-09 20:50 ` [PATCH 1/9] checkpolicy: Add support for ibpkeycon labels Dan Jurgens
@ 2017-05-10 18:22   ` Stephen Smalley
  2017-05-10 21:46     ` Daniel Jurgens
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Smalley @ 2017-05-10 18:22 UTC (permalink / raw)
  To: Dan Jurgens, selinux

On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Add checkpolicy support for scanning and parsing ibpkeycon labels.
> Also
> create a new ocontext for Infiniband Pkeys and define a new policydb
> version for infiniband support.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>  checkpolicy/policy_define.c                |  110
> ++++++++++++++++++++++++++++
>  checkpolicy/policy_define.h                |    1 +
>  checkpolicy/policy_parse.y                 |   15 ++++-
>  checkpolicy/policy_scan.l                  |    3 +
>  libsepol/include/sepol/policydb/policydb.h |   32 +++++---
>  5 files changed, 148 insertions(+), 13 deletions(-)
> 
> diff --git a/checkpolicy/policy_define.c
> b/checkpolicy/policy_define.c
> index 949ca71..6f92bc5 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.
> @@ -4975,6 +4976,115 @@ int define_port_context(unsigned int low,
> unsigned int high)
>  	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;
> +	}
> +
> +#ifdef DARWIN
> +	memcpy(&newc->u.ibpkey.subnet_prefix[0],
> &subnet_prefix.s6_addr[0],
> +	       sizeof(newc->u.ibpkey.subnet_prefix));
> +#else
> +	memcpy(&newc->u.ibpkey.subnet_prefix[0],
> &subnet_prefix.s6_addr32[0],
> +	       sizeof(newc->u.ibpkey.subnet_prefix));
> +#endif

We can just always use s6_addr instead of s6_addr32 and drop the
#ifdef.  Just pushed a commit to fix that elsewhere. Also we switched
from #ifdef DARWIN to __APPLE__ a while ago, but that won't matter once
you drop the #ifdef altogether.

> +
> +	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 &&
> +		    !memcmp(&c->u.ibpkey.subnet_prefix[0],
> +			    &newc->u.ibpkey.subnet_prefix[0],
> +			    sizeof(c->u.ibpkey.subnet_prefix))) {
> +			yyerror2("duplicate ibpkeycon entry for %d-
> %d ",
> +				 low, high);
> +			rc = -1;
> +			goto out;
> +		}
> +		if (low2 <= low && high2 >= high &&
> +		    !memcmp(&c->u.ibpkey.subnet_prefix[0],
> +			    &newc->u.ibpkey.subnet_prefix[0],
> +			    sizeof(c->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_netif_context(void)
>  {
>  	ocontext_t *newc, *c, *head;
> diff --git a/checkpolicy/policy_define.h
> b/checkpolicy/policy_define.h
> index 964baae..b019b1a 100644
> --- a/checkpolicy/policy_define.h
> +++ b/checkpolicy/policy_define.h
> @@ -43,6 +43,7 @@ int define_level(void);
>  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_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 3b6a2f8..f50eab1 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.
> @@ -134,6 +135,7 @@ typedef int (* require_func_t)(int pass);
>  %token TARGET
>  %token SAMEUSER
>  %token FSCON PORTCON NETIFCON NODECON 
> +%token IBPKEYCON
>  %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
>  %token FSUSEXATTR FSUSETASK FSUSETRANS
>  %token GENFSCON
> @@ -169,7 +171,7 @@ base_policy             : { if
> (define_policy(pass, 0) == -1) return -1; }
>  			  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
>  			;
>  classes			: class_def 
>  			| classes class_def
> @@ -708,6 +710,17 @@ port_context_def	: PORTCON identifier
> number security_context_def
>  			| 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_netif_contexts      : netif_contexts 
>                          |
>                          ;
> diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
> index 2f7f221..07352cb 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.
> @@ -181,6 +182,8 @@ INCOMP |
>  incomp				{ return(INCOMP);}
>  fscon |
>  FSCON                           { return(FSCON);}
> +ibpkeycon |
> +IBPKEYCON			{ return(IBPKEYCON);}
>  portcon |
>  PORTCON				{ return(PORTCON);}
>  netifcon |                     
> diff --git a/libsepol/include/sepol/policydb/policydb.h
> b/libsepol/include/sepol/policydb/policydb.h
> index 4336a3f..5ecc623 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
> @@ -354,6 +355,11 @@ typedef struct ocontext {
>  			uint32_t low_ioport;
>  			uint32_t high_ioport;
>  		} ioport;
> +		struct {
> +			uint32_t subnet_prefix[4];
> +			uint16_t low_pkey;
> +			uint16_t high_pkey;
> +		} ibpkey;
>  	} u;
>  	union {
>  		uint32_t sclass;	/* security class for genfs
> */
> @@ -382,14 +388,14 @@ typedef struct genfs {
>  #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 */
>  
>  /* object context array indices for Xen */
>  #define OCON_XEN_ISID  	    0    /* initial SIDs */
> @@ -400,7 +406,7 @@ typedef struct genfs {
>  #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   8
>  
>  /* section: module information */
>  
> @@ -722,10 +728,11 @@ extern int
> policydb_set_target_platform(policydb_t *p, int platform);
>  #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

This is Linux-specific too.

>  
>  /* 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
> @@ -743,10 +750,11 @@ extern int
> policydb_set_target_platform(policydb_t *p, int platform);
>  #define MOD_POLICYDB_VERSION_TUNABLE_SEP	14
>  #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_CONSTRAINT_NAMES	17
> +#define MOD_POLICYDB_VERSION_INFINIBAND		18
>  
>  #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

Hmmm...we never introduced a binary module version for xperms, since
the only user is presently Android and they don't use binary modules
and in general we'd like to get rid of binary modules altogether and
switch entirely to source modules (either .te modules with a te2cil
converter or cil modules).  But I guess you probably want to support
this in the interim for convenient usage within existing Fedora/RHEL
policies.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] libsepol: Add ibpkey ocontext handling
  2017-05-09 20:50 ` [PATCH 2/9] libsepol: Add ibpkey ocontext handling Dan Jurgens
@ 2017-05-10 18:55   ` Stephen Smalley
  2017-05-10 22:23     ` Daniel Jurgens
  2017-05-11 15:19   ` James Carter
  1 sibling, 1 reply; 28+ messages in thread
From: Stephen Smalley @ 2017-05-10 18:55 UTC (permalink / raw)
  To: Dan Jurgens, selinux

On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Add support for reading, writing, and copying Infinabinda Pkey 

s/Infinabinda/Infiniband/

> ocontext
> data. Also add support for querying a Pkey sid to checkpolicy.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>  checkpolicy/checkpolicy.c                  |   27 +++++++++++++
>  libsepol/include/sepol/policydb/services.h |   11 +++++
>  libsepol/src/expand.c                      |    9 ++++
>  libsepol/src/libsepol.map.in               |    1 +
>  libsepol/src/module_to_cil.c               |   39 ++++++++++++++++++
>  libsepol/src/policydb.c                    |   47
> ++++++++++++++++++++++
>  libsepol/src/services.c                    |   59
> ++++++++++++++++++++++++++++
>  libsepol/src/write.c                       |   16 +++++++
>  8 files changed, 209 insertions(+), 0 deletions(-)
> 
> diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
> index 534fc22..0f12347 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.co
> m>
> @@ -699,6 +700,7 @@ int main(int argc, char **argv)
>  	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");
>  #ifdef EQUIVTYPES
>  	printf("z)  Show equivalent types\n");
>  #endif
> @@ -1220,6 +1222,31 @@ int main(int argc, char **argv)
>  				    "\nNo validatetrans expressions
> found.\n");
>  			}
>  			break;
> +		case 'k':
> +			{
> +				char *p;
> +				int len;
> +				struct in6_addr addr6;
> +				unsigned int pkey;
> +
> +				printf("subnet prefix?  ");
> +				FGETS(ans, sizeof(ans), stdin);
> +				ans[strlen(ans) - 1] = 0;
> +				p = (char *)&addr6;
> +				len = sizeof(addr6);
> +
> +				if (inet_pton(AF_INET6, ans, p) < 1)
> {
> +					printf("error parsing subnet
> prefix\n");
> +					break;
> +				}
> +
> +				printf("pkey? ");
> +				FGETS(ans, sizeof(ans), stdin);
> +				pkey = atoi(ans);
> +				sepol_ibpkey_sid(0, 0, p, len, pkey,
> &ssid);
> +				printf("sid %d\n", ssid);
> +			}
> +			break;
>  #ifdef EQUIVTYPES
>  		case 'z':
>  			identify_equiv_types();
> diff --git a/libsepol/include/sepol/policydb/services.h
> b/libsepol/include/sepol/policydb/services.h
> index 9162149..2d7aed1 100644
> --- a/libsepol/include/sepol/policydb/services.h
> +++ b/libsepol/include/sepol/policydb/services.h
> @@ -188,6 +188,17 @@ extern int sepol_port_sid(uint16_t domain,
>  			  uint16_t port, sepol_security_id_t *
> out_sid);
>  
>  /*
> + * Return the SID of the ibpkey specified by
> + * `domain', `type', `subnet prefix', and `pkey'.
> + */

Can you explain why you are passing a (domain,type) pair to this
interface and why subnet_prefix is not fixed length as it is in
corresponding kernel interface (security_pkey_sid)?  Will these
arguments ever be used?  Could the length change in the future?

For that matter, and I guess I should have asked this on the kernel
patches, why are you storing and passing the subnet prefix as a
complete IPv6 address?  Is that just for the convenience of being able
to use inet_pton() and inet_ntop()?  Is this typical for handling of IB
subnet prefixes?  Seems a bit wasteful.

> +extern int sepol_ibpkey_sid(uint16_t domain,
> +			  uint16_t type,
> +			  void *subnet_prefix_p,
> +			  size_t splen,
> +			  uint16_t pkey,
> +			  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/src/expand.c b/libsepol/src/expand.c
> index 54bf781..c45ecbe 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
> @@ -2217,6 +2218,14 @@ static int
> ocontext_copy_selinux(expand_state_t *state)
>  					return -1;
>  				}
>  				break;
> +			case OCON_IBPKEY:
> +				n->u.ibpkey.subnet_prefix[0] = c-
> >u.ibpkey.subnet_prefix[0];
> +				n->u.ibpkey.subnet_prefix[1] = c-
> >u.ibpkey.subnet_prefix[1];
> +				n->u.ibpkey.subnet_prefix[2] = c-
> >u.ibpkey.subnet_prefix[2];
> +				n->u.ibpkey.subnet_prefix[3] = c-
> >u.ibpkey.subnet_prefix[3];
> +				n->u.ibpkey.low_pkey = c-
> >u.ibpkey.low_pkey;
> +				n->u.ibpkey.high_pkey = c-
> >u.ibpkey.high_pkey;
> +			break;
>  			case OCON_PORT:
>  				n->u.port.protocol = c-
> >u.port.protocol;
>  				n->u.port.low_port = c-
> >u.port.low_port;
> diff --git a/libsepol/src/libsepol.map.in
> b/libsepol/src/libsepol.map.in
> index 4042640..36225d1 100644
> --- a/libsepol/src/libsepol.map.in
> +++ b/libsepol/src/libsepol.map.in
> @@ -6,6 +6,7 @@ LIBSEPOL_1.0 {
>  	sepol_context_*; sepol_mls_*; sepol_check_context;
>  	sepol_iface_*; 
>  	sepol_port_*;
> +	sepol_ibpkey_*;
>  	sepol_node_*;
>  	sepol_user_*; sepol_genusers; sepol_set_delusers;
>  	sepol_msg_*; sepol_debug;
> diff --git a/libsepol/src/module_to_cil.c
> b/libsepol/src/module_to_cil.c
> index ac095c3..db3f9c8 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
> @@ -2583,6 +2584,7 @@ static int ocontext_selinux_isid_to_cil(struct
> policydb *pdb, struct ocontext *i
>  		"policy",
>  		"scmp_packet",
>  		"devnull",
> +		"ibpkey",

I thought we dropped the separate initial SID for it?

>  		NULL
>  	};
>  
> @@ -2645,6 +2647,42 @@ exit:
>  	return rc;
>  }
>  
> +static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb,
> +					struct ocontext *ibpkeycons)
> +{
> +	int rc = -1;
> +	struct ocontext *ibpkeycon;
> +	char subnet_prefix[INET6_ADDRSTRLEN];
> +	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;
> +
> +		if (inet_ntop(AF_INET6, &ibpkeycon-
> >u.ibpkey.subnet_prefix,
> +			      subnet_prefix, 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, low);
> +		else
> +			cil_printf("(ibpkeycon %s (%i %i) ",
> subnet_prefix, 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;
> @@ -2878,6 +2916,7 @@ static int ocontexts_to_cil(struct policydb
> *pdb)
>  		ocontext_selinux_node_to_cil,
>  		ocontext_selinux_fsuse_to_cil,
>  		ocontext_selinux_node6_to_cil,
> +		ocontext_selinux_ibpkey_to_cil,
>  	};
>  	static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb,
> struct ocontext *ocon) = {
>  		ocontext_xen_isid_to_cil,
> diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
> index 7093b29..8b76c6a 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
> @@ -185,6 +186,21 @@ static struct policydb_compat_info
> policydb_compat[] = {
>  	 .ocon_num = OCON_NODE6 + 1,
>  	 .target_platform = SEPOL_TARGET_SELINUX,
>  	},
> +
> +	{
> +	 .type = POLICY_KERN,
> +	 .version = POLICYDB_VERSION_XPERMS_IOCTL,
> +	 .sym_num = SYM_NUM,
> +	 .ocon_num = OCON_NODE6 + 1,
> +	 .target_platform = SEPOL_TARGET_SELINUX,
> +	},

This seems duplicated?

> +	{
> +	 .type = POLICY_KERN,
> +	 .version = POLICYDB_VERSION_INFINIBAND,
> +	 .sym_num = SYM_NUM,
> +	 .ocon_num = OCON_IBPKEY + 1,
> +	 .target_platform = SEPOL_TARGET_SELINUX,
> +	},
>  	{
>  	 .type = POLICY_BASE,
>  	 .version = MOD_POLICYDB_VERSION_BASE,
> @@ -284,6 +300,13 @@ static struct policydb_compat_info
> policydb_compat[] = {
>  	 .target_platform = SEPOL_TARGET_SELINUX,
>  	},
>  	{
> +	 .type = POLICY_BASE,
> +	 .version = MOD_POLICYDB_VERSION_INFINIBAND,
> +	 .sym_num = SYM_NUM,
> +	 .ocon_num = OCON_IBPKEY + 1,
> +	 .target_platform = SEPOL_TARGET_SELINUX,
> +	},
> +	{
>  	 .type = POLICY_MOD,
>  	 .version = MOD_POLICYDB_VERSION_BASE,
>  	 .sym_num = SYM_NUM,
> @@ -381,6 +404,13 @@ static struct policydb_compat_info
> policydb_compat[] = {
>  	 .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
> @@ -2782,6 +2812,23 @@ static int ocontext_read_selinux(struct
> policydb_compat_info *info,
>  				    (&c->context[1], p, fp))
>  					return -1;
>  				break;
> +			case OCON_IBPKEY:
> +				rc = next_entry(buf, fp,
> sizeof(uint32_t) * 6);
> +				if (rc < 0)
> +					return -1;
> +
> +				c->u.ibpkey.subnet_prefix[0] =
> buf[0];
> +				c->u.ibpkey.subnet_prefix[1] =
> buf[1];
> +				c->u.ibpkey.subnet_prefix[2] =
> buf[2];
> +				c->u.ibpkey.subnet_prefix[3] =
> buf[3];

Why load all the values rather than just confirming that [2] and [3]
are zero as in the kernel?

> +
> +				c->u.ibpkey.low_pkey =
> le32_to_cpu(buf[4]);
> +				c->u.ibpkey.high_pkey =
> le32_to_cpu(buf[5]);
> +
> +				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)
> diff --git a/libsepol/src/services.c b/libsepol/src/services.c
> index 03fb120..39903d1 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
> @@ -1910,6 +1911,64 @@ int hidden sepol_fs_sid(char *name,
>  	return rc;
>  }
>  
> +static int match_subnet_prefix(uint32_t *input, uint32_t
> *subnet_prefix)
> +{
> +	int i, fail = 0;
> +
> +	for (i = 0; i < 4; i++)
> +		if (subnet_prefix[i] != input[i]) {
> +			fail = 1;
> +			break;
> +		}
> +
> +	return !fail;
> +}
> +
> +/*
> + * Return the SID of the ibpkey specified by
> + * `domain', `type', `subnet prefix', and `pkey number'.
> + */
> +int hidden sepol_ibpkey_sid(uint16_t domain __attribute__
> ((unused)),
> +			  uint16_t type __attribute__ ((unused)),
> +			  void *subnet_prefix_p,
> +			  size_t splen,
> +			  uint16_t pkey, sepol_security_id_t
> *out_sid)
> +{
> +	ocontext_t *c;
> +	int rc = 0;
> +
> +	if (splen != sizeof(uint64_t)) {
> +		rc = -EINVAL;
> +		goto out;
> +	}
> +
> +	c = policydb->ocontexts[OCON_IBPKEY];
> +	while (c) {
> +		if (c->u.ibpkey.low_pkey <= pkey &&
> +		    c->u.ibpkey.high_pkey >= pkey &&
> +		    match_subnet_prefix(subnet_prefix_p,
> +					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 port specified by
>   * `domain', `type', `protocol', and `port'.
> diff --git a/libsepol/src/write.c b/libsepol/src/write.c
> index e75b9ab..fa1b7d1 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
> @@ -1410,6 +1411,21 @@ static int ocontext_write_selinux(struct
> policydb_compat_info *info,
>  				if (context_write(p, &c->context[1], 
> fp))
>  					return POLICYDB_ERROR;
>  				break;
> +			case OCON_IBPKEY:
> +				 /* The subnet prefix is in network
> order */
> +				for (j = 0; j < 4; j++)
> +					buf[j] = c-
> >u.ibpkey.subnet_prefix[j];
> +
> +				buf[4] = cpu_to_le32(c-
> >u.ibpkey.low_pkey);
> +				buf[5] = cpu_to_le32(c-
> >u.ibpkey.high_pkey);
> +
> +				items = put_entry(buf,
> sizeof(uint32_t), 6, fp);
> +				if (items != 6)
> +					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;

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 4/9] checkpolicy: Add support for ibendportcon labels
  2017-05-09 20:50 ` [PATCH 4/9] checkpolicy: Add support for ibendportcon labels Dan Jurgens
@ 2017-05-10 19:00   ` Stephen Smalley
  2017-05-10 22:27     ` Daniel Jurgens
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Smalley @ 2017-05-10 19:00 UTC (permalink / raw)
  To: Dan Jurgens, selinux

On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Add checkpolicy support for scanning and parsing ibendportcon labels.
> Also create a new ocontext for IB end ports.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>  checkpolicy/policy_define.c                |   70
> ++++++++++++++++++++++++++++
>  checkpolicy/policy_define.h                |    1 +
>  checkpolicy/policy_parse.y                 |   14 +++++-
>  checkpolicy/policy_scan.l                  |    2 +
>  libsepol/include/sepol/policydb/policydb.h |    7 ++-
>  5 files changed, 91 insertions(+), 3 deletions(-)
> 
> diff --git a/checkpolicy/policy_define.c
> b/checkpolicy/policy_define.c
> index 6f92bc5..2926f18 100644
> --- a/checkpolicy/policy_define.c
> +++ b/checkpolicy/policy_define.c
> @@ -5085,6 +5085,76 @@ out:
>  	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;
> +	}
> +
> +	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 subnet management interface
> device name.");
> +		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 &&
> +		    !strncmp(c->u.ibendport.dev_name,
> +			     newc->u.ibendport.dev_name,
> +			     64)) {
> +			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 b019b1a..3282aed 100644
> --- a/checkpolicy/policy_define.h
> +++ b/checkpolicy/policy_define.h
> @@ -44,6 +44,7 @@ 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 f50eab1..35b7a33 100644
> --- a/checkpolicy/policy_parse.y
> +++ b/checkpolicy/policy_parse.y
> @@ -136,6 +136,7 @@ typedef int (* require_func_t)(int pass);
>  %token SAMEUSER
>  %token FSCON PORTCON NETIFCON NODECON 
>  %token IBPKEYCON
> +%token IBENDPORTCON
>  %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
>  %token FSUSEXATTR FSUSETASK FSUSETRANS
>  %token GENFSCON
> @@ -171,7 +172,7 @@ base_policy             : { if
> (define_policy(pass, 0) == -1) return -1; }
>  			  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
> opt_ibpkey_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
> @@ -697,7 +698,7 @@ fs_contexts		: fs_context_def
>  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
>                          |
> @@ -721,6 +722,15 @@ ibpkey_context_def	: IBPKEYCON ipv6_addr
> number security_context_def
>  			| 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 07352cb..f38dd22 100644
> --- a/checkpolicy/policy_scan.l
> +++ b/checkpolicy/policy_scan.l
> @@ -184,6 +184,8 @@ fscon |
>  FSCON                           { return(FSCON);}
>  ibpkeycon |
>  IBPKEYCON			{ return(IBPKEYCON);}
> +ibendportcon |
> +IBENDPORTCON			{ return(IBENDPORTCON);}
>  portcon |
>  PORTCON				{ return(PORTCON);}
>  netifcon |                     
> diff --git a/libsepol/include/sepol/policydb/policydb.h
> b/libsepol/include/sepol/policydb/policydb.h
> index 5ecc623..326a7bb 100644
> --- a/libsepol/include/sepol/policydb/policydb.h
> +++ b/libsepol/include/sepol/policydb/policydb.h
> @@ -360,6 +360,10 @@ typedef struct ocontext {
>  			uint16_t low_pkey;
>  			uint16_t high_pkey;
>  		} ibpkey;
> +		struct {
> +			char *dev_name;
> +			uint8_t port;
> +		} ibendport;

These were pkey and ib_endport in the kernel patch, and port was
port_num.  Either way is fine but they probably ought to be consistent.

>  	} u;
>  	union {
>  		uint32_t sclass;	/* security class for genfs
> */
> @@ -396,6 +400,7 @@ typedef struct genfs {
>  #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 */

These were OCON_PKEY and OCON_IB_ENDPORT in the last kernel patches I
saw.  Ok either way but they probably ought to be consistent.

>  
>  /* object context array indices for Xen */
>  #define OCON_XEN_ISID  	    0    /* initial SIDs */
> @@ -406,7 +411,7 @@ typedef struct genfs {
>  #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   8
> +#define OCON_NUM   9
>  
>  /* section: module information */
>  

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 5/9] libsepol: Add ibendport ocontext handling
  2017-05-09 20:50 ` [PATCH 5/9] libsepol: Add ibendport ocontext handling Dan Jurgens
@ 2017-05-10 19:09   ` Stephen Smalley
  2017-05-11 16:13     ` Daniel Jurgens
  2017-05-11 15:20   ` James Carter
  1 sibling, 1 reply; 28+ messages in thread
From: Stephen Smalley @ 2017-05-10 19:09 UTC (permalink / raw)
  To: Dan Jurgens, selinux

On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Add support for reading, writing, and copying IB end port ocontext
> data.
> Also add support for querying a IB end port sid to checkpolicy.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>  checkpolicy/checkpolicy.c                  |   20 ++++++++++++++
>  libsepol/include/sepol/policydb/services.h |   10 +++++++
>  libsepol/src/expand.c                      |    8 +++++
>  libsepol/src/libsepol.map.in               |    1 +
>  libsepol/src/module_to_cil.c               |   15 ++++++++++
>  libsepol/src/policydb.c                    |   21 +++++++++++++-
>  libsepol/src/services.c                    |   39
> ++++++++++++++++++++++++++++
>  libsepol/src/write.c                       |   14 ++++++++++
>  8 files changed, 126 insertions(+), 2 deletions(-)
> 
> diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
> index 0f12347..72431d6 100644
> --- a/checkpolicy/checkpolicy.c
> +++ b/checkpolicy/checkpolicy.c
> @@ -701,6 +701,7 @@ int main(int argc, char **argv)
>  	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
> @@ -1247,6 +1248,25 @@ int main(int argc, char **argv)
>  				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(0, 0, name, port,
> &ssid);
> +			printf("sid %d\n", ssid);
> +			free(name);
> +			break;
>  #ifdef EQUIVTYPES
>  		case 'z':
>  			identify_equiv_types();
> diff --git a/libsepol/include/sepol/policydb/services.h
> b/libsepol/include/sepol/policydb/services.h
> index 2d7aed1..aa8d718 100644
> --- a/libsepol/include/sepol/policydb/services.h
> +++ b/libsepol/include/sepol/policydb/services.h
> @@ -199,6 +199,16 @@ extern int sepol_ibpkey_sid(uint16_t domain,
>  			  sepol_security_id_t *out_sid);
>  
>  /*
> + * Return the SID of the ibendport specified by
> + * `domain', `type', `dev_name', and `port'.
> + */
> +extern int sepol_ibendport_sid(uint16_t domain,
> +			       uint16_t type,
> +			       char *dev_name,
> +			       uint8_t port,
> +			       sepol_security_id_t *out_sid);

Why (domain, type) arguments?

> +
> +/*
>   * 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/src/expand.c b/libsepol/src/expand.c
> index c45ecbe..061945e 100644
> --- a/libsepol/src/expand.c
> +++ b/libsepol/src/expand.c
> @@ -2226,6 +2226,14 @@ static int
> ocontext_copy_selinux(expand_state_t *state)
>  				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;
> diff --git a/libsepol/src/libsepol.map.in
> b/libsepol/src/libsepol.map.in
> index 36225d1..dd1fec2 100644
> --- a/libsepol/src/libsepol.map.in
> +++ b/libsepol/src/libsepol.map.in
> @@ -7,6 +7,7 @@ LIBSEPOL_1.0 {
>  	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/module_to_cil.c
> b/libsepol/src/module_to_cil.c
> index db3f9c8..4b9f2c8 100644
> --- a/libsepol/src/module_to_cil.c
> +++ b/libsepol/src/module_to_cil.c
> @@ -2585,6 +2585,7 @@ static int ocontext_selinux_isid_to_cil(struct
> policydb *pdb, struct ocontext *i
>  		"scmp_packet",
>  		"devnull",
>  		"ibpkey",
> +		"ibendport",

No new initial SIDs.

>  		NULL
>  	};
>  
> @@ -2763,6 +2764,19 @@ exit:
>  	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)
>  {
> @@ -2917,6 +2931,7 @@ static int ocontexts_to_cil(struct policydb
> *pdb)
>  		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,
> diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
> index 8b76c6a..6c9f2f9 100644
> --- a/libsepol/src/policydb.c
> +++ b/libsepol/src/policydb.c
> @@ -198,7 +198,7 @@ static struct policydb_compat_info
> policydb_compat[] = {
>  	 .type = POLICY_KERN,
>  	 .version = POLICYDB_VERSION_INFINIBAND,
>  	 .sym_num = SYM_NUM,
> -	 .ocon_num = OCON_IBPKEY + 1,
> +	 .ocon_num = OCON_IBENDPORT + 1,
>  	 .target_platform = SEPOL_TARGET_SELINUX,
>  	},
>  	{
> @@ -303,7 +303,7 @@ static struct policydb_compat_info
> policydb_compat[] = {
>  	 .type = POLICY_BASE,
>  	 .version = MOD_POLICYDB_VERSION_INFINIBAND,
>  	 .sym_num = SYM_NUM,
> -	 .ocon_num = OCON_IBPKEY + 1,
> +	 .ocon_num = OCON_IBENDPORT + 1,
>  	 .target_platform = SEPOL_TARGET_SELINUX,
>  	},
>  	{
> @@ -2829,6 +2829,23 @@ static int ocontext_read_selinux(struct
> policydb_compat_info *info,
>  				    (&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 (zero_or_saturated(len))
	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)
> diff --git a/libsepol/src/services.c b/libsepol/src/services.c
> index 39903d1..d4a068a 100644
> --- a/libsepol/src/services.c
> +++ b/libsepol/src/services.c
> @@ -1970,6 +1970,45 @@ out:
>  }
>  
>  /*
> + * Return the SID of the subnet management interface specified by
> + * `domain', `type', `device name', and `port'.
> + */
> +int hidden sepol_ibendport_sid(uint16_t domain __attribute__
> ((unused)),
> +			       uint16_t type __attribute__
> ((unused)),
> +			       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 &&
> +		    !strncmp(dev_name, c->u.ibendport.dev_name, 64))
> +			break;

Do you ensure that dev_name cannot be > 64 bytes in checkpolicy and in
ocontext_read_selinux()?  And do we really want strncmp() here rather
than just strcmp()?  What's the advantage?


> +		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 fa1b7d1..e3ff389 100644
> --- a/libsepol/src/write.c
> +++ b/libsepol/src/write.c
> @@ -1426,6 +1426,20 @@ static int ocontext_write_selinux(struct
> policydb_compat_info *info,
>  				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;

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys
  2017-05-09 20:50 ` [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys Dan Jurgens
@ 2017-05-10 19:26   ` Stephen Smalley
  2017-05-11 22:51     ` Daniel Jurgens
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Smalley @ 2017-05-10 19:26 UTC (permalink / raw)
  To: Dan Jurgens, selinux

On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Update libsepol and libsemanage to work with pkey records. Add local
> storage for new and modified pkey records in pkeys.local. Update
> semanage
> to parse the pkey command options to add, modify, and delete pkeys.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>  libsemanage/include/semanage/ibpkey_record.h  |   76 ++++
>  libsemanage/include/semanage/ibpkeys_local.h  |   36 ++
>  libsemanage/include/semanage/ibpkeys_policy.h |   28 ++
>  libsemanage/include/semanage/semanage.h       |    3 +
>  libsemanage/src/direct_api.c                  |   29 ++-
>  libsemanage/src/handle.h                      |   36 ++-
>  libsemanage/src/ibpkey_internal.h             |   52 +++
>  libsemanage/src/ibpkey_record.c               |  187 ++++++++++
>  libsemanage/src/ibpkeys_file.c                |  181 ++++++++++
>  libsemanage/src/ibpkeys_local.c               |  182 ++++++++++
>  libsemanage/src/ibpkeys_policy.c              |   52 +++
>  libsemanage/src/ibpkeys_policydb.c            |   62 ++++
>  libsemanage/src/libsemanage.map               |    1 +
>  libsemanage/src/policy_components.c           |    5 +-
>  libsemanage/src/semanage_store.c              |    1 +
>  libsemanage/src/semanage_store.h              |    1 +
>  libsemanage/src/semanageswig.i                |    3 +
>  libsemanage/src/semanageswig_python.i         |   43 +++
>  libsemanage/utils/semanage_migrate_store      |    3 +-
>  libsepol/VERSION                              |    2 +-
>  libsepol/include/sepol/ibpkey_record.h        |   75 ++++
>  libsepol/include/sepol/ibpkeys.h              |   44 +++
>  libsepol/include/sepol/sepol.h                |    2 +
>  libsepol/src/ibpkey_internal.h                |   21 ++
>  libsepol/src/ibpkey_record.c                  |  474
> +++++++++++++++++++++++++
>  libsepol/src/ibpkeys.c                        |  264 ++++++++++++++
>  python/semanage/semanage                      |   60 +++-
>  python/semanage/seobject.py                   |  253 +++++++++++++
>  28 files changed, 2159 insertions(+), 17 deletions(-)

That's a lot of code.  Did you look at whether you could generalize the
port record stuff at all to see if we could factor out common helpers
or anything?  I guess this is consistent with the current code, but it
seems like a lot of very similar code being duplicated and then
slightly tweaked.

>  create mode 100644 libsemanage/include/semanage/ibpkey_record.h
>  create mode 100644 libsemanage/include/semanage/ibpkeys_local.h
>  create mode 100644 libsemanage/include/semanage/ibpkeys_policy.h
>  create mode 100644 libsemanage/src/ibpkey_internal.h
>  create mode 100644 libsemanage/src/ibpkey_record.c
>  create mode 100644 libsemanage/src/ibpkeys_file.c
>  create mode 100644 libsemanage/src/ibpkeys_local.c
>  create mode 100644 libsemanage/src/ibpkeys_policy.c
>  create mode 100644 libsemanage/src/ibpkeys_policydb.c
>  create mode 100644 libsepol/include/sepol/ibpkey_record.h
>  create mode 100644 libsepol/include/sepol/ibpkeys.h
>  create mode 100644 libsepol/src/ibpkey_internal.h
>  create mode 100644 libsepol/src/ibpkey_record.c
>  create mode 100644 libsepol/src/ibpkeys.c
> 
> diff --git a/libsemanage/include/semanage/ibpkey_record.h
> b/libsemanage/include/semanage/ibpkey_record.h
> new file mode 100644
> index 0000000..45fe59e
> --- /dev/null
> +++ b/libsemanage/include/semanage/ibpkey_record.h
> @@ -0,0 +1,76 @@
> +/* 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>
> +
> +#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 int semanage_ibpkey_get_subnet_prefix_bytes(semanage_handle_t
> *handle,
> +						   const
> semanage_ibpkey_t *ibpkey,
> +						   char
> **subnet_prefix,
> +						   size_t
> *subnet_prefix_sz);
> +
> +extern int semanage_ibpkey_set_subnet_prefix(semanage_handle_t
> *handle,
> +					     semanage_ibpkey_t
> *ibpkey,
> +					     const char
> *subnet_prefix);
> +
> +extern int semanage_ibpkey_set_subnet_prefix_bytes(semanage_handle_t
> *handle,
> +						   semanage_ibpkey_t
> *ibpkey,
> +						   const char
> *subnet_prefix,
> +						   size_t
> subnet_prefix_sz);
> +
> +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..cebf3f4 100644
> --- a/libsemanage/include/semanage/semanage.h
> +++ b/libsemanage/include/semanage/semanage.h
> @@ -33,6 +33,7 @@
>  #include <semanage/context_record.h>
>  #include <semanage/iface_record.h>
>  #include <semanage/port_record.h>
> +#include <semanage/ibpkey_record.h>
>  #include <semanage/node_record.h>
>  
>  /* Dbase */
> @@ -47,6 +48,8 @@
>  #include <semanage/seusers_policy.h>
>  #include <semanage/ports_local.h>
>  #include <semanage/ports_policy.h>
> +#include <semanage/ibpkeys_local.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/direct_api.c
> b/libsemanage/src/direct_api.c
> index f4b0416..f190b0c 100644
> --- a/libsemanage/src/direct_api.c
> +++ b/libsemanage/src/direct_api.c
> @@ -40,6 +40,7 @@
>  #include "user_internal.h"
>  #include "seuser_internal.h"
>  #include "port_internal.h"
> +#include "ibpkey_internal.h"
>  #include "iface_internal.h"
>  #include "boolean_internal.h"
>  #include "fcontext_internal.h"
> @@ -224,6 +225,14 @@ int semanage_direct_connect(semanage_handle_t *
> sh)
>  				 semanage_node_dbase_local(sh)) < 0)
>  		goto err;
>  
> +	if (ibpkey_file_dbase_init(sh,
> +				 semanage_path(SEMANAGE_ACTIVE,
> +					       SEMANAGE_IBPKEYS_LOCA
> L),
> +				 semanage_path(SEMANAGE_TMP,
> +					       SEMANAGE_IBPKEYS_LOCA
> L),
> +				 semanage_ibpkey_dbase_local(sh)) <
> 0)
> +		goto err;
> +
>  	/* Object databases: local modifications + policy */
>  	if (user_base_policydb_dbase_init(sh,
>  					  semanage_user_base_dbase_p
> olicy(sh)) <
> @@ -248,6 +257,9 @@ int semanage_direct_connect(semanage_handle_t *
> sh)
>  	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 (iface_policydb_dbase_init(sh,
> semanage_iface_dbase_policy(sh)) < 0)
>  		goto err;
>  
> @@ -320,6 +332,7 @@ static int
> semanage_direct_disconnect(semanage_handle_t * sh)
>  	user_extra_file_dbase_release(semanage_user_extra_dbase_loca
> l(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));
>  	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 +344,7 @@ static int
> semanage_direct_disconnect(semanage_handle_t * sh)
>  	user_extra_file_dbase_release(semanage_user_extra_dbase_poli
> cy(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(s
> h));
>  	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(s
> h));
> @@ -1144,13 +1158,15 @@ static int
> semanage_direct_commit(semanage_handle_t * sh)
>  
>  	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;
>  	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 *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 +1180,7 @@ static int
> semanage_direct_commit(semanage_handle_t * sh)
>  
>  	/* 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);
>  	seusers_modified = seusers->dtable->is_modified(seusers-
> >dbase);
>  	fcontexts_modified = fcontexts->dtable-
> >is_modified(fcontexts->dbase);
>  
> @@ -1285,7 +1302,7 @@ rebuild:
>  	 * 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
>  		bools->dtable->is_modified(bools->dbase) |
>  		ifaces->dtable->is_modified(ifaces->dbase) |
>  		nodes->dtable->is_modified(nodes->dbase) |
> @@ -1431,6 +1448,7 @@ rebuild:
>  	/* 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 *) pifaces->dbase,
> out);
>  	dbase_policydb_attach((dbase_policydb_t *) pbools->dbase,
> out);
>  	dbase_policydb_attach((dbase_policydb_t *) pnodes->dbase,
> out);
> @@ -1479,6 +1497,12 @@ rebuild:
>  			goto cleanup;
>  	}
>  
> +	/* Validate local ibpkeys for overlap */
> +	if (do_rebuild || ibpkeys_modified) {
> +		retval = semanage_ibpkey_validate_local(sh);
> +		if (retval < 0)
> +			goto cleanup;
> +	}
>  	/* ================== Write non-policydb components
> ========= */
>  
>  	/* Commit changes to components */
> @@ -1558,6 +1582,7 @@ cleanup:
>  	/* 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 *) pifaces->dbase);
>  	dbase_policydb_detach((dbase_policydb_t *) pnodes->dbase);
>  	dbase_policydb_detach((dbase_policydb_t *) pbools->dbase);
> diff --git a/libsemanage/src/handle.h b/libsemanage/src/handle.h
> index 64175c4..306727a 100644
> --- a/libsemanage/src/handle.h
> +++ b/libsemanage/src/handle.h
> @@ -79,7 +79,7 @@ struct semanage_handle {
>  	struct semanage_policy_table *funcs;
>  
>  	/* Object databases */
> -#define DBASE_COUNT      19
> +#define DBASE_COUNT      21
>  
>  /* Local modifications */
>  #define DBASE_LOCAL_USERS_BASE  0
> @@ -91,20 +91,22 @@ struct semanage_handle {
>  #define DBASE_LOCAL_FCONTEXTS	6
>  #define DBASE_LOCAL_SEUSERS     7
>  #define DBASE_LOCAL_NODES       8
> +#define DBASE_LOCAL_IBPKEYS     9
>  
>  /* 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  10
> +#define DBASE_POLICY_USERS_EXTRA 11
> +#define DBASE_POLICY_USERS       12
> +#define DBASE_POLICY_PORTS       13
> +#define DBASE_POLICY_INTERFACES  14
> +#define DBASE_POLICY_BOOLEANS    15
> +#define DBASE_POLICY_FCONTEXTS   16
> +#define DBASE_POLICY_SEUSERS     17
> +#define DBASE_POLICY_NODES       18
> +#define DBASE_POLICY_IBPKEYS     19
>  
>  /* Active kernel policy */
> -#define DBASE_ACTIVE_BOOLEANS    18
> +#define DBASE_ACTIVE_BOOLEANS    20
>  	dbase_config_t dbase[DBASE_COUNT];
>  };
>  
> @@ -134,6 +136,12 @@ static inline
>  }
>  
>  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_iface_dbase_local(semanage_handle_t *
> handle)
>  {
>  	return &handle->dbase[DBASE_LOCAL_INTERFACES];
> @@ -190,6 +198,12 @@ static inline
>  }
>  
>  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_iface_dbase_policy(semanage_handle_t *
> handle)
>  {
>  	return &handle->dbase[DBASE_POLICY_INTERFACES];
> 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..d170c40
> --- /dev/null
> +++ b/libsemanage/src/ibpkey_record.c
> @@ -0,0 +1,187 @@
> +/* 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)
> +
> +int semanage_ibpkey_get_subnet_prefix_bytes(semanage_handle_t
> *handle,
> +					    const semanage_ibpkey_t
> *ibpkey,
> +					    char **subnet_prefix,
> +					    size_t
> *subnet_prefix_sz)
> +{
> +	return sepol_ibpkey_get_subnet_prefix_bytes(handle->sepolh,
> ibpkey, subnet_prefix, subnet_prefix_sz);
> +}
> +
> +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)
> +
> +int semanage_ibpkey_set_subnet_prefix_bytes(semanage_handle_t
> *handle,
> +					    semanage_ibpkey_t
> *ibpkey,
> +					    const char
> *subnet_prefix,
> +					    size_t subnet_prefix_sz)
> +{
> +	return sepol_ibpkey_set_subnet_prefix_bytes(handle->sepolh,
> ibpkey, subnet_prefix, subnet_prefix_sz);
> +}
> +
> +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..e016db0
> --- /dev/null
> +++ b/libsemanage/src/ibpkeys_local.c
> @@ -0,0 +1,182 @@
> +/* 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 "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;
> +	char *subnet_prefix;
> +	char *subnet_prefix2;
> +	char *subnet_prefix_str;
> +	char *subnet_prefix_str2;
> +	int low, high;
> +	int low2, high2;
> +	size_t subnet_prefix_sz, subnet_prefix2_sz;
> +
> +	/* 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) {
> +		int stop = 0;
> +
> +		if (STATUS_SUCCESS !=
> +				semanage_ibpkey_get_subnet_prefix_by
> tes(handle,
> +								    
>   ibpkeys[i],
> +								    
>   &subnet_prefix,
> +								    
>   &subnet_prefix_sz)) {
> +			ERR(handle, "Couldn't get subnet prefix");
> +			goto err;
> +		}
> +		if (STATUS_SUCCESS !=
> semanage_ibpkey_get_subnet_prefix(handle,
> +								    
>   ibpkeys[i],
> +								    
>   &subnet_prefix_str)) {
> +			ERR(handle, "Couldn't get subnet prefix
> string");
> +			goto err;
> +		}
> +
> +		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_by
> tes(handle,
> +								    
>   ibpkeys[j],
> +								    
>   &subnet_prefix2,
> +								    
>   &subnet_prefix2_sz)) {
> +				ERR(handle, "Couldn't get subnet
> prefix");
> +				goto err;
> +			}
> +			if (STATUS_SUCCESS !=
> +				semanage_ibpkey_get_subnet_prefix(ha
> ndle,
> +								ibpk
> eys[j],
> +								&sub
> net_prefix_str2)) {
> +				ERR(handle, "Couldn't get subnet
> prefix string");
> +				goto err;
> +			}
> +			low2 = semanage_ibpkey_get_low(ibpkeys[j]);
> +			high2 =
> semanage_ibpkey_get_high(ibpkeys[j]);
> +
> +			if (subnet_prefix_sz == subnet_prefix2_sz)
> +				stop = !memcmp(subnet_prefix,
> subnet_prefix2, subnet_prefix_sz);
> +		} while (!stop);
> +
> +		/* 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..041b1ce 100644
> --- a/libsemanage/src/libsemanage.map
> +++ b/libsemanage/src/libsemanage.map
> @@ -18,6 +18,7 @@ LIBSEMANAGE_1.0 {
>  	  semanage_root;
>  	  semanage_user_*; semanage_bool_*; semanage_seuser_*;
>  	  semanage_iface_*; semanage_port_*; semanage_context_*;
> +	  semanage_ibpkey_*;
>  	  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/policy_components.c
> b/libsemanage/src/policy_components.c
> index d31bd48..136c5a7 100644
> --- a/libsemanage/src/policy_components.c
> +++ b/libsemanage/src/policy_components.c
> @@ -137,12 +137,14 @@ int
> semanage_base_merge_components(semanage_handle_t * handle)
>  
>  		{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},
>  	};
>  	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 +220,7 @@ int semanage_commit_components(semanage_handle_t
> * handle)
>  		semanage_seuser_dbase_policy(handle),
>  		semanage_bool_dbase_active(handle),
>  		semanage_node_dbase_local(handle),
> +		semanage_ibpkey_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..f61f3b2 100644
> --- a/libsemanage/src/semanage_store.c
> +++ b/libsemanage/src/semanage_store.c
> @@ -99,6 +99,7 @@ static const char
> *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
>  	"/homedir_template",
>  	"/file_contexts.template",
>  	"/commit_num",
> +	"/pkeys.local",
>  	"/ports.local",
>  	"/interfaces.local",
>  	"/nodes.local",
> diff --git a/libsemanage/src/semanage_store.h
> b/libsemanage/src/semanage_store.h
> index 0b96fbe..c7bcf44 100644
> --- a/libsemanage/src/semanage_store.h
> +++ b/libsemanage/src/semanage_store.h
> @@ -44,6 +44,7 @@ enum semanage_sandbox_defs {
>  	SEMANAGE_HOMEDIR_TMPL,
>  	SEMANAGE_FC_TMPL,
>  	SEMANAGE_COMMIT_NUM_FILE,
> +	SEMANAGE_IBPKEYS_LOCAL,
>  	SEMANAGE_PORTS_LOCAL,
>  	SEMANAGE_INTERFACES_LOCAL,
>  	SEMANAGE_NODES_LOCAL,
> diff --git a/libsemanage/src/semanageswig.i
> b/libsemanage/src/semanageswig.i
> index 583b7d8..d3ca795 100644
> --- a/libsemanage/src/semanageswig.i
> +++ b/libsemanage/src/semanageswig.i
> @@ -39,6 +39,9 @@
>  %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/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..40932d8 100644
> --- a/libsemanage/src/semanageswig_python.i
> +++ b/libsemanage/src/semanageswig_python.i
> @@ -437,6 +437,49 @@
>  	$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;
> +}
> +
>  /** node typemaps **/
>  
>  /* the wrapper will setup this parameter for passing... the
> resulting python functions
> diff --git a/libsemanage/utils/semanage_migrate_store
> b/libsemanage/utils/semanage_migrate_store
> index 0ebd285..325de47 100755
> --- a/libsemanage/utils/semanage_migrate_store
> +++ b/libsemanage/utils/semanage_migrate_store
> @@ -253,7 +253,8 @@ if __name__ == "__main__":
>  		"preserve_tunables",
>  		"policy.kern",
>  		"file_contexts",
> -		"homedir_template"]
> +		"homedir_template",
> +                "pkeys.local"]
>  
>  
>  	create_dir(newroot_path(), 0o755)
> diff --git a/libsepol/VERSION b/libsepol/VERSION
> index 5154b3f..e70b452 100644
> --- a/libsepol/VERSION
> +++ b/libsepol/VERSION
> @@ -1 +1 @@
> -2.6
> +2.6.0

Extraneous change?

> diff --git a/libsepol/include/sepol/ibpkey_record.h
> b/libsepol/include/sepol/ibpkey_record.h
> new file mode 100644
> index 0000000..815582b
> --- /dev/null
> +++ b/libsepol/include/sepol/ibpkey_record.h
> @@ -0,0 +1,75 @@
> +#ifndef _SEPOL_IBPKEY_RECORD_H_
> +#define _SEPOL_IBPKEY_RECORD_H_
> +
> +#include <stddef.h>
> +#include <sepol/context_record.h>
> +#include <sepol/handle.h>
> +#include <sys/cdefs.h>
> +
> +__BEGIN_DECLS
> +
> +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,
> +				  const char **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 int sepol_ibpkey_get_subnet_prefix_bytes(sepol_handle_t
> *handle,
> +					      const sepol_ibpkey_t
> *ibpkey,
> +					      char **buffer, size_t
> *bsize);
> +
> +extern int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
> +			sepol_ibpkey_t *ibpkey, const char
> *subnet_prefix);
> +
> +extern int sepol_ibpkey_set_subnet_prefix_bytes(sepol_handle_t
> *handle,
> +					      sepol_ibpkey_t
> *ibpkey,
> +					      const char
> *subnet_prefix,
> +					      size_t
> subnet_prefix_sz);
> +
> +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);
> +
> +__END_DECLS
> +#endif
> diff --git a/libsepol/include/sepol/ibpkeys.h
> b/libsepol/include/sepol/ibpkeys.h
> new file mode 100644
> index 0000000..4ab0a8a
> --- /dev/null
> +++ b/libsepol/include/sepol/ibpkeys.h
> @@ -0,0 +1,44 @@
> +#ifndef _SEPOL_IBPKEYS_H_
> +#define _SEPOL_IBPKEYS_H_
> +
> +#include <sepol/handle.h>
> +#include <sepol/policydb.h>
> +#include <sepol/ibpkey_record.h>
> +#include <sys/cdefs.h>
> +
> +__BEGIN_DECLS
> +
> +/* 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);
> +
> +__END_DECLS
> +#endif
> diff --git a/libsepol/include/sepol/sepol.h
> b/libsepol/include/sepol/sepol.h
> index 513f77d..540f01d 100644
> --- a/libsepol/include/sepol/sepol.h
> +++ b/libsepol/include/sepol/sepol.h
> @@ -11,12 +11,14 @@ extern "C" {
>  #include <sepol/user_record.h>
>  #include <sepol/context_record.h>
>  #include <sepol/iface_record.h>
> +#include <sepol/ibpkey_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/ports.h>
>  #include <sepol/nodes.h>
>  #include <sepol/users.h>
> 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..6fd9116
> --- /dev/null
> +++ b/libsepol/src/ibpkey_record.c
> @@ -0,0 +1,474 @@
> +#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 */
> +	char *subnet_prefix;
> +	size_t subnet_prefix_sz;

Do we need support for variable-length subnet prefix?  Can it change?

> +
> +	/* Low - High range. Same for single ibpkeys. */
> +	int low, high;
> +
> +	/* Context */
> +	sepol_context_t *con;
> +};
> +
> +struct sepol_ibpkey_key {
> +	/* Subnet prefix */
> +	char *subnet_prefix;
> +	size_t subnet_prefix_sz;
> +
> +	/* 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,
> +				      char *subnet_prefix_bytes)
> +{
> +	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;
> +	}
> +
> +#ifdef DARWIN
> +	memcpy(subnet_prefix_bytes, in_addr.s6_addr, 16);
> +#else
> +	memcpy(subnet_prefix_bytes, in_addr.s6_addr32, 16);
> +#endif

Just reduce to always using s6_addr

> +
> +	return STATUS_SUCCESS;
> +}
> +
> +static int ibpkey_alloc_subnet_prefix(sepol_handle_t *handle,
> +				      char **subnet_prefix,
> +				      size_t *subnet_prefix_sz)
> +{
> +	char *tmp_subnet_prefix = malloc(16);
> +	size_t tmp_subnet_prefix_sz = 16;

No magic constants, and definitely not repeatedly used.

> +
> +	if (!tmp_subnet_prefix)
> +		goto omem;
> +
> +	*subnet_prefix = tmp_subnet_prefix;
> +	*subnet_prefix_sz = tmp_subnet_prefix_sz;
> +	return STATUS_SUCCESS;
> +
> +omem:
> +	ERR(handle, "out of memory");
> +	return STATUS_ERR;
> +}
> +
> +/* Converts a numeric representation (subnet_prefix_bytes)
> + * to a string representation (subnet_prefix_str)
> + */
> +
> +static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle,
> +				       char *subnet_prefix_bytes,
> +				       char *subnet_prefix_str)
> +{
> +	struct in6_addr addr;
> +
> +	memset(&addr, 0, sizeof(struct in6_addr));
> +#ifdef DARWIN
> +	memcpy(&addr.s6_addr[0], subnet_prefix_bytes, 16);
> +#else
> +	memcpy(&addr.s6_addr32[0], subnet_prefix_bytes, 16);
> +#endif
> +	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_alloc_subnet_prefix(handle, &tmp_key-
> >subnet_prefix, &tmp_key->subnet_prefix_sz) < 0)
> +		goto err;
> +	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,
> +			     const char **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->subnet_prefix);
> +	free(key);
> +}
> +
> +int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const
> sepol_ibpkey_key_t *key)
> +{
> +	int rc;
> +
> +	if (ibpkey->subnet_prefix_sz < key->subnet_prefix_sz)
> +		return -1;
> +	else if (ibpkey->subnet_prefix_sz > key->subnet_prefix_sz)
> +		return 1;
> +
> +	rc = memcmp(ibpkey->subnet_prefix, key->subnet_prefix,
> ibpkey->subnet_prefix_sz);
> +
> +	if (ibpkey->low == key->low &&
> +	    ibpkey->high == key->high &&
> +	    !rc)
> +		return 0;
> +
> +	if (ibpkey->low < key->low)
> +		return -1;
> +
> +	else if (key->low < ibpkey->low)
> +		return 1;
> +
> +	else if (ibpkey->high < key->high)
> +		return -1;
> +
> +	else if (key->high < ibpkey->high)
> +		return 1;
> +	else
> +		return rc;
> +}
> +
> +int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const
> sepol_ibpkey_t *ibpkey2)
> +{
> +	int rc;
> +
> +	if (ibpkey->subnet_prefix_sz < ibpkey2->subnet_prefix_sz)
> +		return -1;
> +	else if (ibpkey->subnet_prefix_sz > ibpkey2-
> >subnet_prefix_sz)
> +		return 1;
> +
> +	rc = memcmp(ibpkey->subnet_prefix, ibpkey2->subnet_prefix,
> ibpkey->subnet_prefix_sz);
> +
> +	if (ibpkey->low == ibpkey2->low &&
> +	    ibpkey->high == ibpkey2->high &&
> +	    !rc)
> +		return 0;
> +
> +	if (ibpkey->low < ibpkey2->low)
> +		return -1;
> +
> +	else if (ibpkey2->low < ibpkey->low)
> +		return 1;
> +
> +	else if (ibpkey->high < ibpkey2->high)
> +		return -1;
> +
> +	else if (ibpkey2->high < ibpkey->high)
> +		return 1;
> +	else
> +		return rc;
> +}
> +
> +/* 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 */
> +int sepol_ibpkey_get_subnet_prefix_bytes(sepol_handle_t *handle,
> +					 const sepol_ibpkey_t
> *ibpkey,
> +					 char **buffer, size_t
> *bsize)
> +{
> +	char *tmp_buf = malloc(ibpkey->subnet_prefix_sz);
> +
> +	if (!tmp_buf) {
> +		ERR(handle, "out of memory, could not get subnet
> prefix bytes");
> +		return STATUS_ERR;
> +	}
> +
> +	memcpy(tmp_buf, ibpkey->subnet_prefix, ibpkey-
> >subnet_prefix_sz);
> +	*buffer = tmp_buf;
> +	*bsize = ibpkey->subnet_prefix_sz;
> +	return STATUS_SUCCESS;
> +}
> +
> +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)
> +{
> +	char *tmp = NULL;
> +	size_t tmp_sz;
> +
> +	if (ibpkey_alloc_subnet_prefix(handle, &tmp, &tmp_sz) < 0)
> +		goto err;
> +
> +	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, tmp) <
> 0)
> +		goto err;
> +
> +	free(ibpkey->subnet_prefix);
> +	ibpkey->subnet_prefix = tmp;
> +	ibpkey->subnet_prefix_sz = tmp_sz;
> +	return STATUS_SUCCESS;
> +
> +err:
> +	free(tmp);
> +	ERR(handle, "could not set ibpkey subnet prefix to %s",
> subnet_prefix);
> +	return STATUS_ERR;
> +}
> +
> +hidden_def(sepol_ibpkey_set_subnet_prefix)
> +
> +int sepol_ibpkey_set_subnet_prefix_bytes(sepol_handle_t *handle,
> +					 sepol_ibpkey_t *ibpkey,
> +					 const char *subnet_prefix,
> +					 size_t subnet_prefix_sz)
> +{
> +	char *tmp_subnet_prefix = malloc(subnet_prefix_sz);
> +
> +	if (!tmp_subnet_prefix) {
> +		ERR(handle, "out of memory, could not set ibpkey
> subnet prefix");
> +		return STATUS_ERR;
> +	}
> +
> +	memcpy(tmp_subnet_prefix, subnet_prefix, subnet_prefix_sz);
> +	free(ibpkey->subnet_prefix);
> +	ibpkey->subnet_prefix = tmp_subnet_prefix;
> +	ibpkey->subnet_prefix_sz = subnet_prefix_sz;
> +	return STATUS_SUCCESS;
> +}
> +
> +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 = NULL;
> +	tmp_ibpkey->subnet_prefix_sz = 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 = malloc(ibpkey-
> >subnet_prefix_sz);
> +	if (!new_ibpkey->subnet_prefix)
> +		goto omem;
> +
> +	memcpy(new_ibpkey->subnet_prefix, ibpkey->subnet_prefix,
> ibpkey->subnet_prefix_sz);
> +	new_ibpkey->subnet_prefix_sz = ibpkey->subnet_prefix_sz;
> +	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;
> +
> +omem:
> +	ERR(handle, "out of memory");
> +
> +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;
> +
> +	free(ibpkey->subnet_prefix);
> +	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..625ecfd
> --- /dev/null
> +++ b/libsepol/src/ibpkeys.c
> @@ -0,0 +1,264 @@
> +#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);
> +	size_t subnet_prefix_bsize = 0;
> +
> +	tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey));
> +	if (!tmp_ibpkey)
> +		goto omem;
> +
> +	if (sepol_ibpkey_get_subnet_prefix_bytes(handle,
> +					       data,
> +					       &subnet_prefix_buf,
> +					       &subnet_prefix_bsize)
> < 0)
> +		goto err;
> +
> +	memcpy(tmp_ibpkey->u.ibpkey.subnet_prefix,
> subnet_prefix_buf, subnet_prefix_bsize);
> +
> +	free(subnet_prefix_buf);
> +	subnet_prefix_buf = NULL;
> +
> +	/* 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)
> +{
> +	int low = ibpkey->u.ibpkey.low_pkey;
> +	int high = ibpkey->u.ibpkey.high_pkey;
> +	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;
> +
> +	if (sepol_ibpkey_set_subnet_prefix_bytes(handle, tmp_record,
> +					       (const char
> *)&ibpkey->u.ibpkey.subnet_prefix, 16) < 0)
> +		goto err;
> +
> +	sepol_ibpkey_set_range(tmp_record, low, high);
> +
> +	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;
> +
> +	handle = NULL;
> +	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;
> +	const char *subnet_prefix;
> +
> +	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
> +
> +	head = policydb->ocontexts[OCON_IBPKEY];
> +	for (c = head; c; c = c->next) {
> +		unsigned int *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 &&
> +		    (!memcmp(subnet_prefix, subnet_prefix2, 16))) {
> +			*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;
> +	const char *subnet_prefix;
> +
> +	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
> +
> +	head = policydb->ocontexts[OCON_IBPKEY];
> +	for (c = head; c; c = c->next) {
> +		unsigned int *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 &&
> +		    (!memcmp(subnet_prefix, subnet_prefix2, 16))) {
> +			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: %s 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;
> +	const char *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: %s 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/python/semanage/semanage b/python/semanage/semanage
> index 9659aac..11b56e2 100644
> --- a/python/semanage/semanage
> +++ b/python/semanage/semanage
> @@ -58,6 +58,9 @@ usage_user_dict = {' --add': ('(', '-L LEVEL', '-R
> ROLES', '-r RANGE', '-s SEUSE
>  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_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 +148,9 @@ def port_ini():
>      OBJECT = seobject.portRecords(store)
>      return OBJECT
>  
> +def ibpkey_ini():
> +    OBJECT = seobject.ibpkeyRecords(store)
> +    return OBJECT
>  
>  def module_ini():
>      OBJECT = seobject.moduleRecords(store)
> @@ -181,7 +187,7 @@ def dontaudit_ini():
>      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}
>  
>  
>  def generate_custom_usage(usage_text, usage_dict):
> @@ -292,6 +298,11 @@ def parser_add_proto(parser, name):
>      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_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 +522,52 @@ def setupPortParser(subparsers):
>      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 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 +906,7 @@ def createCommandParser():
>      setupLoginParser(subparsers)
>      setupUserParser(subparsers)
>      setupPortParser(subparsers)
> +    setupPkeyParser(subparsers)
>      setupInterfaceParser(subparsers)
>      setupModuleParser(subparsers)
>      setupNodeParser(subparsers)
> diff --git a/python/semanage/seobject.py
> b/python/semanage/seobject.py
> index 7a54373..02ad9f3 100644
> --- a/python/semanage/seobject.py
> +++ b/python/semanage/seobject.py
> @@ -1309,6 +1309,259 @@ class portRecords(semanageRecords):
>                  rec += ", %s" % p
>              print(rec)
>  
> +class ibpkeyRecords(semanageRecords):
> +    try:
> +        valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE,
> "ibpkey_type"))[0]["types"])
> +    except RuntimeError:
> +        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_pkey_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 nodeRecords(semanageRecords):
>      try:

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 1/9] checkpolicy: Add support for ibpkeycon labels
  2017-05-10 18:22   ` Stephen Smalley
@ 2017-05-10 21:46     ` Daniel Jurgens
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Jurgens @ 2017-05-10 21:46 UTC (permalink / raw)
  To: Stephen Smalley, selinux

On 5/10/2017 1:18 PM, Stephen Smalley wrote:
> On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>>
>> +#ifdef DARWIN
>> +	memcpy(&newc->u.ibpkey.subnet_prefix[0],
>> &subnet_prefix.s6_addr[0],
>> +	       sizeof(newc->u.ibpkey.subnet_prefix));
>> +#else
>> +	memcpy(&newc->u.ibpkey.subnet_prefix[0],
>> &subnet_prefix.s6_addr32[0],
>> +	       sizeof(newc->u.ibpkey.subnet_prefix));
>> +#endif
> We can just always use s6_addr instead of s6_addr32 and drop the
> #ifdef.  Just pushed a commit to fix that elsewhere. Also we switched
> from #ifdef DARWIN to __APPLE__ a while ago, but that won't matter once
> you drop the #ifdef altogether.
OK
>
>> @@ -722,10 +728,11 @@ extern int
>> policydb_set_target_platform(policydb_t *p, int platform);
>>  #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
> This is Linux-specific too.
I'll add a similar comment.
>
>>  
>>  /* 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
>> @@ -743,10 +750,11 @@ extern int
>> policydb_set_target_platform(policydb_t *p, int platform);
>>  #define MOD_POLICYDB_VERSION_TUNABLE_SEP	14
>>  #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_CONSTRAINT_NAMES	17
>> +#define MOD_POLICYDB_VERSION_INFINIBAND		18
>>  
>>  #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
> Hmmm...we never introduced a binary module version for xperms, since
> the only user is presently Android and they don't use binary modules
> and in general we'd like to get rid of binary modules altogether and
> switch entirely to source modules (either .te modules with a te2cil
> converter or cil modules).  But I guess you probably want to support
> this in the interim for convenient usage within existing Fedora/RHEL
> policies.
>
Yes, we want to pull this back into RHEL once it's available upstream.

Thank you for your quick review.  I'll continue going through your comments on the other patches and post a v1 after giving some more time for others to comment as well.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] libsepol: Add ibpkey ocontext handling
  2017-05-10 18:55   ` Stephen Smalley
@ 2017-05-10 22:23     ` Daniel Jurgens
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Jurgens @ 2017-05-10 22:23 UTC (permalink / raw)
  To: Stephen Smalley, selinux

On 5/10/2017 1:51 PM, Stephen Smalley wrote:
> On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>> Add support for reading, writing, and copying Infinabinda Pkey 
> s/Infinabinda/Infiniband/
Done
>
>> --- a/libsepol/include/sepol/policydb/services.h
>> +++ b/libsepol/include/sepol/policydb/services.h
>> @@ -188,6 +188,17 @@ extern int sepol_port_sid(uint16_t domain,
>>  			  uint16_t port, sepol_security_id_t *
>> out_sid);
>>  
>>  /*
>> + * Return the SID of the ibpkey specified by
>> + * `domain', `type', `subnet prefix', and `pkey'.
>> + */
> Can you explain why you are passing a (domain,type) pair to this
> interface and why subnet_prefix is not fixed length as it is in
> corresponding kernel interface (security_pkey_sid)?  Will these
> arguments ever be used?  Could the length change in the future?
>
> For that matter, and I guess I should have asked this on the kernel
> patches, why are you storing and passing the subnet prefix as a
> complete IPv6 address?  Is that just for the convenience of being able
> to use inet_pton() and inet_ntop()?  Is this typical for handling of IB
> subnet prefixes?  Seems a bit wasteful.
I modeled it after sepol_port_sid, which has the unused type and domain.  They are not needed and I've removed them. The length was also not needed, it is always the same size and will never change. 

Regarding using an IPv6 address for the subnet prefix, it is for convenience. There is already code to deal with IPv6 addresses, not just inet_pton and inet_ntop, but in the CIL code as well.  The subnet prefix is just the top half of the IPv6 address.  Using IPv6 address to store it allowed code reuse.  When the policy is loaded into the kernel the lower 8 bytes are not stored, subnet prefix is stored as a u64, so the space is not permanently wasted.
>>
>> @@ -2583,6 +2584,7 @@ static int ocontext_selinux_isid_to_cil(struct
>> policydb *pdb, struct ocontext *i
>>  		"policy",
>>  		"scmp_packet",
>>  		"devnull",
>> +		"ibpkey",
> I thought we dropped the separate initial SID for it?
You're right.  Overlooked this when I changed that during the kernel series review.
>>
>> @@ -185,6 +186,21 @@ static struct policydb_compat_info
>> policydb_compat[] = {
>>  	 .ocon_num = OCON_NODE6 + 1,
>>  	 .target_platform = SEPOL_TARGET_SELINUX,
>>  	},
>> +
>> +	{
>> +	 .type = POLICY_KERN,
>> +	 .version = POLICYDB_VERSION_XPERMS_IOCTL,
>> +	 .sym_num = SYM_NUM,
>> +	 .ocon_num = OCON_NODE6 + 1,
>> +	 .target_platform = SEPOL_TARGET_SELINUX,
>> +	},
> This seems duplicated?

Removed

>> @@ -2782,6 +2812,23 @@ static int ocontext_read_selinux(struct
>> policydb_compat_info *info,
>>  				    (&c->context[1], p, fp))
>>  					return -1;
>>  				break;
>> +			case OCON_IBPKEY:
>> +				rc = next_entry(buf, fp,
>> sizeof(uint32_t) * 6);
>> +				if (rc < 0)
>> +					return -1;
>> +
>> +				c->u.ibpkey.subnet_prefix[0] =
>> buf[0];
>> +				c->u.ibpkey.subnet_prefix[1] =
>> buf[1];
>> +				c->u.ibpkey.subnet_prefix[2] =
>> buf[2];
>> +				c->u.ibpkey.subnet_prefix[3] =
>> buf[3];
> Why load all the values rather than just confirming that [2] and [3]
> are zero as in the kernel?

Changed to confirm they are 0.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 4/9] checkpolicy: Add support for ibendportcon labels
  2017-05-10 19:00   ` Stephen Smalley
@ 2017-05-10 22:27     ` Daniel Jurgens
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Jurgens @ 2017-05-10 22:27 UTC (permalink / raw)
  To: Stephen Smalley, selinux

On 5/10/2017 1:56 PM, Stephen Smalley wrote:
> On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>> 	} ibendport;
> These were pkey and ib_endport in the kernel patch, and port was
> port_num.  Either way is fine but they probably ought to be consistent.

Yes, I received an internal comment that pkey wouldn't be an especially strange name collision in the future.  When I repost the kernel series I'll synchronize the names there for consistency.

>> @@ -396,6 +400,7 @@ typedef struct genfs {
>>  #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 */
> These were OCON_PKEY and OCON_IB_ENDPORT in the last kernel patches I
> saw.  Ok either way but they probably ought to be consistent.
Same here.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 6/9] libsepol: Add IB end port handling to CIL
  2017-05-09 20:50 ` [PATCH 6/9] libsepol: Add IB end port handling to CIL Dan Jurgens
@ 2017-05-11 15:07   ` James Carter
  2017-05-12 15:57     ` Daniel Jurgens
  0 siblings, 1 reply; 28+ messages in thread
From: James Carter @ 2017-05-11 15:07 UTC (permalink / raw)
  To: Dan Jurgens, selinux

On 05/09/2017 04:50 PM, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Add IB end port parsing, symbol table management, and policy generation
> to CIL.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>   libsepol/cil/src/cil.c             |   18 ++++++++++
>   libsepol/cil/src/cil_binary.c      |   29 ++++++++++++++++
>   libsepol/cil/src/cil_binary.h      |   12 +++++++
>   libsepol/cil/src/cil_build_ast.c   |   65 ++++++++++++++++++++++++++++++++++++
>   libsepol/cil/src/cil_build_ast.h   |    2 +
>   libsepol/cil/src/cil_copy_ast.c    |   25 ++++++++++++++
>   libsepol/cil/src/cil_flavor.h      |    1 +
>   libsepol/cil/src/cil_internal.h    |    9 +++++
>   libsepol/cil/src/cil_policy.c      |   15 ++++++++
>   libsepol/cil/src/cil_post.c        |   42 +++++++++++++++++++++++
>   libsepol/cil/src/cil_post.h        |    1 +
>   libsepol/cil/src/cil_reset_ast.c   |   10 +++++
>   libsepol/cil/src/cil_resolve_ast.c |   28 +++++++++++++++
>   libsepol/cil/src/cil_tree.c        |   13 +++++++
>   libsepol/cil/src/cil_verify.c      |   23 +++++++++++++
>   15 files changed, 293 insertions(+), 0 deletions(-)
> 
> diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
> index 6b51b8f..f3849ef 100644
> --- a/libsepol/cil/src/cil.c
> +++ b/libsepol/cil/src/cil.c
> @@ -188,6 +188,7 @@ static void cil_init_keys(void)
>   	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");
> @@ -258,6 +259,7 @@ void cil_db_init(struct cil_db **db)
>   	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);
> @@ -310,6 +312,7 @@ void cil_db_destroy(struct cil_db **db)
>   	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);
> @@ -733,6 +736,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
>   	case CIL_PORTCON:
>   		cil_destroy_portcon(*data);
>   		break;
> +	case CIL_IBENDPORTCON:
> +		cil_destroy_ibendportcon(*data);
> +		break;
>   	case CIL_NODECON:
>   		cil_destroy_nodecon(*data);
>   		break;
> @@ -1099,6 +1105,8 @@ const char * cil_node_to_string(struct cil_tree_node *node)
>   		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:
> @@ -1832,6 +1840,16 @@ void cil_netifcon_init(struct cil_netifcon **netifcon)
>   	(*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));
> diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
> index 75398ff..fb65698 100644
> --- a/libsepol/cil/src/cil_binary.c
> +++ b/libsepol/cil/src/cil_binary.c
> @@ -3323,6 +3323,30 @@ exit:
>   	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;
> @@ -3887,6 +3911,11 @@ int __cil_contexts_to_policydb(policydb_t *pdb, const struct cil_db *db)
>   		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 a03d250..5367feb 100644
> --- a/libsepol/cil/src/cil_binary.h
> +++ b/libsepol/cil/src/cil_binary.h
> @@ -342,6 +342,18 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st
>   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 4ca88c1..ede19a2 100644
> --- a/libsepol/cil/src/cil_build_ast.c
> +++ b/libsepol/cil/src/cil_build_ast.c
> @@ -4598,6 +4598,68 @@ void cil_destroy_netifcon(struct cil_netifcon *netifcon)
>   	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 (!db || !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->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[] = {
> @@ -6229,6 +6291,9 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
>   	} 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 64da477..a31f6a4 100644
> --- a/libsepol/cil/src/cil_build_ast.h
> +++ b/libsepol/cil/src/cil_build_ast.h
> @@ -175,6 +175,8 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru
>   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 5c55983..665fe77 100644
> --- a/libsepol/cil/src/cil_copy_ast.c
> +++ b/libsepol/cil/src/cil_copy_ast.c
> @@ -1204,6 +1204,28 @@ int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, __attribute__
>   	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 +1938,9 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
>   	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_flavor.h b/libsepol/cil/src/cil_flavor.h
> index 242154d..04f4abd 100644
> --- a/libsepol/cil/src/cil_flavor.h
> +++ b/libsepol/cil/src/cil_flavor.h
> @@ -113,6 +113,7 @@ enum cil_flavor {
>   	CIL_MLS,
>   	CIL_SRC_INFO,
>   	CIL_IBPKEYCON,
> +	CIL_IBENDPORTCON,
>   
>   /*
>    *          boolean  constraint  set  catset
> diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
> index de2a8df..9d403f6 100644
> --- a/libsepol/cil/src/cil_internal.h
> +++ b/libsepol/cil/src/cil_internal.h
> @@ -203,6 +203,7 @@ 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;
> @@ -287,6 +288,7 @@ struct cil_db {
>   	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;
> @@ -780,6 +782,12 @@ struct cil_netifcon {
>   	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;
> @@ -965,6 +973,7 @@ int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_s
>   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);
> diff --git a/libsepol/cil/src/cil_policy.c b/libsepol/cil/src/cil_policy.c
> index 35a0a29..2196ae8 100644
> --- a/libsepol/cil/src/cil_policy.c
> +++ b/libsepol/cil/src/cil_policy.c
> @@ -1729,6 +1729,20 @@ static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int
>   	}
>   }
>   
> +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;
> @@ -1958,6 +1972,7 @@ void cil_gen_policy(FILE *out, struct cil_db *db)
>   	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 8b6608a..25ee90c 100644
> --- a/libsepol/cil/src/cil_post.c
> +++ b/libsepol/cil/src/cil_post.c
> @@ -217,6 +217,25 @@ int cil_post_netifcon_compare(const void *a, const void *b)
>   	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;
> @@ -426,6 +445,9 @@ static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *fini
>   	case CIL_IBPKEYCON:
>   		db->ibpkeycon->count++;
>   		break;
> +	case CIL_IBENDPORTCON:
> +		db->ibendportcon->count++;
> +		break;
>   	case CIL_PORTCON:
>   		db->portcon->count++;
>   		break;
> @@ -516,6 +538,17 @@ static int __cil_post_db_array_helper(struct cil_tree_node *node, uint32_t *fini
>   		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;
> @@ -1654,6 +1687,14 @@ static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finish
>   			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);
> @@ -2014,6 +2055,7 @@ static int cil_post_db(struct cil_db *db)
>   	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 fe7f3a5..3d54154 100644
> --- a/libsepol/cil/src/cil_post.h
> +++ b/libsepol/cil/src/cil_post.h
> @@ -40,6 +40,7 @@ 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 d366ae3..ff67913 100644
> --- a/libsepol/cil/src/cil_reset_ast.c
> +++ b/libsepol/cil/src/cil_reset_ast.c
> @@ -326,6 +326,13 @@ static void cil_reset_netifcon(struct cil_netifcon *netifcon)
>   	}
>   }
>   
> +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) {
> @@ -498,6 +505,9 @@ int __cil_reset_node(struct cil_tree_node *node,  __attribute__((unused)) uint32
>   	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 1df41da..69ce786 100644
> --- a/libsepol/cil/src/cil_resolve_ast.c
> +++ b/libsepol/cil/src/cil_resolve_ast.c
> @@ -2038,6 +2038,31 @@ exit:
>   	return rc;
>   }
>   
> +int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args)

Should have function prototype in cil_resolve_ast.h

Jim


> +{
> +	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;
> @@ -3555,6 +3580,9 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
>   		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;
> diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
> index 4703e5f..599f756 100644
> --- a/libsepol/cil/src/cil_tree.c
> +++ b/libsepol/cil/src/cil_tree.c
> @@ -1495,6 +1495,19 @@ void cil_tree_print_node(struct cil_tree_node *node)
>   			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 108da33..1036d73 100644
> --- a/libsepol/cil/src/cil_verify.c
> +++ b/libsepol/cil/src/cil_verify.c
> @@ -1012,6 +1012,26 @@ exit:
>   	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;
> @@ -1475,6 +1495,9 @@ int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *ex
>   		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;
> 


-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] libsepol: Add ibpkey ocontext handling
  2017-05-09 20:50 ` [PATCH 2/9] libsepol: Add ibpkey ocontext handling Dan Jurgens
  2017-05-10 18:55   ` Stephen Smalley
@ 2017-05-11 15:19   ` James Carter
  2017-05-12 15:31     ` Daniel Jurgens
  1 sibling, 1 reply; 28+ messages in thread
From: James Carter @ 2017-05-11 15:19 UTC (permalink / raw)
  To: Dan Jurgens, selinux

libsepol now has the functionality to write cil or a policy.conf from a kernel 
policy, so kernel_to_cil.c and kernel_to_conf.c need to be updated as well. 
Doing that shouldn't be any more complicated than what was done for module_to_c.

Jim

On 05/09/2017 04:50 PM, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Add support for reading, writing, and copying Infinabinda Pkey ocontext
> data. Also add support for querying a Pkey sid to checkpolicy.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>   checkpolicy/checkpolicy.c                  |   27 +++++++++++++
>   libsepol/include/sepol/policydb/services.h |   11 +++++
>   libsepol/src/expand.c                      |    9 ++++
>   libsepol/src/libsepol.map.in               |    1 +
>   libsepol/src/module_to_cil.c               |   39 ++++++++++++++++++
>   libsepol/src/policydb.c                    |   47 ++++++++++++++++++++++
>   libsepol/src/services.c                    |   59 ++++++++++++++++++++++++++++
>   libsepol/src/write.c                       |   16 +++++++
>   8 files changed, 209 insertions(+), 0 deletions(-)
> 
> diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
> index 534fc22..0f12347 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,7 @@ int main(int argc, char **argv)
>   	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");
>   #ifdef EQUIVTYPES
>   	printf("z)  Show equivalent types\n");
>   #endif
> @@ -1220,6 +1222,31 @@ int main(int argc, char **argv)
>   				    "\nNo validatetrans expressions found.\n");
>   			}
>   			break;
> +		case 'k':
> +			{
> +				char *p;
> +				int len;
> +				struct in6_addr addr6;
> +				unsigned int pkey;
> +
> +				printf("subnet prefix?  ");
> +				FGETS(ans, sizeof(ans), stdin);
> +				ans[strlen(ans) - 1] = 0;
> +				p = (char *)&addr6;
> +				len = sizeof(addr6);
> +
> +				if (inet_pton(AF_INET6, ans, p) < 1) {
> +					printf("error parsing subnet prefix\n");
> +					break;
> +				}
> +
> +				printf("pkey? ");
> +				FGETS(ans, sizeof(ans), stdin);
> +				pkey = atoi(ans);
> +				sepol_ibpkey_sid(0, 0, p, len, pkey, &ssid);
> +				printf("sid %d\n", ssid);
> +			}
> +			break;
>   #ifdef EQUIVTYPES
>   		case 'z':
>   			identify_equiv_types();
> diff --git a/libsepol/include/sepol/policydb/services.h b/libsepol/include/sepol/policydb/services.h
> index 9162149..2d7aed1 100644
> --- a/libsepol/include/sepol/policydb/services.h
> +++ b/libsepol/include/sepol/policydb/services.h
> @@ -188,6 +188,17 @@ extern int sepol_port_sid(uint16_t domain,
>   			  uint16_t port, sepol_security_id_t * out_sid);
>   
>   /*
> + * Return the SID of the ibpkey specified by
> + * `domain', `type', `subnet prefix', and `pkey'.
> + */
> +extern int sepol_ibpkey_sid(uint16_t domain,
> +			  uint16_t type,
> +			  void *subnet_prefix_p,
> +			  size_t splen,
> +			  uint16_t pkey,
> +			  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/src/expand.c b/libsepol/src/expand.c
> index 54bf781..c45ecbe 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
> @@ -2217,6 +2218,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
>   					return -1;
>   				}
>   				break;
> +			case OCON_IBPKEY:
> +				n->u.ibpkey.subnet_prefix[0] = c->u.ibpkey.subnet_prefix[0];
> +				n->u.ibpkey.subnet_prefix[1] = c->u.ibpkey.subnet_prefix[1];
> +				n->u.ibpkey.subnet_prefix[2] = c->u.ibpkey.subnet_prefix[2];
> +				n->u.ibpkey.subnet_prefix[3] = c->u.ibpkey.subnet_prefix[3];
> +				n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey;
> +				n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey;
> +			break;
>   			case OCON_PORT:
>   				n->u.port.protocol = c->u.port.protocol;
>   				n->u.port.low_port = c->u.port.low_port;
> diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
> index 4042640..36225d1 100644
> --- a/libsepol/src/libsepol.map.in
> +++ b/libsepol/src/libsepol.map.in
> @@ -6,6 +6,7 @@ LIBSEPOL_1.0 {
>   	sepol_context_*; sepol_mls_*; sepol_check_context;
>   	sepol_iface_*;
>   	sepol_port_*;
> +	sepol_ibpkey_*;
>   	sepol_node_*;
>   	sepol_user_*; sepol_genusers; sepol_set_delusers;
>   	sepol_msg_*; sepol_debug;
> diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
> index ac095c3..db3f9c8 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
> @@ -2583,6 +2584,7 @@ static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *i
>   		"policy",
>   		"scmp_packet",
>   		"devnull",
> +		"ibpkey",
>   		NULL
>   	};
>   
> @@ -2645,6 +2647,42 @@ exit:
>   	return rc;
>   }
>   
> +static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb,
> +					struct ocontext *ibpkeycons)
> +{
> +	int rc = -1;
> +	struct ocontext *ibpkeycon;
> +	char subnet_prefix[INET6_ADDRSTRLEN];
> +	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;
> +
> +		if (inet_ntop(AF_INET6, &ibpkeycon->u.ibpkey.subnet_prefix,
> +			      subnet_prefix, 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, low);
> +		else
> +			cil_printf("(ibpkeycon %s (%i %i) ", subnet_prefix, 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;
> @@ -2878,6 +2916,7 @@ static int ocontexts_to_cil(struct policydb *pdb)
>   		ocontext_selinux_node_to_cil,
>   		ocontext_selinux_fsuse_to_cil,
>   		ocontext_selinux_node6_to_cil,
> +		ocontext_selinux_ibpkey_to_cil,
>   	};
>   	static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = {
>   		ocontext_xen_isid_to_cil,
> diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
> index 7093b29..8b76c6a 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
> @@ -185,6 +186,21 @@ static struct policydb_compat_info policydb_compat[] = {
>   	 .ocon_num = OCON_NODE6 + 1,
>   	 .target_platform = SEPOL_TARGET_SELINUX,
>   	},
> +
> +	{
> +	 .type = POLICY_KERN,
> +	 .version = POLICYDB_VERSION_XPERMS_IOCTL,
> +	 .sym_num = SYM_NUM,
> +	 .ocon_num = OCON_NODE6 + 1,
> +	 .target_platform = SEPOL_TARGET_SELINUX,
> +	},
> +	{
> +	 .type = POLICY_KERN,
> +	 .version = POLICYDB_VERSION_INFINIBAND,
> +	 .sym_num = SYM_NUM,
> +	 .ocon_num = OCON_IBPKEY + 1,
> +	 .target_platform = SEPOL_TARGET_SELINUX,
> +	},
>   	{
>   	 .type = POLICY_BASE,
>   	 .version = MOD_POLICYDB_VERSION_BASE,
> @@ -284,6 +300,13 @@ static struct policydb_compat_info policydb_compat[] = {
>   	 .target_platform = SEPOL_TARGET_SELINUX,
>   	},
>   	{
> +	 .type = POLICY_BASE,
> +	 .version = MOD_POLICYDB_VERSION_INFINIBAND,
> +	 .sym_num = SYM_NUM,
> +	 .ocon_num = OCON_IBPKEY + 1,
> +	 .target_platform = SEPOL_TARGET_SELINUX,
> +	},
> +	{
>   	 .type = POLICY_MOD,
>   	 .version = MOD_POLICYDB_VERSION_BASE,
>   	 .sym_num = SYM_NUM,
> @@ -381,6 +404,13 @@ static struct policydb_compat_info policydb_compat[] = {
>   	 .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
> @@ -2782,6 +2812,23 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
>   				    (&c->context[1], p, fp))
>   					return -1;
>   				break;
> +			case OCON_IBPKEY:
> +				rc = next_entry(buf, fp, sizeof(uint32_t) * 6);
> +				if (rc < 0)
> +					return -1;
> +
> +				c->u.ibpkey.subnet_prefix[0] = buf[0];
> +				c->u.ibpkey.subnet_prefix[1] = buf[1];
> +				c->u.ibpkey.subnet_prefix[2] = buf[2];
> +				c->u.ibpkey.subnet_prefix[3] = buf[3];
> +
> +				c->u.ibpkey.low_pkey = le32_to_cpu(buf[4]);
> +				c->u.ibpkey.high_pkey = le32_to_cpu(buf[5]);
> +
> +				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)
> diff --git a/libsepol/src/services.c b/libsepol/src/services.c
> index 03fb120..39903d1 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
> @@ -1910,6 +1911,64 @@ int hidden sepol_fs_sid(char *name,
>   	return rc;
>   }
>   
> +static int match_subnet_prefix(uint32_t *input, uint32_t *subnet_prefix)
> +{
> +	int i, fail = 0;
> +
> +	for (i = 0; i < 4; i++)
> +		if (subnet_prefix[i] != input[i]) {
> +			fail = 1;
> +			break;
> +		}
> +
> +	return !fail;
> +}
> +
> +/*
> + * Return the SID of the ibpkey specified by
> + * `domain', `type', `subnet prefix', and `pkey number'.
> + */
> +int hidden sepol_ibpkey_sid(uint16_t domain __attribute__ ((unused)),
> +			  uint16_t type __attribute__ ((unused)),
> +			  void *subnet_prefix_p,
> +			  size_t splen,
> +			  uint16_t pkey, sepol_security_id_t *out_sid)
> +{
> +	ocontext_t *c;
> +	int rc = 0;
> +
> +	if (splen != sizeof(uint64_t)) {
> +		rc = -EINVAL;
> +		goto out;
> +	}
> +
> +	c = policydb->ocontexts[OCON_IBPKEY];
> +	while (c) {
> +		if (c->u.ibpkey.low_pkey <= pkey &&
> +		    c->u.ibpkey.high_pkey >= pkey &&
> +		    match_subnet_prefix(subnet_prefix_p,
> +					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 port specified by
>    * `domain', `type', `protocol', and `port'.
> diff --git a/libsepol/src/write.c b/libsepol/src/write.c
> index e75b9ab..fa1b7d1 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
> @@ -1410,6 +1411,21 @@ static int ocontext_write_selinux(struct policydb_compat_info *info,
>   				if (context_write(p, &c->context[1], fp))
>   					return POLICYDB_ERROR;
>   				break;
> +			case OCON_IBPKEY:
> +				 /* The subnet prefix is in network order */
> +				for (j = 0; j < 4; j++)
> +					buf[j] = c->u.ibpkey.subnet_prefix[j];
> +
> +				buf[4] = cpu_to_le32(c->u.ibpkey.low_pkey);
> +				buf[5] = cpu_to_le32(c->u.ibpkey.high_pkey);
> +
> +				items = put_entry(buf, sizeof(uint32_t), 6, fp);
> +				if (items != 6)
> +					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;
> 


-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 5/9] libsepol: Add ibendport ocontext handling
  2017-05-09 20:50 ` [PATCH 5/9] libsepol: Add ibendport ocontext handling Dan Jurgens
  2017-05-10 19:09   ` Stephen Smalley
@ 2017-05-11 15:20   ` James Carter
  2017-05-12 15:54     ` Daniel Jurgens
  1 sibling, 1 reply; 28+ messages in thread
From: James Carter @ 2017-05-11 15:20 UTC (permalink / raw)
  To: Dan Jurgens, selinux

Like I mentioned for patch 2, kernel_to_cil.c and kernel_to_conf.c need to be 
updated.

Jim

On 05/09/2017 04:50 PM, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Add support for reading, writing, and copying IB end port ocontext data.
> Also add support for querying a IB end port sid to checkpolicy.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>   checkpolicy/checkpolicy.c                  |   20 ++++++++++++++
>   libsepol/include/sepol/policydb/services.h |   10 +++++++
>   libsepol/src/expand.c                      |    8 +++++
>   libsepol/src/libsepol.map.in               |    1 +
>   libsepol/src/module_to_cil.c               |   15 ++++++++++
>   libsepol/src/policydb.c                    |   21 +++++++++++++-
>   libsepol/src/services.c                    |   39 ++++++++++++++++++++++++++++
>   libsepol/src/write.c                       |   14 ++++++++++
>   8 files changed, 126 insertions(+), 2 deletions(-)
> 
> diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
> index 0f12347..72431d6 100644
> --- a/checkpolicy/checkpolicy.c
> +++ b/checkpolicy/checkpolicy.c
> @@ -701,6 +701,7 @@ int main(int argc, char **argv)
>   	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
> @@ -1247,6 +1248,25 @@ int main(int argc, char **argv)
>   				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(0, 0, name, port, &ssid);
> +			printf("sid %d\n", ssid);
> +			free(name);
> +			break;
>   #ifdef EQUIVTYPES
>   		case 'z':
>   			identify_equiv_types();
> diff --git a/libsepol/include/sepol/policydb/services.h b/libsepol/include/sepol/policydb/services.h
> index 2d7aed1..aa8d718 100644
> --- a/libsepol/include/sepol/policydb/services.h
> +++ b/libsepol/include/sepol/policydb/services.h
> @@ -199,6 +199,16 @@ extern int sepol_ibpkey_sid(uint16_t domain,
>   			  sepol_security_id_t *out_sid);
>   
>   /*
> + * Return the SID of the ibendport specified by
> + * `domain', `type', `dev_name', and `port'.
> + */
> +extern int sepol_ibendport_sid(uint16_t domain,
> +			       uint16_t type,
> +			       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/src/expand.c b/libsepol/src/expand.c
> index c45ecbe..061945e 100644
> --- a/libsepol/src/expand.c
> +++ b/libsepol/src/expand.c
> @@ -2226,6 +2226,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
>   				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;
> diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
> index 36225d1..dd1fec2 100644
> --- a/libsepol/src/libsepol.map.in
> +++ b/libsepol/src/libsepol.map.in
> @@ -7,6 +7,7 @@ LIBSEPOL_1.0 {
>   	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/module_to_cil.c b/libsepol/src/module_to_cil.c
> index db3f9c8..4b9f2c8 100644
> --- a/libsepol/src/module_to_cil.c
> +++ b/libsepol/src/module_to_cil.c
> @@ -2585,6 +2585,7 @@ static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *i
>   		"scmp_packet",
>   		"devnull",
>   		"ibpkey",
> +		"ibendport",
>   		NULL
>   	};
>   
> @@ -2763,6 +2764,19 @@ exit:
>   	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)
>   {
> @@ -2917,6 +2931,7 @@ static int ocontexts_to_cil(struct policydb *pdb)
>   		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,
> diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
> index 8b76c6a..6c9f2f9 100644
> --- a/libsepol/src/policydb.c
> +++ b/libsepol/src/policydb.c
> @@ -198,7 +198,7 @@ static struct policydb_compat_info policydb_compat[] = {
>   	 .type = POLICY_KERN,
>   	 .version = POLICYDB_VERSION_INFINIBAND,
>   	 .sym_num = SYM_NUM,
> -	 .ocon_num = OCON_IBPKEY + 1,
> +	 .ocon_num = OCON_IBENDPORT + 1,
>   	 .target_platform = SEPOL_TARGET_SELINUX,
>   	},
>   	{
> @@ -303,7 +303,7 @@ static struct policydb_compat_info policydb_compat[] = {
>   	 .type = POLICY_BASE,
>   	 .version = MOD_POLICYDB_VERSION_INFINIBAND,
>   	 .sym_num = SYM_NUM,
> -	 .ocon_num = OCON_IBPKEY + 1,
> +	 .ocon_num = OCON_IBENDPORT + 1,
>   	 .target_platform = SEPOL_TARGET_SELINUX,
>   	},
>   	{
> @@ -2829,6 +2829,23 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
>   				    (&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]);
> +				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)
> diff --git a/libsepol/src/services.c b/libsepol/src/services.c
> index 39903d1..d4a068a 100644
> --- a/libsepol/src/services.c
> +++ b/libsepol/src/services.c
> @@ -1970,6 +1970,45 @@ out:
>   }
>   
>   /*
> + * Return the SID of the subnet management interface specified by
> + * `domain', `type', `device name', and `port'.
> + */
> +int hidden sepol_ibendport_sid(uint16_t domain __attribute__ ((unused)),
> +			       uint16_t type __attribute__ ((unused)),
> +			       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 &&
> +		    !strncmp(dev_name, c->u.ibendport.dev_name, 64))
> +			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 fa1b7d1..e3ff389 100644
> --- a/libsepol/src/write.c
> +++ b/libsepol/src/write.c
> @@ -1426,6 +1426,20 @@ static int ocontext_write_selinux(struct policydb_compat_info *info,
>   				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;
> 


-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 5/9] libsepol: Add ibendport ocontext handling
  2017-05-10 19:09   ` Stephen Smalley
@ 2017-05-11 16:13     ` Daniel Jurgens
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Jurgens @ 2017-05-11 16:13 UTC (permalink / raw)
  To: Stephen Smalley, selinux

On 5/10/2017 2:05 PM, Stephen Smalley wrote:
> On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>> --- a/libsepol/include/sepol/policydb/services.h
>> +++ b/libsepol/include/sepol/policydb/services.h
>> @@ -199,6 +199,16 @@ extern int sepol_ibpkey_sid(uint16_t domain,
>>  			  sepol_security_id_t *out_sid);
>>  
>>  /*
>> + * Return the SID of the ibendport specified by
>> + * `domain', `type', `dev_name', and `port'.
>> + */
>> +extern int sepol_ibendport_sid(uint16_t domain,
>> +			       uint16_t type,
>> +			       char *dev_name,
>> +			       uint8_t port,
>> +			       sepol_security_id_t *out_sid);
> Why (domain, type) arguments?

Same case as the pkey one.  Removed.

>> --- a/libsepol/src/module_to_cil.c
>> +++ b/libsepol/src/module_to_cil.c
>> @@ -2585,6 +2585,7 @@ static int ocontext_selinux_isid_to_cil(struct
>> policydb *pdb, struct ocontext *i
>>  		"scmp_packet",
>>  		"devnull",
>>  		"ibpkey",
>> +		"ibendport",
> No new initial SIDs.

Removed


>>
>> @@ -2829,6 +2829,23 @@ static int ocontext_read_selinux(struct
>> policydb_compat_info *info,
>>  				    (&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 (zero_or_saturated(len))
> 	return -1;

Added, but slightly differently because I'm checking for a smaller max length due to the next comment.

>> +int hidden sepol_ibendport_sid(uint16_t domain __attribute__
>> ((unused)),
>> +			       uint16_t type __attribute__
>> ((unused)),
>> +			       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 &&
>> +		    !strncmp(dev_name, c->u.ibendport.dev_name, 64))
>> +			break;
> Do you ensure that dev_name cannot be > 64 bytes in checkpolicy and in
> ocontext_read_selinux()?  And do we really want strncmp() here rather
> than just strcmp()?  What's the advantage?
The maximum size for an Infiniband device name is 64 bytes. But there really isn't an advantage for the comparison.  I'll switch it, and enforce a length check.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys
  2017-05-10 19:26   ` Stephen Smalley
@ 2017-05-11 22:51     ` Daniel Jurgens
  2017-05-12 16:45       ` Stephen Smalley
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Jurgens @ 2017-05-11 22:51 UTC (permalink / raw)
  To: Stephen Smalley, selinux

On 5/10/2017 2:22 PM, Stephen Smalley wrote:
> On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>>
>>  libsepol/src/ibpkeys.c                        |  264 ++++++++++++++
>>  python/semanage/semanage                      |   60 +++-
>>  python/semanage/seobject.py                   |  253 +++++++++++++
>>  28 files changed, 2159 insertions(+), 17 deletions(-)
> That's a lot of code.  Did you look at whether you could generalize the
> port record stuff at all to see if we could factor out common helpers
> or anything?  I guess this is consistent with the current code, but it
> seems like a lot of very similar code being duplicated and then
> slightly tweaked.
I don't see a good way to generalize.  The high/low pkey/port part overlaps, but all that code is compact anyway.  To make it work for both would complicate it to figure out the correct key/ocontext to use.  The protocol and subnet_prefix handling is most of the code, and it's very different.
>
>>  
>>  	create_dir(newroot_path(), 0o755)
>> diff --git a/libsepol/VERSION b/libsepol/VERSION
>> index 5154b3f..e70b452 100644
>> --- a/libsepol/VERSION
>> +++ b/libsepol/VERSION
>> @@ -1 +1 @@
>> -2.6
>> +2.6.0
> Extraneous change?
Yes.
>> +struct sepol_ibpkey {
>> +	/* Subnet prefix */
>> +	char *subnet_prefix;
>> +	size_t subnet_prefix_sz;
> Do we need support for variable-length subnet prefix?  Can it change?
It doesn't need to be variable.  I'll remove.
>> +#ifdef DARWIN
>> +	memcpy(subnet_prefix_bytes, in_addr.s6_addr, 16);
>> +#else
>> +	memcpy(subnet_prefix_bytes, in_addr.s6_addr32, 16);
>> +#endif
> Just reduce to always using s6_addr
Done
>> +static int ibpkey_alloc_subnet_prefix(sepol_handle_t *handle,
>> +				      char **subnet_prefix,
>> +				      size_t *subnet_prefix_sz)
>> +{
>> +	char *tmp_subnet_prefix = malloc(16);
>> +	size_t tmp_subnet_prefix_sz = 16;
> No magic constants, and definitely not repeatedly used.
Done

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] libsepol: Add ibpkey ocontext handling
  2017-05-11 15:19   ` James Carter
@ 2017-05-12 15:31     ` Daniel Jurgens
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Jurgens @ 2017-05-12 15:31 UTC (permalink / raw)
  To: James Carter, selinux

On 5/11/2017 10:18 AM, James Carter wrote:
> libsepol now has the functionality to write cil or a policy.conf from a kernel 
> policy, so kernel_to_cil.c and kernel_to_conf.c need to be updated as well. 
> Doing that shouldn't be any more complicated than what was done for module_to_c.
>
> Jim
Added.  Thanks for reviewing, completely missed when those files were added.
>
> On 05/09/2017 04:50 PM, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>> Add support for reading, writing, and copying Infinabinda Pkey ocontext
>> data. Also add support for querying a Pkey sid to checkpolicy.
>>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 5/9] libsepol: Add ibendport ocontext handling
  2017-05-11 15:20   ` James Carter
@ 2017-05-12 15:54     ` Daniel Jurgens
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Jurgens @ 2017-05-12 15:54 UTC (permalink / raw)
  To: James Carter, selinux

On 5/11/2017 10:20 AM, James Carter wrote:
> Like I mentioned for patch 2, kernel_to_cil.c and kernel_to_conf.c need to be 
> updated.
>
> Jim
Added

> On 05/09/2017 04:50 PM, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>> Add support for reading, writing, and copying IB end port ocontext data.
>> Also add support for querying a IB end port sid to checkpolicy.
>>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 6/9] libsepol: Add IB end port handling to CIL
  2017-05-11 15:07   ` James Carter
@ 2017-05-12 15:57     ` Daniel Jurgens
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Jurgens @ 2017-05-12 15:57 UTC (permalink / raw)
  To: James Carter, selinux

On 5/11/2017 10:07 AM, James Carter wrote:
> On 05/09/2017 04:50 PM, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>>
>> diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
>> index 1df41da..69ce786 100644
>> --- a/libsepol/cil/src/cil_resolve_ast.c
>> +++ b/libsepol/cil/src/cil_resolve_ast.c
>> @@ -2038,6 +2038,31 @@ exit:
>>   	return rc;
>>   }
>>   
>> +int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args)
> Should have function prototype in cil_resolve_ast.h
>
> Jim
Done

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys
  2017-05-11 22:51     ` Daniel Jurgens
@ 2017-05-12 16:45       ` Stephen Smalley
  0 siblings, 0 replies; 28+ messages in thread
From: Stephen Smalley @ 2017-05-12 16:45 UTC (permalink / raw)
  To: Daniel Jurgens, selinux

On Thu, 2017-05-11 at 22:51 +0000, Daniel Jurgens wrote:
> On 5/10/2017 2:22 PM, Stephen Smalley wrote:
> > On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
> > > From: Daniel Jurgens <danielj@mellanox.com>
> > > 
> > > 
> > >  libsepol/src/ibpkeys.c                        |  264
> > > ++++++++++++++
> > >  python/semanage/semanage                      |   60 +++-
> > >  python/semanage/seobject.py                   |  253
> > > +++++++++++++
> > >  28 files changed, 2159 insertions(+), 17 deletions(-)
> > 
> > That's a lot of code.  Did you look at whether you could generalize
> > the
> > port record stuff at all to see if we could factor out common
> > helpers
> > or anything?  I guess this is consistent with the current code, but
> > it
> > seems like a lot of very similar code being duplicated and then
> > slightly tweaked.
> 
> I don't see a good way to generalize.  The high/low pkey/port part
> overlaps, but all that code is compact anyway.  To make it work for
> both would complicate it to figure out the correct key/ocontext to
> use.  The protocol and subnet_prefix handling is most of the code,
> and it's very different.

Yes, looking at it more closely, I agree.  Thanks for looking at it
anyway.

> > 
> > >  
> > >  	create_dir(newroot_path(), 0o755)
> > > diff --git a/libsepol/VERSION b/libsepol/VERSION
> > > index 5154b3f..e70b452 100644
> > > --- a/libsepol/VERSION
> > > +++ b/libsepol/VERSION
> > > @@ -1 +1 @@
> > > -2.6
> > > +2.6.0
> > 
> > Extraneous change?
> 
> Yes.
> > > +struct sepol_ibpkey {
> > > +	/* Subnet prefix */
> > > +	char *subnet_prefix;
> > > +	size_t subnet_prefix_sz;
> > 
> > Do we need support for variable-length subnet prefix?  Can it
> > change?
> 
> It doesn't need to be variable.  I'll remove.
> > > +#ifdef DARWIN
> > > +	memcpy(subnet_prefix_bytes, in_addr.s6_addr, 16);
> > > +#else
> > > +	memcpy(subnet_prefix_bytes, in_addr.s6_addr32, 16);
> > > +#endif
> > 
> > Just reduce to always using s6_addr
> 
> Done
> > > +static int ibpkey_alloc_subnet_prefix(sepol_handle_t *handle,
> > > +				      char **subnet_prefix,
> > > +				      size_t *subnet_prefix_sz)
> > > +{
> > > +	char *tmp_subnet_prefix = malloc(16);
> > > +	size_t tmp_subnet_prefix_sz = 16;
> > 
> > No magic constants, and definitely not repeatedly used.
> 
> Done

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 8/9] semanage: Update semanage to allow runtime labeling of ibendports
  2017-05-09 20:50 ` [PATCH 8/9] semanage: Update semanage to allow runtime labeling of ibendports Dan Jurgens
@ 2017-05-14 12:16   ` Jason Zaman
  0 siblings, 0 replies; 28+ messages in thread
From: Jason Zaman @ 2017-05-14 12:16 UTC (permalink / raw)
  To: Dan Jurgens; +Cc: selinux

On Tue, May 09, 2017 at 11:50:41PM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Update libsepol and libsemanage to work with ibendport records. Add local
> storage for new and modified ibendport records in ibendports.local.
> Update semanage to parse the ibendport command options to add, modify,
> and delete them.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>  libsemanage/include/semanage/ibendport_record.h  |   62 +++++
>  libsemanage/include/semanage/ibendports_local.h  |   36 +++
>  libsemanage/include/semanage/ibendports_policy.h |   28 ++
>  libsemanage/include/semanage/semanage.h          |    3 +
>  libsemanage/src/direct_api.c                     |   42 +++-
>  libsemanage/src/handle.h                         |   38 ++-
>  libsemanage/src/ibendport_internal.h             |   48 ++++
>  libsemanage/src/ibendport_record.c               |  154 +++++++++++
>  libsemanage/src/ibendports_file.c                |  157 +++++++++++
>  libsemanage/src/ibendports_local.c               |  153 +++++++++++
>  libsemanage/src/ibendports_policy.c              |   55 ++++
>  libsemanage/src/ibendports_policydb.c            |   62 +++++
>  libsemanage/src/libsemanage.map                  |    1 +
>  libsemanage/src/policy_components.c              |    4 +
>  libsemanage/src/semanage_store.c                 |    1 +
>  libsemanage/src/semanage_store.h                 |    1 +
>  libsemanage/src/semanageswig.i                   |    3 +
>  libsemanage/src/semanageswig_python.i            |   43 +++
>  libsemanage/utils/semanage_migrate_store         |    3 +-
>  libsepol/include/sepol/ibendport_record.h        |   68 +++++
>  libsepol/include/sepol/ibendports.h              |   45 ++++
>  libsepol/include/sepol/sepol.h                   |    2 +
>  libsepol/src/ibendport_internal.h                |   20 ++
>  libsepol/src/ibendport_record.c                  |  299 ++++++++++++++++++++++
>  libsepol/src/ibendports.c                        |  255 ++++++++++++++++++
>  python/semanage/semanage                         |   58 ++++-
>  python/semanage/seobject.py                      |  238 +++++++++++++++++
>  27 files changed, 1857 insertions(+), 22 deletions(-)
>  create mode 100644 libsemanage/include/semanage/ibendport_record.h
>  create mode 100644 libsemanage/include/semanage/ibendports_local.h
>  create mode 100644 libsemanage/include/semanage/ibendports_policy.h
>  create mode 100644 libsemanage/src/ibendport_internal.h
>  create mode 100644 libsemanage/src/ibendport_record.c
>  create mode 100644 libsemanage/src/ibendports_file.c
>  create mode 100644 libsemanage/src/ibendports_local.c
>  create mode 100644 libsemanage/src/ibendports_policy.c
>  create mode 100644 libsemanage/src/ibendports_policydb.c
>  create mode 100644 libsepol/include/sepol/ibendport_record.h
>  create mode 100644 libsepol/include/sepol/ibendports.h
>  create mode 100644 libsepol/src/ibendport_internal.h
>  create mode 100644 libsepol/src/ibendport_record.c
>  create mode 100644 libsepol/src/ibendports.c

[ ... ]

> diff --git a/python/semanage/semanage b/python/semanage/semanage
> index 11b56e2..313537c 100644
> --- a/python/semanage/semanage
> +++ b/python/semanage/semanage
> @@ -61,6 +61,9 @@ usage_port_dict = {' --add': ('-t TYPE', '-p PROTOCOL', '-r RANGE', '(', 'port_n
>  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': ('',)}
>  
> @@ -152,6 +155,10 @@ 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)
>      return OBJECT
> @@ -187,8 +194,7 @@ def dontaudit_ini():
>      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, 'ibpkey': ibpkey_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
> @@ -303,6 +309,10 @@ def parser_add_subnet_prefix(parser, name):
>      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)
> @@ -567,6 +577,49 @@ def setupPkeyParser(subparsers):
>      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'), ('')]}
> @@ -907,6 +960,7 @@ def createCommandParser():
>      setupUserParser(subparsers)
>      setupPortParser(subparsers)
>      setupPkeyParser(subparsers)
> +    setupIbendportParser(subparsers)
>      setupInterfaceParser(subparsers)
>      setupModuleParser(subparsers)
>      setupNodeParser(subparsers)
> diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
> index 02ad9f3..895becd 100644
> --- a/python/semanage/seobject.py
> +++ b/python/semanage/seobject.py
> @@ -1563,6 +1563,244 @@ class ibpkeyRecords(semanageRecords):
>                  rec += ", %s" % p
>              print rec
>  
> +class ibendportRecords(semanageRecords):
> +    try:
> +        valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "ibendport_type"))[0]["types"])
> +    except RuntimeError:
> +        valid_types = []

Can you use setools4 directly instead of sepolicy.info()? It's an
abomination now and I only "fixed" it to keep backwards compat. It's
super slow cuz it has to loop through what setools returns and stuff it
into a dict to match the old info() format.

When I have time I want to kill most of seobject.py because its now
mostly just slow wrappers around setools4. New stuff shouldnt really use
it.

> +    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:
>          valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "node_type"))[0]["types"])
> -- 
> 1.7.1
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2017-05-14 12:17 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-09 20:50 [PATCH 0/9] SELinux user space support for Infiniband RDMA Dan Jurgens
2017-05-09 20:50 ` [PATCH 1/9] checkpolicy: Add support for ibpkeycon labels Dan Jurgens
2017-05-10 18:22   ` Stephen Smalley
2017-05-10 21:46     ` Daniel Jurgens
2017-05-09 20:50 ` [PATCH 2/9] libsepol: Add ibpkey ocontext handling Dan Jurgens
2017-05-10 18:55   ` Stephen Smalley
2017-05-10 22:23     ` Daniel Jurgens
2017-05-11 15:19   ` James Carter
2017-05-12 15:31     ` Daniel Jurgens
2017-05-09 20:50 ` [PATCH 3/9] libsepol: Add Infiniband Pkey handling to CIL Dan Jurgens
2017-05-09 20:50 ` [PATCH 4/9] checkpolicy: Add support for ibendportcon labels Dan Jurgens
2017-05-10 19:00   ` Stephen Smalley
2017-05-10 22:27     ` Daniel Jurgens
2017-05-09 20:50 ` [PATCH 5/9] libsepol: Add ibendport ocontext handling Dan Jurgens
2017-05-10 19:09   ` Stephen Smalley
2017-05-11 16:13     ` Daniel Jurgens
2017-05-11 15:20   ` James Carter
2017-05-12 15:54     ` Daniel Jurgens
2017-05-09 20:50 ` [PATCH 6/9] libsepol: Add IB end port handling to CIL Dan Jurgens
2017-05-11 15:07   ` James Carter
2017-05-12 15:57     ` Daniel Jurgens
2017-05-09 20:50 ` [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys Dan Jurgens
2017-05-10 19:26   ` Stephen Smalley
2017-05-11 22:51     ` Daniel Jurgens
2017-05-12 16:45       ` Stephen Smalley
2017-05-09 20:50 ` [PATCH 8/9] semanage: Update semanage to allow runtime labeling of ibendports Dan Jurgens
2017-05-14 12:16   ` Jason Zaman
2017-05-09 20:50 ` [PATCH 9/9] semanage: Update man pages for infiniband Dan Jurgens

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.