diff options
| -rw-r--r-- | include/linux/lsm_audit.h | 8 | ||||
| -rw-r--r-- | security/lsm_audit.c | 5 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 25 | ||||
| -rw-r--r-- | security/selinux/include/classmap.h | 2 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 2 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 41 | 
6 files changed, 83 insertions, 0 deletions
| diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index 0df5639a4ff4..22b5d4e687ce 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h @@ -21,6 +21,7 @@  #include <linux/path.h>  #include <linux/key.h>  #include <linux/skbuff.h> +#include <rdma/ib_verbs.h>  struct lsm_network_audit {  	int netif; @@ -50,6 +51,11 @@ struct lsm_ibpkey_audit {  	u16	pkey;  }; +struct lsm_ibendport_audit { +	char	dev_name[IB_DEVICE_NAME_MAX]; +	u8	port; +}; +  /* Auxiliary data to use in generating the audit record. */  struct common_audit_data {  	char type; @@ -66,6 +72,7 @@ struct common_audit_data {  #define LSM_AUDIT_DATA_IOCTL_OP	11  #define LSM_AUDIT_DATA_FILE	12  #define LSM_AUDIT_DATA_IBPKEY	13 +#define LSM_AUDIT_DATA_IBENDPORT 14  	union 	{  		struct path path;  		struct dentry *dentry; @@ -84,6 +91,7 @@ struct common_audit_data {  		struct lsm_ioctlop_audit *op;  		struct file *file;  		struct lsm_ibpkey_audit *ibpkey; +		struct lsm_ibendport_audit *ibendport;  	} u;  	/* this union contains LSM specific data */  	union { diff --git a/security/lsm_audit.c b/security/lsm_audit.c index c22c99fae06a..28d4c3a528ab 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -421,6 +421,11 @@ static void dump_common_audit_data(struct audit_buffer *ab,  				 a->u.ibpkey->pkey, &sbn_pfx);  		break;  	} +	case LSM_AUDIT_DATA_IBENDPORT: +		audit_log_format(ab, " device=%s port_num=%u", +				 a->u.ibendport->dev_name, +				 a->u.ibendport->port); +		break;  	} /* switch (a->type) */  } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b59255f86274..91ec46dd34d9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6169,6 +6169,29 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)  			    INFINIBAND_PKEY__ACCESS, &ad);  } +static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, +					    u8 port_num) +{ +	struct common_audit_data ad; +	int err; +	u32 sid = 0; +	struct ib_security_struct *sec = ib_sec; +	struct lsm_ibendport_audit ibendport; + +	err = security_ib_endport_sid(dev_name, port_num, &sid); + +	if (err) +		return err; + +	ad.type = LSM_AUDIT_DATA_IBENDPORT; +	strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name)); +	ibendport.port = port_num; +	ad.u.ibendport = &ibendport; +	return avc_has_perm(sec->sid, sid, +			    SECCLASS_INFINIBAND_ENDPORT, +			    INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad); +} +  static int selinux_ib_alloc_security(void **ib_sec)  {  	struct ib_security_struct *sec; @@ -6374,6 +6397,8 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {  	LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),  #ifdef CONFIG_SECURITY_INFINIBAND  	LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access), +	LSM_HOOK_INIT(ib_endport_manage_subnet, +		      selinux_ib_endport_manage_subnet),  	LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),  	LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),  #endif diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 0fec1c505f84..b9fe3434b036 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -233,6 +233,8 @@ struct security_class_mapping secclass_map[] = {  	  { COMMON_SOCK_PERMS, NULL } },  	{ "infiniband_pkey",  	  { "access", NULL } }, +	{ "infiniband_endport", +	  { "manage_subnet", NULL } },  	{ NULL }    }; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 592c014e369c..e91f08c16c0b 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -183,6 +183,8 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid);  int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid); +int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid); +  int security_netif_sid(char *name, u32 *if_sid);  int security_node_sid(u16 domain, void *addr, u32 addrlen, diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 02257d90adc9..202166612b80 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2273,6 +2273,47 @@ out:  }  /** + * security_ib_endport_sid - Obtain the SID for a subnet management interface. + * @dev_name: device name + * @port: port number + * @out_sid: security identifier + */ +int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid) +{ +	struct ocontext *c; +	int rc = 0; + +	read_lock(&policy_rwlock); + +	c = policydb.ocontexts[OCON_IBENDPORT]; +	while (c) { +		if (c->u.ibendport.port == port_num && +		    !strncmp(c->u.ibendport.dev_name, +			     dev_name, +			     IB_DEVICE_NAME_MAX)) +			break; + +		c = c->next; +	} + +	if (c) { +		if (!c->sid[0]) { +			rc = 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: +	read_unlock(&policy_rwlock); +	return rc; +} + +/**   * security_netif_sid - Obtain the SID for a network interface.   * @name: interface name   * @if_sid: interface SID | 
