diff mbox

[v1,5/9] libsepol: Add ibendport ocontext handling

Message ID 1494880961-73481-6-git-send-email-danielj@mellanox.com (mailing list archive)
State Superseded
Headers show

Commit Message

Daniel Jurgens May 15, 2017, 8:42 p.m. UTC
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>

---
v1:
Stephen Smalley:
- Removed unused domain and type params from sepol_ibendport_sid.
- Remove ibendport initial sid from ocontext_selinux_isid_to_cil
- Check the length provide for the device name in ocontext_read_selinux
- Used strcmp for dev_name comparison.

James Carter:
- Added ibendport handling to kernel_to_cil.c and kernel_to_conf.c

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
---
 checkpolicy/checkpolicy.c                  | 20 ++++++++++++++
 libsepol/include/sepol/policydb/services.h |  8 ++++++
 libsepol/src/expand.c                      |  8 ++++++
 libsepol/src/kernel_to_cil.c               | 42 ++++++++++++++++++++++++++++++
 libsepol/src/kernel_to_conf.c              | 41 +++++++++++++++++++++++++++++
 libsepol/src/libsepol.map.in               |  1 +
 libsepol/src/module_to_cil.c               | 14 ++++++++++
 libsepol/src/policydb.c                    | 26 +++++++++++++++---
 libsepol/src/services.c                    | 37 ++++++++++++++++++++++++++
 libsepol/src/write.c                       | 14 ++++++++++
 10 files changed, 208 insertions(+), 3 deletions(-)

Comments

James Carter May 17, 2017, 1:54 p.m. UTC | #1
On 05/15/2017 04:42 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>
> 
> ---
> v1:
> Stephen Smalley:
> - Removed unused domain and type params from sepol_ibendport_sid.
> - Remove ibendport initial sid from ocontext_selinux_isid_to_cil
> - Check the length provide for the device name in ocontext_read_selinux
> - Used strcmp for dev_name comparison.
> 
> James Carter:
> - Added ibendport handling to kernel_to_cil.c and kernel_to_conf.c
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> ---
>   checkpolicy/checkpolicy.c                  | 20 ++++++++++++++
>   libsepol/include/sepol/policydb/services.h |  8 ++++++
>   libsepol/src/expand.c                      |  8 ++++++
>   libsepol/src/kernel_to_cil.c               | 42 ++++++++++++++++++++++++++++++
>   libsepol/src/kernel_to_conf.c              | 41 +++++++++++++++++++++++++++++
>   libsepol/src/libsepol.map.in               |  1 +
>   libsepol/src/module_to_cil.c               | 14 ++++++++++
>   libsepol/src/policydb.c                    | 26 +++++++++++++++---
>   libsepol/src/services.c                    | 37 ++++++++++++++++++++++++++
>   libsepol/src/write.c                       | 14 ++++++++++
>   10 files changed, 208 insertions(+), 3 deletions(-)
> 
> diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
> index d0e46ba..94bf083 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
> @@ -1245,6 +1246,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(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 459254e..e4f2f11 100644
> --- a/libsepol/include/sepol/policydb/services.h
> +++ b/libsepol/include/sepol/policydb/services.h
> @@ -196,6 +196,14 @@ extern int sepol_ibpkey_sid(void *subnet_prefix_p,
>   			    sepol_security_id_t *out_sid);
>   
>   /*
> + * Return the SID of the ibendport specified by
> + * `dev_name', and `port'.
> + */
> +extern int sepol_ibendport_sid(char *dev_name,
> +			       uint8_t port,
> +			       sepol_security_id_t *out_sid);
> +
> +/*
>    * Return the SIDs to use for a network interface
>    * with the name `name'.  The `if_sid' SID is returned for
>    * the interface and the `msg_sid' SID is returned as
> diff --git a/libsepol/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/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
> index fcfd0e0..6587ff4 100644
> --- a/libsepol/src/kernel_to_cil.c
> +++ b/libsepol/src/kernel_to_cil.c
> @@ -2837,6 +2837,43 @@ exit:
>   	return rc;
>   }
>   
> +static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)
> +{
> +	struct ocontext *ibendportcon;
> +	char port_str[4];
> +	char *ctx;
> +	int rc = 0;
> +
> +	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
> +	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
> +		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
> +		if (rc < 0 || rc >= 4) {
> +			rc = -1;
> +			goto exit;
> +		}
> +
> +		ctx = context_to_str(pdb, &ibendportcon->context[0]);
> +		if (!ctx) {
> +			rc = -1;
> +			goto exit;
> +		}
> +
> +		sepol_printf(out, "(ibendportcon %s %s %s)\n",
> +			     ibendportcon->u.ibendport.dev_name, port_str, ctx);
> +
> +		free(ctx);
> +	}
> +
> +	rc = 0;
> +
> +exit:
> +	if (rc != 0) {
> +		sepol_log_err("Error writing ibendportcon rules to CIL\n");
> +	}
> +
> +	return rc;
> +}
> +

You need to have the ibendport rules sorted like I mentioned for ibpkey in patch 2.

Jim

>   static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
>   {
>   	return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str);
> @@ -3238,6 +3275,11 @@ int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
>   		if (rc != 0) {
>   			goto exit;
>   		}
> +
> +		rc = write_selinux_ibendport_rules_to_cil(out, pdb);
> +		if (rc != 0) {
> +			goto exit;
> +		}
>   	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
>   		rc = write_xen_isid_rules_to_cil(out, pdb);
>   		if (rc != 0) {
> diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
> index 795cf56..ba261cf 100644
> --- a/libsepol/src/kernel_to_conf.c
> +++ b/libsepol/src/kernel_to_conf.c
> @@ -2699,6 +2699,42 @@ exit:
>   	return rc;
>   }
>   
> +static int write_selinux_ibendport_rules_to_conf(FILE *out, struct policydb *pdb)
> +{
> +	struct ocontext *ibendportcon;
> +	char port_str[4];
> +	char *ctx;
> +	int rc = 0;
> +
> +	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
> +	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
> +		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
> +		if (rc < 0 || rc >= 4) {
> +			rc = -1;
> +			goto exit;
> +		}
> +
> +		ctx = context_to_str(pdb, &ibendportcon->context[0]);
> +		if (!ctx) {
> +			rc = -1;
> +			goto exit;
> +		}
> +
> +		sepol_printf(out, "ibendportcon %s %s %s\n", ibendportcon->u.ibendport.dev_name, port_str, ctx);
> +
> +		free(ctx);
> +	}
> +
> +	rc = 0;
> +
> +exit:
> +	if (rc != 0) {
> +		sepol_log_err("Error writing ibendportcon rules to policy.conf\n");
> +	}
> +
> +	return rc;
> +}
> +
>   static int write_xen_isid_rules_to_conf(FILE *out, struct policydb *pdb)
>   {
>   	return write_sid_context_rules_to_conf(out, pdb, xen_sid_to_str);
> @@ -3104,6 +3140,11 @@ int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb)
>   		if (rc != 0) {
>   			goto exit;
>   		}
> +
> +		rc = write_selinux_ibendport_rules_to_conf(out, pdb);
> +		if (rc != 0) {
> +			goto exit;
> +		}
>   	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
>   		rc = write_xen_isid_rules_to_conf(out, pdb);
>   		if (rc != 0) {
> diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
> index 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 c97f453..04394f0 100644
> --- a/libsepol/src/module_to_cil.c
> +++ b/libsepol/src/module_to_cil.c
> @@ -2773,6 +2773,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)
>   {
> @@ -2927,6 +2940,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 d6e8e6f..9a11d45 100644
> --- a/libsepol/src/policydb.c
> +++ b/libsepol/src/policydb.c
> @@ -190,7 +190,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,
>   	},
>   	{
> @@ -295,7 +295,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,
>   	},
>   	{
> @@ -2788,7 +2788,7 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
>   				if (rc < 0)
>   					return -1;
>   				len = le32_to_cpu(buf[0]);
> -				if (zero_or_saturated(len))
> +				if (zero_or_saturated(len) || len > 63)
>   					return -1;
>   				c->u.name = malloc(len + 1);
>   				if (!c->u.name)
> @@ -2819,6 +2819,26 @@ 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 (len == 0 || len > IB_DEVICE_NAME_MAX - 1)
> +					return -1;
> +
> +				c->u.ibendport.dev_name = malloc(len + 1);
> +				if (!c->u.ibendport.dev_name)
> +					return -1;
> +				rc = next_entry(c->u.ibendport.dev_name, fp, len);
> +				if (rc < 0)
> +					return -1;
> +				c->u.ibendport.dev_name[len] = 0;
> +				c->u.ibendport.port = le32_to_cpu(buf[1]);
> +				if (context_read_and_validate
> +				    (&c->context[0], p, fp))
> +					return -1;
> +				break;
>   			case OCON_PORT:
>   				rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
>   				if (rc < 0)
> diff --git a/libsepol/src/services.c b/libsepol/src/services.c
> index 4236aac..f444f10 100644
> --- a/libsepol/src/services.c
> +++ b/libsepol/src/services.c
> @@ -1962,6 +1962,43 @@ out:
>   }
>   
>   /*
> + * Return the SID of the subnet management interface specified by
> + * `device name', and `port'.
> + */
> +int hidden sepol_ibendport_sid(char *dev_name,
> +			       uint8_t port,
> +			       sepol_security_id_t *out_sid)
> +{
> +	ocontext_t *c;
> +	int rc = 0;
> +
> +	c = policydb->ocontexts[OCON_IBENDPORT];
> +	while (c) {
> +		if (c->u.ibendport.port == port &&
> +		    !strcmp(dev_name, c->u.ibendport.dev_name))
> +			break;
> +		c = c->next;
> +	}
> +
> +	if (c) {
> +		if (!c->sid[0]) {
> +			rc = sepol_sidtab_context_to_sid(sidtab,
> +							 &c->context[0],
> +							 &c->sid[0]);
> +			if (rc)
> +				goto out;
> +		}
> +		*out_sid = c->sid[0];
> +	} else {
> +		*out_sid = SECINITSID_UNLABELED;
> +	}
> +
> +out:
> +	return rc;
> +}
> +
> +
> +/*
>    * Return the SID of the port specified by
>    * `domain', `type', `protocol', and `port'.
>    */
> diff --git a/libsepol/src/write.c b/libsepol/src/write.c
> index 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;
>
Daniel Jurgens May 18, 2017, 9:55 p.m. UTC | #2
On 5/17/2017 8:53 AM, James Carter wrote:
> On 05/15/2017 04:42 PM, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>>
>> +exit:
>> +	if (rc != 0) {
>> +		sepol_log_err("Error writing ibendportcon rules to CIL\n");
>> +	}
>> +
>> +	return rc;
>> +}
>> +
> You need to have the ibendport rules sorted like I mentioned for ibpkey in patch 2.
>
> Jim
Done for both patches.
diff mbox

Patch

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index d0e46ba..94bf083 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
@@ -1245,6 +1246,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(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 459254e..e4f2f11 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -196,6 +196,14 @@  extern int sepol_ibpkey_sid(void *subnet_prefix_p,
 			    sepol_security_id_t *out_sid);
 
 /*
+ * Return the SID of the ibendport specified by
+ * `dev_name', and `port'.
+ */
+extern int sepol_ibendport_sid(char *dev_name,
+			       uint8_t port,
+			       sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/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/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index fcfd0e0..6587ff4 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -2837,6 +2837,43 @@  exit:
 	return rc;
 }
 
+static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)
+{
+	struct ocontext *ibendportcon;
+	char port_str[4];
+	char *ctx;
+	int rc = 0;
+
+	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
+	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
+		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
+		if (rc < 0 || rc >= 4) {
+			rc = -1;
+			goto exit;
+		}
+
+		ctx = context_to_str(pdb, &ibendportcon->context[0]);
+		if (!ctx) {
+			rc = -1;
+			goto exit;
+		}
+
+		sepol_printf(out, "(ibendportcon %s %s %s)\n",
+			     ibendportcon->u.ibendport.dev_name, port_str, ctx);
+
+		free(ctx);
+	}
+
+	rc = 0;
+
+exit:
+	if (rc != 0) {
+		sepol_log_err("Error writing ibendportcon rules to CIL\n");
+	}
+
+	return rc;
+}
+
 static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
 {
 	return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str);
@@ -3238,6 +3275,11 @@  int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
 		if (rc != 0) {
 			goto exit;
 		}
+
+		rc = write_selinux_ibendport_rules_to_cil(out, pdb);
+		if (rc != 0) {
+			goto exit;
+		}
 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
 		rc = write_xen_isid_rules_to_cil(out, pdb);
 		if (rc != 0) {
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index 795cf56..ba261cf 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -2699,6 +2699,42 @@  exit:
 	return rc;
 }
 
+static int write_selinux_ibendport_rules_to_conf(FILE *out, struct policydb *pdb)
+{
+	struct ocontext *ibendportcon;
+	char port_str[4];
+	char *ctx;
+	int rc = 0;
+
+	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
+	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
+		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
+		if (rc < 0 || rc >= 4) {
+			rc = -1;
+			goto exit;
+		}
+
+		ctx = context_to_str(pdb, &ibendportcon->context[0]);
+		if (!ctx) {
+			rc = -1;
+			goto exit;
+		}
+
+		sepol_printf(out, "ibendportcon %s %s %s\n", ibendportcon->u.ibendport.dev_name, port_str, ctx);
+
+		free(ctx);
+	}
+
+	rc = 0;
+
+exit:
+	if (rc != 0) {
+		sepol_log_err("Error writing ibendportcon rules to policy.conf\n");
+	}
+
+	return rc;
+}
+
 static int write_xen_isid_rules_to_conf(FILE *out, struct policydb *pdb)
 {
 	return write_sid_context_rules_to_conf(out, pdb, xen_sid_to_str);
@@ -3104,6 +3140,11 @@  int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb)
 		if (rc != 0) {
 			goto exit;
 		}
+
+		rc = write_selinux_ibendport_rules_to_conf(out, pdb);
+		if (rc != 0) {
+			goto exit;
+		}
 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
 		rc = write_xen_isid_rules_to_conf(out, pdb);
 		if (rc != 0) {
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index 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 c97f453..04394f0 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -2773,6 +2773,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)
 {
@@ -2927,6 +2940,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 d6e8e6f..9a11d45 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -190,7 +190,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,
 	},
 	{
@@ -295,7 +295,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,
 	},
 	{
@@ -2788,7 +2788,7 @@  static int ocontext_read_selinux(struct policydb_compat_info *info,
 				if (rc < 0)
 					return -1;
 				len = le32_to_cpu(buf[0]);
-				if (zero_or_saturated(len))
+				if (zero_or_saturated(len) || len > 63)
 					return -1;
 				c->u.name = malloc(len + 1);
 				if (!c->u.name)
@@ -2819,6 +2819,26 @@  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 (len == 0 || len > IB_DEVICE_NAME_MAX - 1)
+					return -1;
+
+				c->u.ibendport.dev_name = malloc(len + 1);
+				if (!c->u.ibendport.dev_name)
+					return -1;
+				rc = next_entry(c->u.ibendport.dev_name, fp, len);
+				if (rc < 0)
+					return -1;
+				c->u.ibendport.dev_name[len] = 0;
+				c->u.ibendport.port = le32_to_cpu(buf[1]);
+				if (context_read_and_validate
+				    (&c->context[0], p, fp))
+					return -1;
+				break;
 			case OCON_PORT:
 				rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
 				if (rc < 0)
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 4236aac..f444f10 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -1962,6 +1962,43 @@  out:
 }
 
 /*
+ * Return the SID of the subnet management interface specified by
+ * `device name', and `port'.
+ */
+int hidden sepol_ibendport_sid(char *dev_name,
+			       uint8_t port,
+			       sepol_security_id_t *out_sid)
+{
+	ocontext_t *c;
+	int rc = 0;
+
+	c = policydb->ocontexts[OCON_IBENDPORT];
+	while (c) {
+		if (c->u.ibendport.port == port &&
+		    !strcmp(dev_name, c->u.ibendport.dev_name))
+			break;
+		c = c->next;
+	}
+
+	if (c) {
+		if (!c->sid[0]) {
+			rc = sepol_sidtab_context_to_sid(sidtab,
+							 &c->context[0],
+							 &c->sid[0]);
+			if (rc)
+				goto out;
+		}
+		*out_sid = c->sid[0];
+	} else {
+		*out_sid = SECINITSID_UNLABELED;
+	}
+
+out:
+	return rc;
+}
+
+
+/*
  * Return the SID of the port specified by
  * `domain', `type', `protocol', and `port'.
  */
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 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;