All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-06 23:33 Dan Jurgens
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                   ` (3 more replies)
  0 siblings, 4 replies; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux, linux-security-module, linux-rdma; +Cc: yevgenyp, Daniel Jurgens

From: Daniel Jurgens <danielj@mellanox.com>

Changes for v2:
In response to James Morris
* Added IB core patches.

In response to Casey Schaufler
* Changed all hooks to take structure pointers instead of opaque security blobs
  for easier security module stacking.  This required adding more specific
  hooks.
* Formatting change in security/security.c to not line break call_int_hook.
* Changed so SELinux has 2 new hooks to register and deregister a callback.

In response to Or Gerlitz
* Removed my email address in copyright headers

Currently there is no way to provide granular access control to an Infiniband
fabric.  By providing an ability to restrict user access to specific virtual
subfabrics administrators can limit access to bandwidth and isolate users on
the fabric.

The approach for controlling access for Infiniband is to control access to
partitions.  A partition is similar in concept to a VLAN where each data packet
carries the partition key (PKey) in its header and isolation is enforced by
the hardware.  The partition key is not a cryptographic key, it's a 16 bit
number identifying the partition.  By controlling access to PKeys users can be
isolated on the fabric.

All Infiniband fabrics must have a subnet manager.  The subnet manager
provisions the partitions and configures the end nodes.  Each end port has a
PKey table containing all the partitions it can access.  In order to enforce
access to partitions the subnet management interface (SMI) must also be
controlled to prevent unauthorized changes to the fabric configuration. 

In order to support this there must be a capability to provide security
contexts for two new types of objects - PKeys and SMIs.

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

An Infiniband device (ibdev) is labeled by name and port number.  There is a
single access vector for ibdevs as well, called "smi".

Because RDMA allows for kernel bypass all enforcement must be done during
connection setup.  To communicate over RDMA requires a send and receive queue
called a queue pair (QP).  During the creation of a QP it is initialized
before it can be used to send or receive data.  During initialization the user
must provide the PKey and port the QP will use, at this time access can be
enforced.

Because there is a possibility that the enforcement settings or security
policy can change, a means of notifying the ib_core module of such changes is
required.  To facilitate this two LSM hooks are provided, ib_core will
register and unregister a callback function at init and cleanup respectively.
SELinux will call the callback as appropriate if it has been registered.
When the callback is called ib_core will recheck the PKey access for all
existing QPs.

Because frequent accesses to the same PKey's SID is expected a cache is
implemented which is very similar to the netport cache.

In order to properly enforce security when changes to the PKey table or
security policy or enforcement occur ib_core must track which QPs are using
each port, pkey index, and alternate path for every IB device.  This turns
modify qp and destroy qp into transactions..

When modifying a QP ib_core must associate it with the PKey index, port,
and alternate path specified.  If the QP was already associated with different
settings the QP is added to the new list prior to the modify attempt.  If
the modify succeeds then the old listing is removed.  If the modify fails
the new listing is removed and the old listing remains unchanged.

When destroying a QP the ib_qp structure is freed by the hardware driver
if the destroy is successful.  This requires storing security related
information in a separate structure. When a destroy request is in process
the ib_qp structure is in an undefined state so if there are changes to the
security policy or PKey table the security checks cannot reset the QP if it
doesn't have permission for the new setting.  If the destroy fails security
for that QP must be enforced again, and its status in the list restored. 
 If the destroy succeeds the security info can be cleaned up and freed.

There are a number of locks required to protect the QP security structure and
the QP to device/port/pkey index lists.  If multiple locks are required the
safe locking order is qp security structure mutex first, followed by any list
locks needed, which are sorted first by port followed by pkey index.

Daniel Jurgens (13):
  security: Add LSM hooks for Infiniband security
  selinux: Create policydb version for Infiniband support
  selinux: Implement Infiniband flush callback
  selinux: Allocate and free infiniband security hooks
  selinux: Implement Infiniband PKey "Access" access vector
  selinux: Add IB Device SMI access vector
  selinux: Add a cache for quicker retreival of PKey SIDs
  ib/core: IB cache enhancements to support Infiniband security
  ib/core: Enforce PKey security when modifying QPs
  ib/core: Enforce PKey security on management datagrams
  ib/core: Enforce Infiniband device SMI security
  ib/core: Track which QPs are using which port and PKey index
  ib/core: Implement the Infiniband flush callback.

 drivers/infiniband/core/Makefile                 |    2 +-
 drivers/infiniband/core/cache.c                  |   57 ++-
 drivers/infiniband/core/core_priv.h              |   95 +++
 drivers/infiniband/core/core_security.c          |  667 ++++++++++++++++++++++
 drivers/infiniband/core/device.c                 |   59 ++
 drivers/infiniband/core/mad.c                    |  115 ++++-
 drivers/infiniband/core/uverbs_cmd.c             |   20 +-
 drivers/infiniband/core/verbs.c                  |   29 +-
 include/linux/lsm_audit.h                        |   15 +
 include/linux/lsm_hooks.h                        |   71 +++
 include/linux/security.h                         |   65 +++
 include/rdma/ib_mad.h                            |    1 +
 include/rdma/ib_verbs.h                          |   47 ++
 security/Kconfig                                 |    9 +
 security/security.c                              |   82 +++
 security/selinux/Makefile                        |    2 +-
 security/selinux/hooks.c                         |  159 +++++-
 security/selinux/include/classmap.h              |    4 +
 security/selinux/include/initial_sid_to_string.h |    2 +
 security/selinux/include/objsec.h                |   11 +
 security/selinux/include/pkey.h                  |   31 +
 security/selinux/include/security.h              |    7 +-
 security/selinux/pkey.c                          |  218 +++++++
 security/selinux/ss/policydb.c                   |  129 ++++-
 security/selinux/ss/policydb.h                   |   13 +-
 security/selinux/ss/services.c                   |   84 +++
 26 files changed, 1957 insertions(+), 37 deletions(-)
 create mode 100644 drivers/infiniband/core/core_security.c
 create mode 100644 security/selinux/include/pkey.h
 create mode 100644 security/selinux/pkey.c


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

* [RFC PATCH v2 01/13] security: Add LSM hooks for Infiniband security
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
@ 2016-04-06 23:33   ` Dan Jurgens
  2016-04-06 23:33   ` [RFC PATCH v2 02/13] selinux: Create policydb version for Infiniband support Dan Jurgens
                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Add nine new hooks
 1. Allocate security contexts for Infiniband QPs.
 2. Free security contexts for Infiniband QPs.
 3. Allocate security contexts for Infiniband MAD agents.
 4. Free security contexts for Infiniband MAD agents.
 5. Enforce QP access to Pkeys
 6. Enforce MAD agent access to Pkeys
 7. Enforce MAD agent access to Infiniband devices subnet management
    interfaces
 8. A hook to register a callback to receive notifications of
    security policy or enforcement changes.  Restricting a QPs access to
    a pkey will be done during setup and not on a per packet basis
    access must be enforced again.
 9. A hook to unregister the callback.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 include/linux/lsm_hooks.h |   71 +++++++++++++++++++++++++++++++++++++++
 include/linux/security.h  |   65 +++++++++++++++++++++++++++++++++++
 security/Kconfig          |    9 +++++
 security/security.c       |   82 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 227 insertions(+), 0 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index cdee11c..ebbc15c 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -8,6 +8,7 @@
  * Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
  * Copyright (C) 2015 Intel Corporation.
  * Copyright (C) 2015 Casey Schaufler <casey-iSGtlc1asvQWG2LlvL+J4A@public.gmane.org>
+ * Copyright (C) 2016 Mellanox Techonologies
  *
  *	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
@@ -876,6 +877,50 @@
  *	associated with the TUN device's security structure.
  *	@security pointer to the TUN devices's security structure.
  *
+ * Security hooks for Infiniband
+ *
+ * @qp_pkey_access:
+ *	Check permission to access a pkey when modifing a QP.
+ *	@subnet_prefix the subnet prefix of the port being used.
+ *	@pkey the pkey to be accessed.
+ *	@qp_sec pointer to the ib_qp_security structure.
+ * @mad_agent_pkey_access:
+ *	Check permission to access a pkey when transmiting and receiving MADS.
+ *	@subnet_prefix the subnet prefix of the port being used.
+ *	@pkey the pkey to be accessed.
+ *	@mad_agent pointer to the ib_mad_agent structure.
+ * @ibdev_smi:
+ *	Check permissions to access the devices subnet management interface.
+ *	@dev_name the IB device name.
+ *	@port_num the port number the agent is being created for.
+ *	@mad_agent pointer to the ib_mad_agent structure.
+ * @ib_qp_alloc_security:
+ *	Allocate and attach a security structure to the qp_sec->q_security
+ *	field. The q_security field is initialized to NULL when the structure
+ *	is allocated.  A separate QP security structure is used instead of the
+ *	QP structure because when a QP is destroyed the memory is freed by the
+ *	hardware driver.  That operation can fail so the security info must be
+ *	maintained until the destroy completes successfully.
+ *	@qp_sec contains the ib_qp_security structure to be modified.
+ *	Return 0 if operation was successful.
+ * @ib_mad_agent_alloc_security:
+ *	Allocate and attach a security structure to the mad_agent->m_security
+ *	field. The m_security field is initialized to NULL when the structure
+ *	is allocated.
+ *	@mad_agent contains the ib_mad_agent structure to be modified.
+ *	Return 0 if operation was successful.
+ * @ib_qp_free_security:
+ *	Deallocate and clear the qp_sec->q_security field.
+ *	@qp_sec contains the ib_qp_security structure to be modified.
+ * @ib_mad_agent_free_security:
+ *	Deallocate and clear the mad_agent->m_security field.
+ *	@mad_agent contains the ib_mad_agent structure to be modified.
+ * @register_ib_flush_callback:
+ *	Provide a way for security modules to notify ib_core of policy changes.
+ *	@callback function pointer to call when policy changes.
+ * @unregister_ib_flush_callback:
+ *	Unregister the callback function.
+ *
  * Security hooks for XFRM operations.
  *
  * @xfrm_policy_alloc_security:
@@ -1578,6 +1623,21 @@ union security_list_options {
 	int (*tun_dev_open)(void *security);
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_INFINIBAND
+	int (*qp_pkey_access)(u64 subnet_prefix, u16 pkey,
+			      struct ib_qp_security *qp_sec);
+	int (*mad_agent_pkey_access)(u64 subnet_prefix, u16 pkey,
+				     struct ib_mad_agent *mad_agent);
+	int (*ibdev_smi)(const char *dev_name, u8 port,
+			 struct ib_mad_agent *mad_agent);
+	int (*ib_qp_alloc_security)(struct ib_qp_security *qp_sec);
+	int (*ib_mad_agent_alloc_security)(struct ib_mad_agent *mad_agent);
+	void (*ib_qp_free_security)(struct ib_qp_security *qp_sec);
+	void (*ib_mad_agent_free_security)(struct ib_mad_agent *mad_agent);
+	void (*register_ib_flush_callback)(void (*callback)(void));
+	void (*unregister_ib_flush_callback)(void);
+#endif	/* CONFIG_SECURITY_INFINIBAND */
+
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 	int (*xfrm_policy_alloc_security)(struct xfrm_sec_ctx **ctxp,
 					  struct xfrm_user_sec_ctx *sec_ctx,
@@ -1806,6 +1866,17 @@ struct security_hook_heads {
 	struct list_head tun_dev_open;
 	struct list_head skb_owned_by;
 #endif	/* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_INFINIBAND
+	struct list_head qp_pkey_access;
+	struct list_head mad_agent_pkey_access;
+	struct list_head ibdev_smi;
+	struct list_head ib_qp_alloc_security;
+	struct list_head ib_qp_free_security;
+	struct list_head ib_mad_agent_alloc_security;
+	struct list_head ib_mad_agent_free_security;
+	struct list_head register_ib_flush_callback;
+	struct list_head unregister_ib_flush_callback;
+#endif	/* CONFIG_SECURITY_INFINIBAND */
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 	struct list_head xfrm_policy_alloc_security;
 	struct list_head xfrm_policy_clone_security;
diff --git a/include/linux/security.h b/include/linux/security.h
index 157f0cb..1b5b48a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -6,6 +6,7 @@
  * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley-M06CiZnz2FM@public.gmane.org>
  * Copyright (C) 2001 James Morris <jmorris-G2x6lROWQUcJY7gZg3T8ig@public.gmane.org>
  * Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
+ * Copyright (C) 2016 Mellanox Techonologies
  *
  *	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
@@ -55,6 +56,8 @@ struct msg_queue;
 struct xattr;
 struct xfrm_sec_ctx;
 struct mm_struct;
+struct ib_qp_security;
+struct ib_mad_agent;
 
 /* If capable should audit the security request */
 #define SECURITY_CAP_NOAUDIT 0
@@ -1356,6 +1359,68 @@ static inline int security_tun_dev_open(void *security)
 }
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_INFINIBAND
+int security_qp_pkey_access(u64 subnet_prefix, u16 pkey,
+			    struct ib_qp_security *qp_sec);
+int security_mad_agent_pkey_access(u64 subnet_prefix, u16 pkey,
+				   struct ib_mad_agent *mad_agent);
+int security_ibdev_smi(const char *dev_name, u8 port,
+		       struct ib_mad_agent *mad_agent);
+int security_ib_qp_alloc_security(struct ib_qp_security *qp_sec);
+void security_ib_qp_free_security(struct ib_qp_security *qp_sec);
+int security_ib_mad_agent_alloc_security(struct ib_mad_agent *mad_agent);
+void security_ib_mad_agent_free_security(struct ib_mad_agent *mad_agent);
+void security_register_ib_flush_callback(void (*callback)(void));
+void security_unregister_ib_flush_callback(void);
+#else	/* CONFIG_SECURITY_INFINIBAND */
+static inline int security_qp_pkey_access(u64 subnet_prefix,
+					  u16 pkey,
+					  struct ib_qp_security *qp_sec)
+{
+	return 0;
+}
+
+static inline int security_mad_agent_pkey_access(u64 subnet_prefix,
+						 u16 pkey,
+						 struct ib_mad_agent *mad_agent)
+{
+	return 0;
+}
+
+static inline int security_ibdev_smi(const char *dev_name,
+				     u8 port,
+				     struct ib_mad_agent *mad_agent)
+{
+	return 0;
+}
+
+static inline int security_ib_qp_alloc_security(struct ib_qp_security *qp_sec)
+{
+	return 0;
+}
+
+static inline void security_ib_qp_free_security(struct ib_qp_security *qp_sec)
+{
+}
+
+static inline int security_ib_mad_agent_alloc_security(struct ib_mad_agent *mad_agent)
+{
+	return 0;
+}
+
+static inline void security_ib_mad_agent_free_security(struct ib_mad_agent *mad_agent)
+{
+}
+
+static inline void security_register_ib_flush_callback(void (*callback)(void))
+{
+}
+
+static inline void security_unregister_ib_flush_callback(void)
+{
+}
+#endif	/* CONFIG_SECURITY_INFINIBAND */
+
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 
 int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
diff --git a/security/Kconfig b/security/Kconfig
index e452378..bac790a 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -49,6 +49,15 @@ config SECURITY_NETWORK
 	  implement socket and networking access controls.
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_INFINIBAND
+	bool "Infiniband Security Hooks"
+	depends on SECURITY && INFINIBAND
+	help
+	  This enables the Infiniband security hooks.
+	  If enabled, a security module can use these hooks to
+	  implement Infiniband access controls.
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_NETWORK_XFRM
 	bool "XFRM (IPSec) Networking Security Hooks"
 	depends on XFRM && SECURITY_NETWORK
diff --git a/security/security.c b/security/security.c
index 3644b03..9549fc8 100644
--- a/security/security.c
+++ b/security/security.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2001 WireX Communications, Inc <chris-ZMHXrckZAt0AvxtiuMwx3w@public.gmane.org>
  * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
  * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley-M06CiZnz2FM@public.gmane.org>
+ * Copyright (C) 2016 Mellanox Technologies
  *
  *	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
@@ -1398,6 +1399,67 @@ EXPORT_SYMBOL(security_tun_dev_open);
 
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_INFINIBAND
+
+int security_qp_pkey_access(u64 subnet_prefix, u16 pkey,
+			    struct ib_qp_security *qp_sec)
+{
+	return call_int_hook(qp_pkey_access, 0, subnet_prefix, pkey, qp_sec);
+}
+EXPORT_SYMBOL(security_qp_pkey_access);
+
+int security_mad_agent_pkey_access(u64 subnet_prefix, u16 pkey,
+				   struct ib_mad_agent *mad_agent)
+{
+	return call_int_hook(mad_agent_pkey_access, 0, subnet_prefix, pkey, mad_agent);
+}
+EXPORT_SYMBOL(security_mad_agent_pkey_access);
+
+int security_ibdev_smi(const char *dev_name, u8 port,
+		       struct ib_mad_agent *mad_agent)
+{
+	return call_int_hook(ibdev_smi, 0, dev_name, port, mad_agent);
+}
+EXPORT_SYMBOL(security_ibdev_smi);
+
+int security_ib_qp_alloc_security(struct ib_qp_security *qp_sec)
+{
+	return call_int_hook(ib_qp_alloc_security, 0, qp_sec);
+}
+EXPORT_SYMBOL(security_ib_qp_alloc_security);
+
+void security_ib_qp_free_security(struct ib_qp_security *qp_sec)
+{
+	call_void_hook(ib_qp_free_security, qp_sec);
+}
+EXPORT_SYMBOL(security_ib_qp_free_security);
+
+int security_ib_mad_agent_alloc_security(struct ib_mad_agent *mad_agent)
+{
+	return call_int_hook(ib_mad_agent_alloc_security, 0, mad_agent);
+}
+EXPORT_SYMBOL(security_ib_mad_agent_alloc_security);
+
+void security_ib_mad_agent_free_security(struct ib_mad_agent *mad_agent)
+{
+	call_void_hook(ib_mad_agent_free_security, mad_agent);
+}
+EXPORT_SYMBOL(security_ib_mad_agent_free_security);
+
+void security_register_ib_flush_callback(void (*callback)(void))
+{
+	call_void_hook(register_ib_flush_callback, callback);
+}
+EXPORT_SYMBOL(security_register_ib_flush_callback);
+
+void security_unregister_ib_flush_callback(void)
+{
+	call_void_hook(unregister_ib_flush_callback);
+}
+EXPORT_SYMBOL(security_unregister_ib_flush_callback);
+
+#endif	/* CONFIG_SECURITY_INFINIBAND */
+
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 
 int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
@@ -1850,6 +1912,26 @@ struct security_hook_heads security_hook_heads = {
 	.tun_dev_open =	LIST_HEAD_INIT(security_hook_heads.tun_dev_open),
 	.skb_owned_by =	LIST_HEAD_INIT(security_hook_heads.skb_owned_by),
 #endif	/* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_INFINIBAND
+	.qp_pkey_access = LIST_HEAD_INIT(security_hook_heads.qp_pkey_access),
+	.mad_agent_pkey_access =
+		LIST_HEAD_INIT(security_hook_heads.mad_agent_pkey_access),
+	.ibdev_smi = LIST_HEAD_INIT(security_hook_heads.ibdev_smi),
+	.ib_qp_alloc_security =
+		LIST_HEAD_INIT(security_hook_heads.ib_qp_alloc_security),
+	.ib_qp_free_security =
+		LIST_HEAD_INIT(security_hook_heads.ib_qp_free_security),
+	.ib_mad_agent_alloc_security =
+		LIST_HEAD_INIT(security_hook_heads.ib_mad_agent_alloc_security),
+	.ib_mad_agent_free_security =
+		LIST_HEAD_INIT(security_hook_heads.ib_mad_agent_free_security),
+	.register_ib_flush_callback =
+		LIST_HEAD_INIT(security_hook_heads.register_ib_flush_callback),
+	.unregister_ib_flush_callback =
+		LIST_HEAD_INIT(security_hook_heads.unregister_ib_flush_callback),
+#endif	/* CONFIG_SECURITY_INFINIBAND */
+
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 	.xfrm_policy_alloc_security =
 		LIST_HEAD_INIT(security_hook_heads.xfrm_policy_alloc_security),
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 02/13] selinux: Create policydb version for Infiniband support
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2016-04-06 23:33   ` [RFC PATCH v2 01/13] security: Add LSM hooks for Infiniband security Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
  2016-04-06 23:33   ` [RFC PATCH v2 03/13] selinux: Implement Infiniband flush callback Dan Jurgens
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Support for Infiniband requires the addition of two new object contexts,
one for infiniband PKeys and another IB Devices.  Added handlers to read
and write the new ocontext types when reading or writing a binary policy
representation.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 security/selinux/include/security.h |    3 +-
 security/selinux/ss/policydb.c      |  129 +++++++++++++++++++++++++++++++----
 security/selinux/ss/policydb.h      |   13 +++-
 3 files changed, 128 insertions(+), 17 deletions(-)

diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 38feb55..a7e6ed2 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -36,13 +36,14 @@
 #define POLICYDB_VERSION_DEFAULT_TYPE	28
 #define POLICYDB_VERSION_CONSTRAINT_NAMES	29
 #define POLICYDB_VERSION_XPERMS_IOCTL	30
+#define POLICYDB_VERSION_INFINIBAND		31
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
 #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
 #define POLICYDB_VERSION_MAX	CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
 #else
-#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_XPERMS_IOCTL
+#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_INFINIBAND
 #endif
 
 /* Mask for just the mount related flags */
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 992a315..a69fbcd 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -17,6 +17,11 @@
  *
  *      Added support for the policy capability bitmap
  *
+ * Update: Mellanox Techonologies
+ *
+ *	Added Infiniband support
+ *
+ * Copyright (C) 2016 Mellanox Techonologies
  * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
@@ -76,81 +81,86 @@ static struct policydb_compat_info policydb_compat[] = {
 	{
 		.version	= POLICYDB_VERSION_BASE,
 		.sym_num	= SYM_NUM - 3,
-		.ocon_num	= OCON_NUM - 1,
+		.ocon_num	= OCON_NUM - 3,
 	},
 	{
 		.version	= POLICYDB_VERSION_BOOL,
 		.sym_num	= SYM_NUM - 2,
-		.ocon_num	= OCON_NUM - 1,
+		.ocon_num	= OCON_NUM - 3,
 	},
 	{
 		.version	= POLICYDB_VERSION_IPV6,
 		.sym_num	= SYM_NUM - 2,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_NLCLASS,
 		.sym_num	= SYM_NUM - 2,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_MLS,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_AVTAB,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_RANGETRANS,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_POLCAP,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_PERMISSIVE,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_BOUNDARY,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_FILENAME_TRANS,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_ROLETRANS,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_DEFAULT_TYPE,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_CONSTRAINT_NAMES,
 		.sym_num	= SYM_NUM,
-		.ocon_num	= OCON_NUM,
+		.ocon_num	= OCON_NUM - 2,
 	},
 	{
 		.version	= POLICYDB_VERSION_XPERMS_IOCTL,
 		.sym_num	= SYM_NUM,
+		.ocon_num	= OCON_NUM - 2,
+	},
+	{
+		.version	= POLICYDB_VERSION_INFINIBAND,
+		.sym_num	= SYM_NUM,
 		.ocon_num	= OCON_NUM,
 	},
 };
@@ -2219,6 +2229,58 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
 					goto out;
 				break;
 			}
+			case OCON_PKEY: {
+				rc = next_entry(nodebuf, fp, sizeof(u32) * 6);
+				if (rc)
+					goto out;
+
+				c->u.pkey.subnet_prefix = be64_to_cpu(*((__be64 *)nodebuf));
+				/* The subnet prefix is stored as an IPv6
+				 * address in the policy.
+				 *
+				 * Check that the lower 2 DWORDS are 0.
+				 */
+				if (nodebuf[2] || nodebuf[3]) {
+					rc = -EINVAL;
+					goto out;
+				}
+
+				if (nodebuf[4] > 0xffff ||
+				    nodebuf[5] > 0xffff) {
+					rc = -EINVAL;
+					goto out;
+				}
+
+				c->u.pkey.low_pkey = le32_to_cpu(nodebuf[4]);
+				c->u.pkey.high_pkey = le32_to_cpu(nodebuf[5]);
+
+				rc = context_read_and_validate(&c->context[0],
+							       p,
+							       fp);
+				if (rc)
+					goto out;
+				break;
+			}
+			case OCON_IBDEV:
+				rc = next_entry(buf, fp, sizeof(u32) * 2);
+				if (rc)
+					goto out;
+				len = le32_to_cpu(buf[0]);
+
+				rc = str_read(&c->u.ibdev.dev_name, GFP_KERNEL,
+					      fp,
+					      len);
+				if (rc)
+					goto out;
+
+				c->u.ibdev.port = le32_to_cpu(buf[1]);
+
+				rc = context_read_and_validate(&c->context[0],
+							       p,
+							       fp);
+				if (rc)
+					goto out;
+				break;
 			}
 		}
 	}
@@ -3147,6 +3209,43 @@ static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
 				if (rc)
 					return rc;
 				break;
+			case OCON_PKEY: {
+				__be64 *sbn_pfx = (__be64 *)nodebuf;
+				*sbn_pfx = cpu_to_be64(c->u.pkey.subnet_prefix);
+
+				/*
+				 * The low order 2 bits were confirmed to be 0
+				 * when the policy was loaded. Write them out
+				 * as zero
+				 */
+				nodebuf[2] = 0;
+				nodebuf[3] = 0;
+
+				nodebuf[4] = cpu_to_le32(c->u.pkey.low_pkey);
+				nodebuf[5] = cpu_to_le32(c->u.pkey.high_pkey);
+
+				rc = put_entry(nodebuf, sizeof(u32), 6, fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[0], fp);
+				if (rc)
+					return rc;
+				break;
+			}
+			case OCON_IBDEV:
+				len = strlen(c->u.ibdev.dev_name);
+				buf[0] = cpu_to_le32(len);
+				buf[1] = cpu_to_le32(c->u.ibdev.port);
+				rc = put_entry(buf, sizeof(u32), 2, fp);
+				if (rc)
+					return rc;
+				rc = put_entry(c->u.ibdev.dev_name, 1, len, fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[0], fp);
+				if (rc)
+					return rc;
+				break;
 			}
 		}
 	}
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 725d594..06c572e 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -187,6 +187,15 @@ struct ocontext {
 			u32 addr[4];
 			u32 mask[4];
 		} node6;        /* IPv6 node information */
+		struct {
+			u64 subnet_prefix;
+			u16 low_pkey;
+			u16 high_pkey;
+		} pkey;
+		struct {
+			char *dev_name;
+			u8 port;
+		} ibdev;
 	} u;
 	union {
 		u32 sclass;  /* security class for genfs */
@@ -222,7 +231,9 @@ struct genfs {
 #define OCON_NODE  4	/* nodes */
 #define OCON_FSUSE 5	/* fs_use */
 #define OCON_NODE6 6	/* IPv6 nodes */
-#define OCON_NUM   7
+#define OCON_PKEY  7    /* Infiniband PKEYs */
+#define OCON_IBDEV 8    /* Infiniband devices */
+#define OCON_NUM   9
 
 /* The policy database */
 struct policydb {
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 03/13] selinux: Implement Infiniband flush callback
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2016-04-06 23:33   ` [RFC PATCH v2 01/13] security: Add LSM hooks for Infiniband security Dan Jurgens
  2016-04-06 23:33   ` [RFC PATCH v2 02/13] selinux: Create policydb version for Infiniband support Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
  2016-04-06 23:33   ` [RFC PATCH v2 04/13] selinux: Allocate and free infiniband security hooks Dan Jurgens
                     ` (7 subsequent siblings)
  10 siblings, 0 replies; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Because access for infiniband is enforced in the setup phase of a
connection there must be a way to notify ib_core if the policy or
enforcement setting have changed.

Added register and unregister_ib_flush_callback hooks so infiniband can
setup notification of policy and enforment changes.  In the AVC reset
callback function call the ib_flush callback if it's registered. Also
renamed the callback function, the previous name was 'net' specific.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 security/selinux/hooks.c |   36 ++++++++++++++++++++++++++++++++++--
 1 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index fce7dc8..0fbf3f8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -94,6 +94,9 @@
 #include "audit.h"
 #include "avc_ss.h"
 
+static void (*ib_flush_callback)(void);
+static DEFINE_MUTEX(ib_flush_mutex);
+
 /* SECMARK reference count */
 static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
 
@@ -159,13 +162,17 @@ static int selinux_peerlbl_enabled(void)
 	return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
 }
 
-static int selinux_netcache_avc_callback(u32 event)
+static int selinux_cache_avc_callback(u32 event)
 {
 	if (event == AVC_CALLBACK_RESET) {
 		sel_netif_flush();
 		sel_netnode_flush();
 		sel_netport_flush();
 		synchronize_net();
+		mutex_lock(&ib_flush_mutex);
+		if (ib_flush_callback)
+			ib_flush_callback();
+		mutex_unlock(&ib_flush_mutex);
 	}
 	return 0;
 }
@@ -5977,6 +5984,23 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
 
 #endif
 
+#ifdef CONFIG_SECURITY_INFINIBAND
+static void selinux_register_ib_flush_callback(void (*callback)(void))
+{
+	mutex_lock(&ib_flush_mutex);
+	ib_flush_callback = callback;
+	mutex_unlock(&ib_flush_mutex);
+}
+
+static void selinux_unregister_ib_flush_callback(void)
+{
+	mutex_lock(&ib_flush_mutex);
+	ib_flush_callback = NULL;
+	mutex_unlock(&ib_flush_mutex);
+}
+
+#endif
+
 static struct security_hook_list selinux_hooks[] = {
 	LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
 	LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
@@ -6158,6 +6182,12 @@ static struct security_hook_list selinux_hooks[] = {
 	LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
 	LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
 	LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
+#ifdef CONFIG_SECURITY_INFINIBAND
+	LSM_HOOK_INIT(register_ib_flush_callback,
+		      selinux_register_ib_flush_callback),
+	LSM_HOOK_INIT(unregister_ib_flush_callback,
+		      selinux_unregister_ib_flush_callback),
+#endif
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 	LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
@@ -6217,9 +6247,11 @@ static __init int selinux_init(void)
 					    0, SLAB_PANIC, NULL);
 	avc_init();
 
+	ib_flush_callback = NULL;
+
 	security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
 
-	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
+	if (avc_add_callback(selinux_cache_avc_callback, AVC_CALLBACK_RESET))
 		panic("SELinux: Unable to register AVC netcache callback\n");
 
 	if (selinux_enforcing)
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 04/13] selinux: Allocate and free infiniband security hooks
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (2 preceding siblings ...)
  2016-04-06 23:33   ` [RFC PATCH v2 03/13] selinux: Implement Infiniband flush callback Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
       [not found]     ` <1459985638-37233-5-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2016-04-06 23:33   ` [RFC PATCH v2 05/13] selinux: Implement Infiniband PKey "Access" access vector Dan Jurgens
                     ` (6 subsequent siblings)
  10 siblings, 1 reply; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Implement and attach hooks to allocate and free Infiniband QP and MAD
agent security structures.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 include/rdma/ib_mad.h             |    1 +
 include/rdma/ib_verbs.h           |    5 +++
 security/selinux/hooks.c          |   53 +++++++++++++++++++++++++++++++++++++
 security/selinux/include/objsec.h |    5 +++
 4 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 37dd534..772135c 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -481,6 +481,7 @@ struct ib_mad_agent {
 	u32			flags;
 	u8			port_num;
 	u8			rmpp_version;
+	void			*m_security;
 };
 
 /**
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index fb2cef4..66d37b8 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1416,6 +1416,10 @@ struct ib_srq {
 	} ext;
 };
 
+struct ib_qp_security {
+	void *q_security;
+};
+
 struct ib_qp {
 	struct ib_device       *device;
 	struct ib_pd	       *pd;
@@ -1433,6 +1437,7 @@ struct ib_qp {
 	void		       *qp_context;
 	u32			qp_num;
 	enum ib_qp_type		qp_type;
+	struct ib_qp_security  *qp_sec;
 };
 
 struct ib_mr {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 0fbf3f8..3ac29bd 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -17,6 +17,7 @@
  *	Paul Moore <paul-r2n+y4ga6xFZroRs9YW3xA@public.gmane.org>
  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
  *		       Yuichi Nakamura <ynakam-FkO1umbPgv4fag7Bw7Dlfw@public.gmane.org>
+ *  Copyright (C) 2016 Mellanox Technologies
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License version 2,
@@ -83,6 +84,8 @@
 #include <linux/export.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_mad.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -5999,6 +6002,47 @@ static void selinux_unregister_ib_flush_callback(void)
 	mutex_unlock(&ib_flush_mutex);
 }
 
+static int selinux_ib_qp_alloc_security(struct ib_qp_security *qp_sec)
+{
+	struct ib_security_struct *sec;
+
+	sec = kzalloc(sizeof(*sec), GFP_ATOMIC);
+	if (!sec)
+		return -ENOMEM;
+	sec->sid = current_sid();
+
+	qp_sec->q_security = sec;
+	return 0;
+}
+
+static void selinux_ib_qp_free_security(struct ib_qp_security *qp_sec)
+{
+	struct ib_security_struct *sec = qp_sec->q_security;
+
+	qp_sec->q_security = NULL;
+	kfree(sec);
+}
+
+static int selinux_ib_mad_agent_alloc_security(struct ib_mad_agent *mad_agent)
+{
+	struct ib_security_struct *sec;
+
+	sec = kzalloc(sizeof(*sec), GFP_ATOMIC);
+	if (!sec)
+		return -ENOMEM;
+	sec->sid = current_sid();
+
+	mad_agent->m_security = sec;
+	return 0;
+}
+
+static void selinux_ib_mad_agent_free_security(struct ib_mad_agent *mad_agent)
+{
+	struct ib_security_struct *sec = mad_agent->m_security;
+
+	mad_agent->m_security = NULL;
+	kfree(sec);
+}
 #endif
 
 static struct security_hook_list selinux_hooks[] = {
@@ -6182,11 +6226,20 @@ static struct security_hook_list selinux_hooks[] = {
 	LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
 	LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
 	LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
+
 #ifdef CONFIG_SECURITY_INFINIBAND
 	LSM_HOOK_INIT(register_ib_flush_callback,
 		      selinux_register_ib_flush_callback),
 	LSM_HOOK_INIT(unregister_ib_flush_callback,
 		      selinux_unregister_ib_flush_callback),
+	LSM_HOOK_INIT(ib_qp_alloc_security,
+		      selinux_ib_qp_alloc_security),
+	LSM_HOOK_INIT(ib_qp_free_security,
+		      selinux_ib_qp_free_security),
+	LSM_HOOK_INIT(ib_mad_agent_alloc_security,
+		      selinux_ib_mad_agent_alloc_security),
+	LSM_HOOK_INIT(ib_mad_agent_free_security,
+		      selinux_ib_mad_agent_free_security),
 #endif
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index c21e135..8e7db43 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -10,6 +10,7 @@
  *
  *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
  *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+ *  Copyright (C) 2016 Mellanox Technologies
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License version 2,
@@ -128,6 +129,10 @@ struct key_security_struct {
 	u32 sid;	/* SID of key */
 };
 
+struct ib_security_struct {
+	u32 sid;        /* SID of the queue pair or MAD agent */
+};
+
 extern unsigned int selinux_checkreqprot;
 
 #endif /* _SELINUX_OBJSEC_H_ */
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 05/13] selinux: Implement Infiniband PKey "Access" access vector
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (3 preceding siblings ...)
  2016-04-06 23:33   ` [RFC PATCH v2 04/13] selinux: Allocate and free infiniband security hooks Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
  2016-04-06 23:33   ` [RFC PATCH v2 06/13] selinux: Add IB Device SMI " Dan Jurgens
                     ` (5 subsequent siblings)
  10 siblings, 0 replies; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Add a type and access vector for PKeys. Implement the qp_pkey_access
and mad_agent_pkey_access hooks to check that the caller has
permission to access the PKey on the given subnet prefix.  Add an
interface to get the PKey SID. Walk the PKey ocontexts to find an entry
for the given subnet prefix and pkey.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 include/linux/lsm_audit.h                        |    7 ++++
 security/selinux/hooks.c                         |   40 +++++++++++++++++++++
 security/selinux/include/classmap.h              |    2 +
 security/selinux/include/initial_sid_to_string.h |    1 +
 security/selinux/include/security.h              |    2 +
 security/selinux/ss/services.c                   |   41 ++++++++++++++++++++++
 6 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index ffb9c9d..8ff7eae 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -45,6 +45,11 @@ struct lsm_ioctlop_audit {
 	u16 cmd;
 };
 
+struct lsm_pkey_audit {
+	u64	subnet_prefix;
+	u16	pkey;
+};
+
 /* Auxiliary data to use in generating the audit record. */
 struct common_audit_data {
 	char type;
@@ -59,6 +64,7 @@ struct common_audit_data {
 #define LSM_AUDIT_DATA_INODE	9
 #define LSM_AUDIT_DATA_DENTRY	10
 #define LSM_AUDIT_DATA_IOCTL_OP	11
+#define LSM_AUDIT_DATA_PKEY	12
 	union 	{
 		struct path path;
 		struct dentry *dentry;
@@ -75,6 +81,7 @@ struct common_audit_data {
 #endif
 		char *kmod_name;
 		struct lsm_ioctlop_audit *op;
+		struct lsm_pkey_audit *pkey;
 	} u;
 	/* this union contains LSM specific data */
 	union {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3ac29bd..aa62f72 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6002,6 +6002,44 @@ static void selinux_unregister_ib_flush_callback(void)
 	mutex_unlock(&ib_flush_mutex);
 }
 
+static int selinux_pkey_access(u64 subnet_prefix, u16 pkey_val, void *security)
+{
+	struct common_audit_data ad;
+	int err;
+	u32 sid = 0;
+	struct ib_security_struct *sec = security;
+	struct lsm_pkey_audit pkey;
+
+	err = security_pkey_sid(subnet_prefix, pkey_val, &sid);
+
+	if (err)
+		goto out;
+
+	ad.type = LSM_AUDIT_DATA_PKEY;
+	pkey.subnet_prefix = subnet_prefix;
+	pkey.pkey = pkey_val;
+	ad.u.pkey = &pkey;
+	err = avc_has_perm(sec->sid, sid,
+			   SECCLASS_INFINIBAND_PKEY,
+			   INFINIBAND_PKEY__ACCESS, &ad);
+out:
+	return err;
+}
+
+static int selinux_qp_pkey_access(u64 subnet_prefix, u16 pkey_val,
+				  struct ib_qp_security *qp_sec)
+{
+	return selinux_pkey_access(subnet_prefix, pkey_val,
+				   qp_sec->q_security);
+}
+
+static int selinux_mad_agent_pkey_access(u64 subnet_prefix, u16 pkey_val,
+					 struct ib_mad_agent *mad_agent)
+{
+	return selinux_pkey_access(subnet_prefix, pkey_val,
+					mad_agent->m_security);
+}
+
 static int selinux_ib_qp_alloc_security(struct ib_qp_security *qp_sec)
 {
 	struct ib_security_struct *sec;
@@ -6232,6 +6270,8 @@ static struct security_hook_list selinux_hooks[] = {
 		      selinux_register_ib_flush_callback),
 	LSM_HOOK_INIT(unregister_ib_flush_callback,
 		      selinux_unregister_ib_flush_callback),
+	LSM_HOOK_INIT(qp_pkey_access, selinux_qp_pkey_access),
+	LSM_HOOK_INIT(mad_agent_pkey_access, selinux_mad_agent_pkey_access),
 	LSM_HOOK_INIT(ib_qp_alloc_security,
 		      selinux_ib_qp_alloc_security),
 	LSM_HOOK_INIT(ib_qp_free_security,
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 8fbd138..322b56c 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -157,5 +157,7 @@ struct security_class_mapping secclass_map[] = {
 	  { COMMON_SOCK_PERMS, "attach_queue", NULL } },
 	{ "binder", { "impersonate", "call", "set_context_mgr", "transfer",
 		      NULL } },
+	{ "infiniband_pkey",
+	  { "access", NULL } },
 	{ NULL }
   };
diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h
index a59b64e..8f2eefc 100644
--- a/security/selinux/include/initial_sid_to_string.h
+++ b/security/selinux/include/initial_sid_to_string.h
@@ -29,5 +29,6 @@ static const char *initial_sid_to_string[] =
     "policy",
     "scmp_packet",
     "devnull",
+    "pkey",
 };
 
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index a7e6ed2..8f1a66e 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -180,6 +180,8 @@ int security_get_user_sids(u32 callsid, char *username,
 
 int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
 
+int security_pkey_sid(u64 subnet_prefix, u16 pkey_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 ebda973..2fc48c5 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2229,6 +2229,47 @@ out:
 }
 
 /**
+ * security_pkey_sid - Obtain the SID for a pkey.
+ * @subnet_prefix: Subnet Prefix
+ * @pkey_num: pkey number
+ * @out_sid: security identifier
+ */
+int security_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
+{
+	struct ocontext *c;
+	int rc = 0;
+
+	read_lock(&policy_rwlock);
+
+	c = policydb.ocontexts[OCON_PKEY];
+	while (c) {
+		if (c->u.pkey.low_pkey <= pkey_num &&
+		    c->u.pkey.high_pkey >= pkey_num &&
+		    c->u.pkey.subnet_prefix == subnet_prefix)
+			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_PKEY;
+	}
+
+out:
+	read_unlock(&policy_rwlock);
+	return rc;
+}
+
+/**
  * security_netif_sid - Obtain the SID for a network interface.
  * @name: interface name
  * @if_sid: interface SID
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 06/13] selinux: Add IB Device SMI access vector
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (4 preceding siblings ...)
  2016-04-06 23:33   ` [RFC PATCH v2 05/13] selinux: Implement Infiniband PKey "Access" access vector Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
  2016-04-06 23:33   ` [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs Dan Jurgens
                     ` (4 subsequent siblings)
  10 siblings, 0 replies; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Add a type and access vector for infiniband devices and their subnet
management interface. Implement the ibdev_smi hook to check that the
caller has permission to access the SMI specified by the device name and
port.  Add interface to query the SID for a IB device, which walks the
IBDEV ocontexts to find an entry for the given name and port.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 include/linux/lsm_audit.h                        |    8 ++++
 security/selinux/hooks.c                         |   27 ++++++++++++++
 security/selinux/include/classmap.h              |    2 +
 security/selinux/include/initial_sid_to_string.h |    1 +
 security/selinux/include/security.h              |    2 +
 security/selinux/ss/services.c                   |   43 ++++++++++++++++++++++
 6 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 8ff7eae..9177ed3 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_pkey_audit {
 	u16	pkey;
 };
 
+struct lsm_ibdev_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;
@@ -65,6 +71,7 @@ struct common_audit_data {
 #define LSM_AUDIT_DATA_DENTRY	10
 #define LSM_AUDIT_DATA_IOCTL_OP	11
 #define LSM_AUDIT_DATA_PKEY	12
+#define LSM_AUDIT_DATA_IBDEV	13
 	union 	{
 		struct path path;
 		struct dentry *dentry;
@@ -82,6 +89,7 @@ struct common_audit_data {
 		char *kmod_name;
 		struct lsm_ioctlop_audit *op;
 		struct lsm_pkey_audit *pkey;
+		struct lsm_ibdev_audit *ibdev;
 	} u;
 	/* this union contains LSM specific data */
 	union {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index aa62f72..15c0671 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6040,6 +6040,32 @@ static int selinux_mad_agent_pkey_access(u64 subnet_prefix, u16 pkey_val,
 					mad_agent->m_security);
 }
 
+static int selinux_ibdev_smi(const char *dev_name, u8 port,
+			     struct ib_mad_agent *mad_agent)
+{
+	struct common_audit_data ad;
+	int err;
+	u32 sid = 0;
+	struct ib_security_struct *sec = mad_agent->m_security;
+	struct lsm_ibdev_audit ibdev;
+
+	err = security_ibdev_sid(dev_name, port, &sid);
+
+	if (err)
+		goto out;
+
+	ad.type = LSM_AUDIT_DATA_IBDEV;
+	strncpy(ibdev.dev_name, dev_name, sizeof(ibdev.dev_name));
+	ibdev.port = port;
+	ad.u.ibdev = &ibdev;
+	err = avc_has_perm(sec->sid, sid,
+			   SECCLASS_INFINIBAND_DEVICE,
+			   INFINIBAND_DEVICE__SMI, &ad);
+
+out:
+	return err;
+}
+
 static int selinux_ib_qp_alloc_security(struct ib_qp_security *qp_sec)
 {
 	struct ib_security_struct *sec;
@@ -6272,6 +6298,7 @@ static struct security_hook_list selinux_hooks[] = {
 		      selinux_unregister_ib_flush_callback),
 	LSM_HOOK_INIT(qp_pkey_access, selinux_qp_pkey_access),
 	LSM_HOOK_INIT(mad_agent_pkey_access, selinux_mad_agent_pkey_access),
+	LSM_HOOK_INIT(ibdev_smi, selinux_ibdev_smi),
 	LSM_HOOK_INIT(ib_qp_alloc_security,
 		      selinux_ib_qp_alloc_security),
 	LSM_HOOK_INIT(ib_qp_free_security,
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 322b56c..4521261 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -159,5 +159,7 @@ struct security_class_mapping secclass_map[] = {
 		      NULL } },
 	{ "infiniband_pkey",
 	  { "access", NULL } },
+	{ "infiniband_device",
+	  { "smi", NULL } },
 	{ NULL }
   };
diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h
index 8f2eefc..56737c3 100644
--- a/security/selinux/include/initial_sid_to_string.h
+++ b/security/selinux/include/initial_sid_to_string.h
@@ -30,5 +30,6 @@ static const char *initial_sid_to_string[] =
     "scmp_packet",
     "devnull",
     "pkey",
+    "ibdev",
 };
 
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 8f1a66e..692c3ce 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -182,6 +182,8 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
 
 int security_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid);
 
+int security_ibdev_sid(const char *dev_name, u8 port, 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 2fc48c5..e49d276 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -53,6 +53,7 @@
 #include <linux/flex_array.h>
 #include <linux/vmalloc.h>
 #include <net/netlabel.h>
+#include <rdma/ib_verbs.h>
 
 #include "flask.h"
 #include "avc.h"
@@ -2270,6 +2271,48 @@ out:
 }
 
 /**
+ * security_ibdev_sid - Obtain the SID for a subnet management interface.
+ * @dev_name: device name
+ * @port: port number
+ * @out_sid: security identifier
+ */
+int security_ibdev_sid(const char *dev_name, u8 port, u32 *out_sid)
+{
+	struct ocontext *c;
+	int rc = 0;
+
+	read_lock(&policy_rwlock);
+
+	c = policydb.ocontexts[OCON_IBDEV];
+	while (c) {
+		if (c->u.ibdev.port == port &&
+		    !strncmp(c->u.ibdev.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_IBDEV;
+	}
+
+out:
+	read_unlock(&policy_rwlock);
+	return rc;
+}
+
+/**
  * security_netif_sid - Obtain the SID for a network interface.
  * @name: interface name
  * @if_sid: interface SID
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 07/13] selinux: Add a cache for quicker retreival of PKey SIDs
  2016-04-06 23:33 [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA Dan Jurgens
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
@ 2016-04-06 23:33 ` Dan Jurgens
  2016-04-06 23:33 ` [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security Dan Jurgens
  2016-04-06 23:33 ` [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security Dan Jurgens
  3 siblings, 0 replies; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux, linux-security-module, linux-rdma; +Cc: yevgenyp, Daniel Jurgens

From: Daniel Jurgens <danielj@mellanox.com>

It is likely that the SID for the same PKey will be requested many
times.  To reduce the time to modify QPs and process MADs use a cache to
store PKey SIDs.

This code is heavily based on the "netif" and "netport" concept
originally developed by James Morris <jmorris@redhat.com> and Paul Moore
<paul@paul-moore.com> (see security/selinux/netif.c and
security/selinux/netport.c for more information)

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
Reviewed-by: Eli Cohen <eli@mellanox.com>
---
 security/selinux/Makefile         |    2 +-
 security/selinux/hooks.c          |    5 +-
 security/selinux/include/objsec.h |    6 +
 security/selinux/include/pkey.h   |   31 +++++
 security/selinux/pkey.c           |  218 +++++++++++++++++++++++++++++++++++++
 5 files changed, 260 insertions(+), 2 deletions(-)
 create mode 100644 security/selinux/include/pkey.h
 create mode 100644 security/selinux/pkey.c

diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 3411c33..a698df4 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -5,7 +5,7 @@
 obj-$(CONFIG_SECURITY_SELINUX) := selinux.o
 
 selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
-	     netnode.o netport.o exports.o \
+	     netnode.o netport.o pkey.o exports.o \
 	     ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
 	     ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 15c0671..6d794da 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -92,6 +92,7 @@
 #include "netif.h"
 #include "netnode.h"
 #include "netport.h"
+#include "pkey.h"
 #include "xfrm.h"
 #include "netlabel.h"
 #include "audit.h"
@@ -172,6 +173,8 @@ static int selinux_cache_avc_callback(u32 event)
 		sel_netnode_flush();
 		sel_netport_flush();
 		synchronize_net();
+
+		sel_pkey_flush();
 		mutex_lock(&ib_flush_mutex);
 		if (ib_flush_callback)
 			ib_flush_callback();
@@ -6010,7 +6013,7 @@ static int selinux_pkey_access(u64 subnet_prefix, u16 pkey_val, void *security)
 	struct ib_security_struct *sec = security;
 	struct lsm_pkey_audit pkey;
 
-	err = security_pkey_sid(subnet_prefix, pkey_val, &sid);
+	err = sel_pkey_sid(subnet_prefix, pkey_val, &sid);
 
 	if (err)
 		goto out;
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 8e7db43..4139f28 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -133,6 +133,12 @@ struct ib_security_struct {
 	u32 sid;        /* SID of the queue pair or MAD agent */
 };
 
+struct pkey_security_struct {
+	u64	subnet_prefix; /* Port subnet prefix */
+	u16	pkey;	/* PKey number */
+	u32	sid;	/* SID of pkey */
+};
+
 extern unsigned int selinux_checkreqprot;
 
 #endif /* _SELINUX_OBJSEC_H_ */
diff --git a/security/selinux/include/pkey.h b/security/selinux/include/pkey.h
new file mode 100644
index 0000000..58a7a3b
--- /dev/null
+++ b/security/selinux/include/pkey.h
@@ -0,0 +1,31 @@
+/*
+ * pkey table
+ *
+ * SELinux must keep a mapping of pkeys to labels/SIDs.  This
+ * mapping is maintained as part of the normal policy but a fast cache is
+ * needed to reduce the lookup overhead.
+ *
+ */
+
+/*
+ * (c) Mellanox Technologies, 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef _SELINUX_IB_H
+#define _SELINUX_IB_H
+
+void sel_pkey_flush(void);
+
+int sel_pkey_sid(u64 subnet_prefix, u16 pkey, u32 *sid);
+
+#endif
diff --git a/security/selinux/pkey.c b/security/selinux/pkey.c
new file mode 100644
index 0000000..466776a
--- /dev/null
+++ b/security/selinux/pkey.c
@@ -0,0 +1,218 @@
+/*
+ * Pkey table
+ *
+ * SELinux must keep a mapping of Infinband PKEYs to labels/SIDs.  This
+ * mapping is maintained as part of the normal policy but a fast cache is
+ * needed to reduce the lookup overhead.
+ *
+ * This code is heavily based on the "netif" and "netport" concept originally
+ * developed by
+ * James Morris <jmorris@redhat.com> and
+ * Paul Moore <paul@paul-moore.com>
+ *   (see security/selinux/netif.c and security/selinux/netport.c for more
+ *   information)
+ *
+ */
+
+/*
+ * (c) Mellanox Technologies, 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#include "pkey.h"
+#include "objsec.h"
+
+#define SEL_PKEY_HASH_SIZE       256
+#define SEL_PKEY_HASH_BKT_LIMIT   16
+
+struct sel_pkey_bkt {
+	int size;
+	struct list_head list;
+};
+
+struct sel_pkey {
+	struct pkey_security_struct psec;
+	struct list_head list;
+	struct rcu_head rcu;
+};
+
+static LIST_HEAD(sel_pkey_list);
+static DEFINE_SPINLOCK(sel_pkey_lock);
+static struct sel_pkey_bkt sel_pkey_hash[SEL_PKEY_HASH_SIZE];
+
+/**
+ * sel_pkey_hashfn - Hashing function for the pkey table
+ * @pkey: pkey number
+ *
+ * Description:
+ * This is the hashing function for the pkey table, it returns the bucket
+ * number for the given pkey.
+ *
+ */
+static unsigned int sel_pkey_hashfn(u16 pkey)
+{
+	return (pkey & (SEL_PKEY_HASH_SIZE - 1));
+}
+
+/**
+ * sel_pkey_insert - Insert a new pkey into the table
+ * @pkey: the new pkey record
+ *
+ * Description:
+ * Add a new pkey record to the hash table.
+ *
+ */
+static void sel_pkey_insert(struct sel_pkey *pkey)
+{
+	unsigned int idx;
+
+	/* we need to impose a limit on the growth of the hash table so check
+	 * this bucket to make sure it is within the specified bounds
+	 */
+	idx = sel_pkey_hashfn(pkey->psec.pkey);
+	list_add_rcu(&pkey->list, &sel_pkey_hash[idx].list);
+	if (sel_pkey_hash[idx].size == SEL_PKEY_HASH_BKT_LIMIT) {
+		struct sel_pkey *tail;
+
+		tail = list_entry(
+			rcu_dereference_protected(
+				sel_pkey_hash[idx].list.prev,
+				lockdep_is_held(&sel_pkey_lock)),
+			struct sel_pkey, list);
+		list_del_rcu(&tail->list);
+		kfree_rcu(tail, rcu);
+	} else {
+		sel_pkey_hash[idx].size++;
+	}
+}
+
+/**
+ * sel_pkey_sid_slow - Lookup the SID of a pkey using the policy
+ * @subnet_prefix: subnet prefix
+ * @pkey_num: pkey number
+ * @sid: pkey SID
+ *
+ * Description:
+ * This function determines the SID of a pkey by querying the security
+ * policy.  The result is added to the pkey table to speedup future
+ * queries.  Returns zero on success, negative values on failure.
+ *
+ */
+static int sel_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid)
+{
+	int ret = -ENOMEM;
+	struct sel_pkey *new = NULL;
+
+	spin_lock_bh(&sel_pkey_lock);
+	new = kzalloc(sizeof(*new), GFP_ATOMIC);
+	if (!new)
+		goto out;
+	ret = security_pkey_sid(subnet_prefix, pkey_num, sid);
+	if (ret != 0)
+		goto out;
+
+	new->psec.subnet_prefix = subnet_prefix;
+	new->psec.pkey = pkey_num;
+	new->psec.sid = *sid;
+	sel_pkey_insert(new);
+
+out:
+	spin_unlock_bh(&sel_pkey_lock);
+	if (unlikely(ret))
+		kfree(new);
+
+	return ret;
+}
+
+/**
+ * sel_pkey_sid - Lookup the SID of a PKEY
+ * @subnet_prefix: subnet_prefix
+ * @pkey_num: pkey number
+ * @sid: pkey SID
+ *
+ * Description:
+ * This function determines the SID of a PKEY using the fastest method
+ * possible.  First the pkey table is queried, but if an entry can't be found
+ * then the policy is queried and the result is added to the table to speedup
+ * future queries.  Returns zero on success, negative values on failure.
+ *
+ */
+int sel_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *sid)
+{
+	struct sel_pkey *pkey, *found_pkey = NULL;
+	unsigned int idx;
+
+	rcu_read_lock();
+	idx = sel_pkey_hashfn(pkey_num);
+	list_for_each_entry_rcu(pkey, &sel_pkey_hash[idx].list, list) {
+		if (pkey->psec.pkey == pkey_num &&
+		    pkey->psec.subnet_prefix == subnet_prefix) {
+			found_pkey = pkey;
+			break;
+		}
+	}
+
+	if (found_pkey) {
+		*sid = pkey->psec.sid;
+		rcu_read_unlock();
+		return 0;
+	}
+	rcu_read_unlock();
+
+	return sel_pkey_sid_slow(subnet_prefix, pkey_num, sid);
+}
+
+/**
+ * sel_pkey_flush - Flush the entire pkey table
+ *
+ * Description:
+ * Remove all entries from the pkey table
+ *
+ */
+void sel_pkey_flush(void)
+{
+	unsigned int idx;
+	struct sel_pkey *pkey, *pkey_tmp;
+
+	spin_lock_bh(&sel_pkey_lock);
+	for (idx = 0; idx < SEL_PKEY_HASH_SIZE; idx++) {
+		list_for_each_entry_safe(pkey, pkey_tmp,
+					 &sel_pkey_hash[idx].list, list) {
+			list_del_rcu(&pkey->list);
+			kfree_rcu(pkey, rcu);
+		}
+		sel_pkey_hash[idx].size = 0;
+	}
+	spin_unlock_bh(&sel_pkey_lock);
+}
+
+static __init int sel_pkey_init(void)
+{
+	int iter;
+
+	if (!selinux_enabled)
+		return 0;
+
+	for (iter = 0; iter < SEL_PKEY_HASH_SIZE; iter++) {
+		INIT_LIST_HEAD(&sel_pkey_hash[iter].list);
+		sel_pkey_hash[iter].size = 0;
+	}
+
+	return 0;
+}
+
+subsys_initcall(sel_pkey_init);
-- 
1.7.1


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

* [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security
  2016-04-06 23:33 [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA Dan Jurgens
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2016-04-06 23:33 ` [RFC PATCH v2 07/13] selinux: Add a cache for quicker retreival of PKey SIDs Dan Jurgens
@ 2016-04-06 23:33 ` Dan Jurgens
       [not found]   ` <1459985638-37233-9-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2016-04-06 23:33 ` [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security Dan Jurgens
  3 siblings, 1 reply; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux, linux-security-module, linux-rdma; +Cc: yevgenyp, Daniel Jurgens

From: Daniel Jurgens <danielj@mellanox.com>

Cache the subnet prefix and add a function to access it. Enforcing
security requires frequent queries of the subnet prefix and the pkeys in
the pkey table.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
Reviewed-by: Eli Cohen <eli@mellanox.com>
---
 drivers/infiniband/core/cache.c     |   36 ++++++++++++++++++++++++++++++++++-
 drivers/infiniband/core/core_priv.h |    3 ++
 include/rdma/ib_verbs.h             |    1 +
 3 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index cb00d59..83cf528 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -925,6 +925,26 @@ int ib_get_cached_pkey(struct ib_device *device,
 }
 EXPORT_SYMBOL(ib_get_cached_pkey);
 
+int ib_get_cached_subnet_prefix(struct ib_device *device,
+				u8                port_num,
+				u64              *sn_pfx)
+{
+	unsigned long flags;
+	int ret = 0;
+	int p = port_num - rdma_start_port(device);
+
+	if (port_num < rdma_start_port(device) ||
+	    port_num > rdma_end_port(device))
+		return -EINVAL;
+
+	read_lock_irqsave(&device->cache.lock, flags);
+	*sn_pfx = device->cache.subnet_prefix_cache[p];
+	read_unlock_irqrestore(&device->cache.lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(ib_get_cached_subnet_prefix);
+
 int ib_find_cached_pkey(struct ib_device *device,
 			u8                port_num,
 			u16               pkey,
@@ -1101,6 +1121,8 @@ static void ib_cache_update(struct ib_device *device,
 
 	device->cache.lmc_cache[port - rdma_start_port(device)] = tprops->lmc;
 
+	device->cache.subnet_prefix_cache[port - rdma_start_port(device)] =
+							tprops->subnet_prefix;
 	write_unlock_irq(&device->cache.lock);
 
 	kfree(gid_cache);
@@ -1159,8 +1181,19 @@ int ib_cache_setup_one(struct ib_device *device)
 					  (rdma_end_port(device) -
 					   rdma_start_port(device) + 1),
 					  GFP_KERNEL);
+
+	device->cache.subnet_prefix_cache = kcalloc((rdma_end_port(device) -
+						     rdma_start_port(device) + 1),
+						    sizeof(*device->cache.subnet_prefix_cache),
+						    GFP_KERNEL);
+
 	if (!device->cache.pkey_cache ||
-	    !device->cache.lmc_cache) {
+	    !device->cache.lmc_cache ||
+	    !device->cache.subnet_prefix_cache) {
+		kfree(device->cache.pkey_cache);
+		kfree(device->cache.lmc_cache);
+		kfree(device->cache.subnet_prefix_cache);
+
 		pr_warn("Couldn't allocate cache for %s\n", device->name);
 		return -ENOMEM;
 	}
@@ -1204,6 +1237,7 @@ void ib_cache_release_one(struct ib_device *device)
 	gid_table_release_one(device);
 	kfree(device->cache.pkey_cache);
 	kfree(device->cache.lmc_cache);
+	kfree(device->cache.subnet_prefix_cache);
 }
 
 void ib_cache_cleanup_one(struct ib_device *device)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index eab3221..722b866 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -137,4 +137,7 @@ static inline bool rdma_is_upper_dev_rcu(struct net_device *dev,
 	return _upper == upper;
 }
 
+int ib_get_cached_subnet_prefix(struct ib_device *device,
+				u8                port_num,
+				u64              *sn_pfx);
 #endif /* _CORE_PRIV_H */
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 66d37b8..870c5ac 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1616,6 +1616,7 @@ struct ib_cache {
 	struct ib_pkey_cache  **pkey_cache;
 	struct ib_gid_table   **gid_cache;
 	u8                     *lmc_cache;
+	u64                    *subnet_prefix_cache;
 };
 
 struct ib_dma_mapping_ops {
-- 
1.7.1


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

* [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (5 preceding siblings ...)
  2016-04-06 23:33   ` [RFC PATCH v2 06/13] selinux: Add IB Device SMI " Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
       [not found]     ` <1459985638-37233-10-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2016-04-06 23:33   ` [RFC PATCH v2 10/13] ib/core: Enforce PKey security on management datagrams Dan Jurgens
                     ` (3 subsequent siblings)
  10 siblings, 1 reply; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Allocate and free a security context when creating and destroying a QP.
This context is used for controlling access to PKeys.

When a request is made to modify a QP that changes the port, PKey index,
alternate path port, or alternate path PKey index, check that the QP has
permission for the PKey in the index on the subnet prefix of the port.
If the QP is shared make sure all handles to the QP also have access.

Store which port and pkey a QP is using.  After the reset to init
transition the user can modify the port and pkey independently.  This
adds a transactional aspect to modify QP when the port, pkey, or
alternate path change.  Permission must be checked for the new settings,
then the modify can be attempted.  If the modify fails the old setting
should be restored.

To keep the security changes isolated a new file is used to hold security
related functionality.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 drivers/infiniband/core/Makefile        |    2 +-
 drivers/infiniband/core/core_priv.h     |   41 ++++
 drivers/infiniband/core/core_security.c |  331 +++++++++++++++++++++++++++++++
 drivers/infiniband/core/uverbs_cmd.c    |   20 ++-
 drivers/infiniband/core/verbs.c         |   24 +++-
 include/rdma/ib_verbs.h                 |   28 +++-
 6 files changed, 439 insertions(+), 7 deletions(-)
 create mode 100644 drivers/infiniband/core/core_security.c

diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index f818538..48a4013 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=	ib_uverbs.o ib_ucm.o \
 
 ib_core-y :=			packer.o ud_header.o verbs.o cq.o sysfs.o \
 				device.o fmr_pool.o cache.o netlink.o \
-				roce_gid_mgmt.o
+				roce_gid_mgmt.o core_security.o
 ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
 ib_core-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o umem_rbtree.o
 
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 722b866..27f2fa8 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -140,4 +140,45 @@ static inline bool rdma_is_upper_dev_rcu(struct net_device *dev,
 int ib_get_cached_subnet_prefix(struct ib_device *device,
 				u8                port_num,
 				u64              *sn_pfx);
+
+#ifdef CONFIG_SECURITY_INFINIBAND
+int ib_security_modify_qp(struct ib_qp *qp,
+			  struct ib_qp_attr *qp_attr,
+			  int qp_attr_mask,
+			  struct ib_udata *udata);
+
+int ib_security_create_qp_security(struct ib_qp *qp);
+void ib_security_destroy_qp(struct ib_qp_security *sec);
+int ib_security_open_shared_qp(struct ib_qp *qp);
+void ib_security_close_shared_qp(struct ib_qp_security *sec);
+#else
+static inline int ib_security_modify_qp(struct ib_qp *qp,
+					struct ib_qp_attr *qp_attr,
+					int qp_attr_mask,
+					struct ib_udata *udata)
+{
+	return qp->device->modify_qp(qp->real_qp,
+				     qp_attr,
+				     qp_attr_mask,
+				     udata);
+}
+
+static inline int ib_security_create_qp_security(struct ib_qp *qp)
+{
+	return 0;
+}
+
+static inline void ib_security_destroy_qp(struct ib_qp_security *sec)
+{
+}
+
+static inline int ib_security_open_shared_qp(struct ib_qp *qp)
+{
+	return 0;
+}
+
+static inline void ib_security_close_shared_qp(struct ib_qp_security *sec)
+{
+}
+#endif
 #endif /* _CORE_PRIV_H */
diff --git a/drivers/infiniband/core/core_security.c b/drivers/infiniband/core/core_security.c
new file mode 100644
index 0000000..768edea
--- /dev/null
+++ b/drivers/infiniband/core/core_security.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef CONFIG_SECURITY_INFINIBAND
+
+#include <linux/security.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
+#include "core_priv.h"
+
+static int get_pkey_info(struct ib_device *dev,
+			 u8 port_num,
+			 u16 pkey_index,
+			 u64 *subnet_prefix,
+			 u16 *pkey)
+{
+	int err;
+
+	err = ib_get_cached_pkey(dev, port_num, pkey_index, pkey);
+	if (err)
+		return err;
+
+	err = ib_get_cached_subnet_prefix(dev, port_num, subnet_prefix);
+
+	return err;
+}
+
+static int enforce_qp_pkey_security(struct ib_device *dev,
+				    u8 port_num,
+				    u16 pkey_index,
+				    struct ib_qp_security *sec)
+{
+	struct ib_qp_security *shared_qp_sec;
+	u64 subnet_prefix;
+	int err = 0;
+	u16 pkey;
+
+	err = get_pkey_info(dev, port_num, pkey_index, &subnet_prefix, &pkey);
+	if (err)
+		return err;
+
+	err = security_qp_pkey_access(subnet_prefix, pkey, sec);
+	if (err)
+		return err;
+
+	if (sec->qp == sec->qp->real_qp) {
+		/* The caller of this function holds the QP security
+		 * mutex so this list traversal is safe
+		*/
+		list_for_each_entry(shared_qp_sec,
+				    &sec->shared_qp_list,
+				    shared_qp_list) {
+			err = security_qp_pkey_access(subnet_prefix,
+						      pkey,
+						      shared_qp_sec);
+			if (err)
+				break;
+		}
+	}
+	return err;
+}
+
+static int check_pkey(const struct ib_qp *qp,
+		      const struct ib_qp_attr *qp_attr,
+		      int qp_attr_mask)
+{
+	bool check_pkey = !!(qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT));
+
+	return check_pkey && (qp->qp_num != IB_QPT_SMI &&
+			      qp->qp_num != IB_QPT_GSI);
+}
+
+static int check_alt_pkey(const struct ib_qp *qp,
+			  const struct ib_qp_attr *qp_attr,
+			  int qp_attr_mask)
+{
+	bool check_alt_pkey = !!(qp_attr_mask & IB_QP_ALT_PATH);
+
+	return check_alt_pkey && (qp->qp_num != IB_QPT_SMI &&
+				  qp->qp_num != IB_QPT_GSI);
+}
+
+static int affects_security_settings(const struct ib_qp *qp,
+				     const struct ib_qp_attr *qp_attr,
+				     int qp_attr_mask)
+{
+	return check_pkey(qp, qp_attr, qp_attr_mask) ||
+	       check_alt_pkey(qp, qp_attr, qp_attr_mask);
+}
+
+static void begin_port_pkey_change(struct ib_qp *qp,
+				   struct ib_port_pkey *pp,
+				   struct ib_port_pkey *old_pp,
+				   u8 port_num,
+				   u16 pkey_index)
+{
+	if (pp->state == IB_PORT_PKEY_NOT_VALID ||
+	    (pkey_index != pp->pkey_index ||
+	     port_num != pp->port_num)) {
+		old_pp->pkey_index = pp->pkey_index;
+		old_pp->port_num = pp->port_num;
+		old_pp->state = pp->state;
+
+		pp->port_num = port_num;
+		pp->pkey_index = pkey_index;
+		pp->state = IB_PORT_PKEY_CHANGING;
+	}
+}
+
+static int qp_modify_enforce_security(struct ib_qp *qp,
+				      const struct ib_qp_attr *qp_attr,
+				      int qp_attr_mask)
+{
+	struct ib_qp_security *sec = qp->qp_sec;
+	int err = 0;
+
+	if (check_pkey(qp, qp_attr, qp_attr_mask)) {
+		u8 port_num = (qp_attr_mask & IB_QP_PORT) ?
+			       qp_attr->port_num :
+			       sec->ports_pkeys.main.port_num;
+
+		u16 pkey_index = (qp_attr_mask & IB_QP_PKEY_INDEX) ?
+				  qp_attr->pkey_index :
+				  sec->ports_pkeys.main.pkey_index;
+
+		err = enforce_qp_pkey_security(qp->device,
+					       port_num,
+					       pkey_index,
+					       sec);
+
+		if (err)
+			return err;
+
+		begin_port_pkey_change(qp,
+				       &sec->ports_pkeys.main,
+				       &sec->old_ports_pkeys.main,
+				       port_num,
+				       pkey_index);
+	}
+
+	if (check_alt_pkey(qp, qp_attr, qp_attr_mask)) {
+		err = enforce_qp_pkey_security(qp->device,
+					       qp_attr->alt_port_num,
+					       qp_attr->alt_pkey_index,
+					       sec);
+
+		if (err)
+			return err;
+
+		begin_port_pkey_change(qp,
+				       &sec->ports_pkeys.alt,
+				       &sec->old_ports_pkeys.alt,
+				       qp_attr->alt_port_num,
+				       qp_attr->alt_pkey_index);
+	}
+	return err;
+}
+
+static void abort_port_pkey_change(struct ib_qp *qp,
+				   struct ib_port_pkey *pp,
+				   struct ib_port_pkey *old_pp)
+{
+	if (pp->state == IB_PORT_PKEY_CHANGING) {
+		pp->pkey_index = old_pp->pkey_index;
+		pp->port_num = old_pp->port_num;
+		pp->state = old_pp->state;
+	}
+}
+
+static int cleanup_qp_pkey_associations(struct ib_qp *qp,
+					bool revert_to_old)
+{
+	struct ib_qp_security *sec = qp->qp_sec;
+
+	if (revert_to_old) {
+		abort_port_pkey_change(qp,
+				       &qp->qp_sec->ports_pkeys.main,
+				       &qp->qp_sec->old_ports_pkeys.main);
+
+		abort_port_pkey_change(qp,
+				       &qp->qp_sec->ports_pkeys.alt,
+				       &qp->qp_sec->old_ports_pkeys.alt);
+	} else {
+		if (sec->ports_pkeys.main.state == IB_PORT_PKEY_CHANGING)
+			sec->ports_pkeys.main.state = IB_PORT_PKEY_VALID;
+
+		if (sec->ports_pkeys.alt.state == IB_PORT_PKEY_CHANGING)
+			sec->ports_pkeys.alt.state = IB_PORT_PKEY_VALID;
+	}
+
+	memset(&sec->old_ports_pkeys, 0, sizeof(sec->old_ports_pkeys));
+
+	return 0;
+}
+
+int ib_security_open_shared_qp(struct ib_qp *qp)
+{
+	struct ib_qp *real_qp = qp->real_qp;
+	int err;
+
+	err = ib_security_create_qp_security(qp);
+	if (err)
+		goto out;
+
+	mutex_lock(&real_qp->qp_sec->mutex);
+
+	if (real_qp->qp_sec->ports_pkeys.main.state != IB_PORT_PKEY_NOT_VALID)
+		err = enforce_qp_pkey_security(real_qp->device,
+					       real_qp->qp_sec->ports_pkeys.main.port_num,
+					       real_qp->qp_sec->ports_pkeys.main.pkey_index,
+					       qp->qp_sec);
+	if (err)
+		goto err;
+
+	if (real_qp->qp_sec->ports_pkeys.alt.state != IB_PORT_PKEY_NOT_VALID)
+		err = enforce_qp_pkey_security(real_qp->device,
+					       real_qp->qp_sec->ports_pkeys.alt.port_num,
+					       real_qp->qp_sec->ports_pkeys.alt.pkey_index,
+					       qp->qp_sec);
+
+	if (err)
+		goto err;
+
+	if (qp != real_qp)
+		list_add(&qp->qp_sec->shared_qp_list,
+			 &real_qp->qp_sec->shared_qp_list);
+err:
+	mutex_unlock(&real_qp->qp_sec->mutex);
+	if (err)
+		ib_security_destroy_qp(qp->qp_sec);
+
+out:
+	return err;
+}
+
+void ib_security_close_shared_qp(struct ib_qp_security *sec)
+{
+	struct ib_qp *real_qp = sec->qp->real_qp;
+
+	mutex_lock(&real_qp->qp_sec->mutex);
+	list_del(&sec->shared_qp_list);
+	mutex_unlock(&real_qp->qp_sec->mutex);
+
+	ib_security_destroy_qp(sec);
+}
+
+int ib_security_create_qp_security(struct ib_qp *qp)
+{
+	int err;
+
+	qp->qp_sec = kzalloc(sizeof(*qp->qp_sec), GFP_KERNEL);
+	if (!qp->qp_sec)
+		return -ENOMEM;
+
+	qp->qp_sec->qp = qp;
+	mutex_init(&qp->qp_sec->mutex);
+	INIT_LIST_HEAD(&qp->qp_sec->shared_qp_list);
+	err = security_ib_qp_alloc_security(qp->qp_sec);
+	if (err)
+		kfree(qp->qp_sec);
+
+	return err;
+}
+EXPORT_SYMBOL(ib_security_create_qp_security);
+
+void ib_security_destroy_qp(struct ib_qp_security *sec)
+{
+	security_ib_qp_free_security(sec);
+	kfree(sec);
+}
+
+int ib_security_modify_qp(struct ib_qp *qp,
+			  struct ib_qp_attr *qp_attr,
+			  int qp_attr_mask,
+			  struct ib_udata *udata)
+{
+	int err = 0;
+	bool enforce_security = affects_security_settings(qp,
+							  qp_attr,
+							  qp_attr_mask);
+
+	if (enforce_security) {
+		mutex_lock(&qp->qp_sec->mutex);
+
+		err = qp_modify_enforce_security(qp, qp_attr, qp_attr_mask);
+	}
+
+	if (!err)
+		err = qp->device->modify_qp(qp->real_qp,
+					    qp_attr,
+					    qp_attr_mask,
+					    udata);
+	if (enforce_security) {
+		cleanup_qp_pkey_associations(qp, !!err);
+		mutex_unlock(&qp->qp_sec->mutex);
+	}
+	return err;
+}
+EXPORT_SYMBOL(ib_security_modify_qp);
+
+#endif /* CONFIG_SECURITY_INFINIBAND */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 6fdc7ec..6df15ea 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -37,7 +37,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
-
+#include <linux/security.h>
 #include <asm/uaccess.h>
 
 #include "uverbs.h"
@@ -1857,6 +1857,10 @@ static int create_qp(struct ib_uverbs_file *file,
 	}
 
 	if (cmd->qp_type != IB_QPT_XRC_TGT) {
+		ret = ib_security_create_qp_security(qp);
+		if (ret)
+			goto err_destroy;
+
 		qp->real_qp	  = qp;
 		qp->device	  = device;
 		qp->pd		  = pd;
@@ -2339,10 +2343,18 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
 		ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
 		if (ret)
 			goto release_qp;
-		ret = qp->device->modify_qp(qp, attr,
-			modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+
+		ret = ib_security_modify_qp(qp,
+					    attr,
+					    modify_qp_mask(qp->qp_type,
+							   cmd.attr_mask),
+					    &udata);
 	} else {
-		ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+		ret = ib_security_modify_qp(qp,
+					    attr,
+					    modify_qp_mask(qp->qp_type,
+							   cmd.attr_mask),
+					    NULL);
 	}
 
 	if (ret)
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 15b8adb..47000ee 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -44,6 +44,7 @@
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <net/addrconf.h>
+#include <linux/security.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
@@ -681,12 +682,19 @@ static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
 {
 	struct ib_qp *qp;
 	unsigned long flags;
+	int err;
 
 	qp = kzalloc(sizeof *qp, GFP_KERNEL);
 	if (!qp)
 		return ERR_PTR(-ENOMEM);
 
 	qp->real_qp = real_qp;
+	err = ib_security_open_shared_qp(qp);
+	if (err) {
+		kfree(qp);
+		return ERR_PTR(err);
+	}
+
 	atomic_inc(&real_qp->usecnt);
 	qp->device = real_qp->device;
 	qp->event_handler = event_handler;
@@ -728,11 +736,16 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
 {
 	struct ib_qp *qp, *real_qp;
 	struct ib_device *device;
+	int err;
 
 	device = pd ? pd->device : qp_init_attr->xrcd->device;
 	qp = device->create_qp(pd, qp_init_attr, NULL);
 
 	if (!IS_ERR(qp)) {
+		err = ib_security_create_qp_security(qp);
+		if (err)
+			goto destroy_qp;
+
 		qp->device     = device;
 		qp->real_qp    = qp;
 		qp->uobject    = NULL;
@@ -780,6 +793,10 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
 	}
 
 	return qp;
+
+destroy_qp:
+	ib_destroy_qp(qp);
+	return ERR_PTR(err);
 }
 EXPORT_SYMBOL(ib_create_qp);
 
@@ -1180,7 +1197,7 @@ int ib_modify_qp(struct ib_qp *qp,
 	if (ret)
 		return ret;
 
-	return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
+	return ib_security_modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
 }
 EXPORT_SYMBOL(ib_modify_qp);
 
@@ -1209,6 +1226,7 @@ int ib_close_qp(struct ib_qp *qp)
 	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
 
 	atomic_dec(&real_qp->usecnt);
+	ib_security_close_shared_qp(qp->qp_sec);
 	kfree(qp);
 
 	return 0;
@@ -1248,6 +1266,7 @@ int ib_destroy_qp(struct ib_qp *qp)
 	struct ib_pd *pd;
 	struct ib_cq *scq, *rcq;
 	struct ib_srq *srq;
+	struct ib_qp_security *sec;
 	int ret;
 
 	if (atomic_read(&qp->usecnt))
@@ -1260,6 +1279,7 @@ int ib_destroy_qp(struct ib_qp *qp)
 	scq  = qp->send_cq;
 	rcq  = qp->recv_cq;
 	srq  = qp->srq;
+	sec  = qp->qp_sec;
 
 	ret = qp->device->destroy_qp(qp);
 	if (!ret) {
@@ -1271,6 +1291,8 @@ int ib_destroy_qp(struct ib_qp *qp)
 			atomic_dec(&rcq->usecnt);
 		if (srq)
 			atomic_dec(&srq->usecnt);
+		if (sec)
+			ib_security_destroy_qp(sec);
 	}
 
 	return ret;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 870c5ac..f71cb47 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1416,8 +1416,34 @@ struct ib_srq {
 	} ext;
 };
 
+enum port_pkey_state {
+	IB_PORT_PKEY_NOT_VALID = 0,
+	IB_PORT_PKEY_VALID = 1,
+	IB_PORT_PKEY_CHANGING = 2,
+};
+
+struct ib_port_pkey {
+	enum port_pkey_state	state;
+	u16			pkey_index;
+	u8			port_num;
+};
+
+struct ib_ports_pkeys {
+	struct ib_port_pkey	main;
+	struct ib_port_pkey	alt;
+};
+
 struct ib_qp_security {
-	void *q_security;
+	struct ib_qp	       *qp;
+	/* Hold this mutex when changing port and pkey settings. */
+	struct mutex		mutex;
+	struct ib_ports_pkeys	ports_pkeys;
+	struct ib_ports_pkeys	old_ports_pkeys;
+	/* A list of all open shared QP handles.  Required to enforce security
+	 * properly for all users of a shared QP.
+	 */
+	struct list_head        shared_qp_list;
+	void                   *q_security;
 };
 
 struct ib_qp {
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 10/13] ib/core: Enforce PKey security on management datagrams
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (6 preceding siblings ...)
  2016-04-06 23:33   ` [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
       [not found]     ` <1459985638-37233-11-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2016-04-06 23:33   ` [RFC PATCH v2 12/13] ib/core: Track which QPs are using which port and PKey index Dan Jurgens
                     ` (2 subsequent siblings)
  10 siblings, 1 reply; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Allocate and free a security context when creating and destroying a MAD
agent.  This context is used for controlling access to PKeys.

When sending or receiving a MAD check that the agent has permission to
access the PKey for the Subnet Prefix of the port.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 drivers/infiniband/core/core_priv.h     |   14 +++++++
 drivers/infiniband/core/core_security.c |   17 ++++++++
 drivers/infiniband/core/mad.c           |   65 +++++++++++++++++++++++++++---
 3 files changed, 89 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 27f2fa8..2759a18 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -142,6 +142,11 @@ int ib_get_cached_subnet_prefix(struct ib_device *device,
 				u64              *sn_pfx);
 
 #ifdef CONFIG_SECURITY_INFINIBAND
+int ib_security_enforce_mad_agent_pkey_access(struct ib_device *dev,
+					      u8 port_num,
+					      u16 pkey_index,
+					      struct ib_mad_agent *mad_agent);
+
 int ib_security_modify_qp(struct ib_qp *qp,
 			  struct ib_qp_attr *qp_attr,
 			  int qp_attr_mask,
@@ -152,6 +157,15 @@ void ib_security_destroy_qp(struct ib_qp_security *sec);
 int ib_security_open_shared_qp(struct ib_qp *qp);
 void ib_security_close_shared_qp(struct ib_qp_security *sec);
 #else
+static inline int ib_security_enforce_mad_agent_pkey_access(
+					      struct ib_device *dev,
+					      u8 port_num,
+					      u16 pkey_index,
+					      struct ib_mad_agent *mad_agent)
+{
+	return 0;
+}
+
 static inline int ib_security_modify_qp(struct ib_qp *qp,
 					struct ib_qp_attr *qp_attr,
 					int qp_attr_mask,
diff --git a/drivers/infiniband/core/core_security.c b/drivers/infiniband/core/core_security.c
index 768edea..dda680b 100644
--- a/drivers/infiniband/core/core_security.c
+++ b/drivers/infiniband/core/core_security.c
@@ -328,4 +328,21 @@ int ib_security_modify_qp(struct ib_qp *qp,
 }
 EXPORT_SYMBOL(ib_security_modify_qp);
 
+int ib_security_enforce_mad_agent_pkey_access(struct ib_device *dev,
+					      u8 port_num,
+					      u16 pkey_index,
+					      struct ib_mad_agent *mad_agent)
+{
+	u64 subnet_prefix;
+	u16 pkey;
+	int err;
+
+	err = get_pkey_info(dev, port_num, pkey_index, &subnet_prefix, &pkey);
+	if (err)
+		return err;
+
+	return security_mad_agent_pkey_access(subnet_prefix, pkey, mad_agent);
+}
+EXPORT_SYMBOL(ib_security_enforce_mad_agent_pkey_access);
+
 #endif /* CONFIG_SECURITY_INFINIBAND */
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 9fa5bf3..907f8ee 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -40,9 +40,11 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/security.h>
 #include <rdma/ib_cache.h>
 
 #include "mad_priv.h"
+#include "core_priv.h"
 #include "mad_rmpp.h"
 #include "smi.h"
 #include "opa_smi.h"
@@ -341,11 +343,17 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
 		goto error1;
 	}
 
+	ret2 = security_ib_mad_agent_alloc_security(&mad_agent_priv->agent);
+	if (ret2) {
+		ret = ERR_PTR(ret2);
+		goto error3;
+	}
+
 	if (mad_reg_req) {
 		reg_req = kmemdup(mad_reg_req, sizeof *reg_req, GFP_KERNEL);
 		if (!reg_req) {
 			ret = ERR_PTR(-ENOMEM);
-			goto error3;
+			goto error4;
 		}
 	}
 
@@ -388,7 +396,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
 				if (method) {
 					if (method_in_use(&method,
 							   mad_reg_req))
-						goto error4;
+						goto error5;
 				}
 			}
 			ret2 = add_nonoui_reg_req(mad_reg_req, mad_agent_priv,
@@ -404,14 +412,14 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
 					if (is_vendor_method_in_use(
 							vendor_class,
 							mad_reg_req))
-						goto error4;
+						goto error5;
 				}
 			}
 			ret2 = add_oui_reg_req(mad_reg_req, mad_agent_priv);
 		}
 		if (ret2) {
 			ret = ERR_PTR(ret2);
-			goto error4;
+			goto error5;
 		}
 	}
 
@@ -421,9 +429,11 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
 
 	return &mad_agent_priv->agent;
 
-error4:
+error5:
 	spin_unlock_irqrestore(&port_priv->reg_lock, flags);
 	kfree(reg_req);
+error4:
+	security_ib_mad_agent_free_security(&mad_agent_priv->agent);
 error3:
 	kfree(mad_agent_priv);
 error1:
@@ -493,6 +503,7 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
 	struct ib_mad_agent *ret;
 	struct ib_mad_snoop_private *mad_snoop_priv;
 	int qpn;
+	int err;
 
 	/* Validate parameters */
 	if ((is_snooping_sends(mad_snoop_flags) && !snoop_handler) ||
@@ -517,6 +528,13 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
 		goto error1;
 	}
 
+	err = security_ib_mad_agent_alloc_security(&mad_snoop_priv->agent);
+
+	if (err) {
+		ret = ERR_PTR(err);
+		goto error2;
+	}
+
 	/* Now, fill in the various structures */
 	mad_snoop_priv->qp_info = &port_priv->qp_info[qpn];
 	mad_snoop_priv->agent.device = device;
@@ -527,17 +545,19 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
 	mad_snoop_priv->agent.port_num = port_num;
 	mad_snoop_priv->mad_snoop_flags = mad_snoop_flags;
 	init_completion(&mad_snoop_priv->comp);
+
 	mad_snoop_priv->snoop_index = register_snoop_agent(
 						&port_priv->qp_info[qpn],
 						mad_snoop_priv);
 	if (mad_snoop_priv->snoop_index < 0) {
 		ret = ERR_PTR(mad_snoop_priv->snoop_index);
-		goto error2;
+		goto error3;
 	}
 
 	atomic_set(&mad_snoop_priv->refcount, 1);
 	return &mad_snoop_priv->agent;
-
+error3:
+	security_ib_mad_agent_free_security(&mad_snoop_priv->agent);
 error2:
 	kfree(mad_snoop_priv);
 error1:
@@ -583,6 +603,8 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
 	deref_mad_agent(mad_agent_priv);
 	wait_for_completion(&mad_agent_priv->comp);
 
+	security_ib_mad_agent_free_security(&mad_agent_priv->agent);
+
 	kfree(mad_agent_priv->reg_req);
 	kfree(mad_agent_priv);
 }
@@ -601,6 +623,8 @@ static void unregister_mad_snoop(struct ib_mad_snoop_private *mad_snoop_priv)
 	deref_snoop_agent(mad_snoop_priv);
 	wait_for_completion(&mad_snoop_priv->comp);
 
+	security_ib_mad_agent_free_security(&mad_snoop_priv->agent);
+
 	kfree(mad_snoop_priv);
 }
 
@@ -1220,6 +1244,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
 	struct ib_mad_send_wr_private *mad_send_wr;
 	unsigned long flags;
 	int ret = -EINVAL;
+	u16 pkey_index;
 
 	/* Walk list of send WRs and post each on send list */
 	for (; send_buf; send_buf = next_send_buf) {
@@ -1228,6 +1253,16 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
 					   struct ib_mad_send_wr_private,
 					   send_buf);
 		mad_agent_priv = mad_send_wr->mad_agent_priv;
+		pkey_index = mad_send_wr->send_wr.pkey_index;
+
+		ret = ib_security_enforce_mad_agent_pkey_access(
+					mad_agent_priv->agent.device,
+					mad_agent_priv->agent.port_num,
+					pkey_index,
+					&mad_agent_priv->agent);
+
+		if (ret)
+			goto error;
 
 		if (!send_buf->mad_agent->send_handler ||
 		    (send_buf->timeout_ms &&
@@ -1962,6 +1997,16 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 	struct ib_mad_send_wr_private *mad_send_wr;
 	struct ib_mad_send_wc mad_send_wc;
 	unsigned long flags;
+	int ret;
+
+	ret = ib_security_enforce_mad_agent_pkey_access(
+					      mad_agent_priv->agent.device,
+					      mad_agent_priv->agent.port_num,
+					      mad_recv_wc->wc->pkey_index,
+					      &mad_agent_priv->agent);
+
+	if (ret)
+		goto security_error;
 
 	INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
 	list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
@@ -2019,6 +2064,12 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 						   mad_recv_wc);
 		deref_mad_agent(mad_agent_priv);
 	}
+
+	return;
+
+security_error:
+	ib_free_recv_mad(mad_recv_wc);
+	deref_mad_agent(mad_agent_priv);
 }
 
 static enum smi_action handle_ib_smi(const struct ib_mad_port_private *port_priv,
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security
  2016-04-06 23:33 [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA Dan Jurgens
                   ` (2 preceding siblings ...)
  2016-04-06 23:33 ` [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security Dan Jurgens
@ 2016-04-06 23:33 ` Dan Jurgens
       [not found]   ` <1459985638-37233-12-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  3 siblings, 1 reply; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux, linux-security-module, linux-rdma; +Cc: yevgenyp, Daniel Jurgens

From: Daniel Jurgens <danielj@mellanox.com>

During MAD and snoop agent registration for SMI QPs check that the
calling process has permission to access the SMI.

When sending and receiving MADs check that the agent has access to the
SMI if it's on an SMI QP.  Because security policy can change it's
possible permission was allowed when creating the agent, but no longer
is.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
Reviewed-by: Eli Cohen <eli@mellanox.com>
---
 drivers/infiniband/core/mad.c |   52 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 51 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 907f8ee..b5f42ad 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -349,6 +349,21 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
 		goto error3;
 	}
 
+	if (qp_type == IB_QPT_SMI) {
+		ret2 = security_ibdev_smi(device->name,
+					  port_num,
+					  &mad_agent_priv->agent);
+		if (ret2) {
+			dev_err(&device->dev,
+				"%s: Access Denied. Err: %d\n",
+				__func__,
+				ret2);
+
+			ret = ERR_PTR(ret2);
+			goto error4;
+		}
+	}
+
 	if (mad_reg_req) {
 		reg_req = kmemdup(mad_reg_req, sizeof *reg_req, GFP_KERNEL);
 		if (!reg_req) {
@@ -535,6 +550,22 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
 		goto error2;
 	}
 
+	if (qp_type == IB_QPT_SMI) {
+		err = security_ibdev_smi(device->name,
+					 port_num,
+					 &mad_snoop_priv->agent);
+
+		if (err) {
+			dev_err(&device->dev,
+				"%s: Access Denied. Err: %d\n",
+				__func__,
+				err);
+
+			ret = ERR_PTR(err);
+			goto error3;
+		}
+	}
+
 	/* Now, fill in the various structures */
 	mad_snoop_priv->qp_info = &port_priv->qp_info[qpn];
 	mad_snoop_priv->agent.device = device;
@@ -1248,6 +1279,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
 
 	/* Walk list of send WRs and post each on send list */
 	for (; send_buf; send_buf = next_send_buf) {
+		int err = 0;
 
 		mad_send_wr = container_of(send_buf,
 					   struct ib_mad_send_wr_private,
@@ -1255,6 +1287,16 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
 		mad_agent_priv = mad_send_wr->mad_agent_priv;
 		pkey_index = mad_send_wr->send_wr.pkey_index;
 
+		if (mad_agent_priv->agent.qp->qp_type == IB_QPT_SMI)
+			err = security_ibdev_smi(mad_agent_priv->agent.device->name,
+						 mad_agent_priv->agent.port_num,
+						 &mad_agent_priv->agent);
+
+		if (err) {
+			ret = err;
+			goto error;
+		}
+
 		ret = ib_security_enforce_mad_agent_pkey_access(
 					mad_agent_priv->agent.device,
 					mad_agent_priv->agent.port_num,
@@ -1997,7 +2039,15 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 	struct ib_mad_send_wr_private *mad_send_wr;
 	struct ib_mad_send_wc mad_send_wc;
 	unsigned long flags;
-	int ret;
+	int ret = 0;
+
+	if (mad_agent_priv->agent.qp->qp_type == IB_QPT_SMI)
+		ret = security_ibdev_smi(mad_agent_priv->agent.device->name,
+					 mad_agent_priv->agent.port_num,
+					 &mad_agent_priv->agent);
+
+	if (ret)
+		goto security_error;
 
 	ret = ib_security_enforce_mad_agent_pkey_access(
 					      mad_agent_priv->agent.device,
-- 
1.7.1


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

* [RFC PATCH v2 12/13] ib/core: Track which QPs are using which port and PKey index
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (7 preceding siblings ...)
  2016-04-06 23:33   ` [RFC PATCH v2 10/13] ib/core: Enforce PKey security on management datagrams Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
       [not found]     ` <1459985638-37233-13-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2016-04-06 23:33   ` [RFC PATCH v2 13/13] ib/core: Implement the Infiniband flush callback Dan Jurgens
  2016-04-11 20:11     ` Jason Gunthorpe
  10 siblings, 1 reply; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

In order to maintain access control to PKeys keep a list of which QPs
are using each PKey index on a particular port because the PKey table
can change. If that happens all QPs using a particular PKey index must
have access to the new PKey enforced.

This adds a transaction to the QP modify process.  Association with
the old port and PKey index must be maintained if the modify fails,
and must be removed if it succeeds.  Association with the new port and
Pkey index must be removed if the modify fails and maintained if it
succeeds.

1. When a QP is modified to a particular port and PKey index insert that
  QP into the list.

2. If the modify succeeds remove any prior associations.

3. If the modify fails remove the new association.

4. The alternate path port and PKey index must be maintained similarly.

When the PKey table or subnet prefix changes walk the list of QPs and
check that they have permission.  If not send the QP to the error state
and raise a fatal error event.  If it's a shared QP also make sure all
the QPs that share the real_qp also have permission.

Maintaining the list correctly also turns QP destroy into a transaction.
Before attempting to destroy the QP via the hardware driver the list
must be marked so that a cache update doesn't cause an attempt to reset
the QP in question.  After the hardware driver returns the QP security
information is cleaned up if the destroy was successful, or the PKey
security for the QP is verified and it's position in the list unmarked
if the destroy failed.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 drivers/infiniband/core/cache.c         |   21 ++-
 drivers/infiniband/core/core_priv.h     |   48 +++-
 drivers/infiniband/core/core_security.c |  427 +++++++++++++++++++++++++++----
 drivers/infiniband/core/device.c        |   33 +++
 drivers/infiniband/core/uverbs_cmd.c    |    2 +-
 drivers/infiniband/core/verbs.c         |   13 +-
 include/rdma/ib_verbs.h                 |   15 +
 7 files changed, 492 insertions(+), 67 deletions(-)

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 83cf528..a4c406d 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -53,6 +53,7 @@ struct ib_update_work {
 	struct work_struct work;
 	struct ib_device  *device;
 	u8                 port_num;
+	bool		   enforce_security;
 };
 
 union ib_gid zgid;
@@ -1037,7 +1038,8 @@ int ib_get_cached_lmc(struct ib_device *device,
 EXPORT_SYMBOL(ib_get_cached_lmc);
 
 static void ib_cache_update(struct ib_device *device,
-			    u8                port)
+			    u8                port,
+			    bool	      enforce_security)
 {
 	struct ib_port_attr       *tprops = NULL;
 	struct ib_pkey_cache      *pkey_cache = NULL, *old_pkey_cache;
@@ -1125,6 +1127,11 @@ static void ib_cache_update(struct ib_device *device,
 							tprops->subnet_prefix;
 	write_unlock_irq(&device->cache.lock);
 
+	if (enforce_security)
+		ib_security_cache_change(device,
+					 port,
+					 tprops->subnet_prefix);
+
 	kfree(gid_cache);
 	kfree(old_pkey_cache);
 	kfree(tprops);
@@ -1141,7 +1148,9 @@ static void ib_cache_task(struct work_struct *_work)
 	struct ib_update_work *work =
 		container_of(_work, struct ib_update_work, work);
 
-	ib_cache_update(work->device, work->port_num);
+	ib_cache_update(work->device,
+			work->port_num,
+			work->enforce_security);
 	kfree(work);
 }
 
@@ -1162,6 +1171,12 @@ static void ib_cache_event(struct ib_event_handler *handler,
 			INIT_WORK(&work->work, ib_cache_task);
 			work->device   = event->device;
 			work->port_num = event->element.port_num;
+			if (event->event == IB_EVENT_PKEY_CHANGE ||
+			    event->event == IB_EVENT_GID_CHANGE)
+				work->enforce_security = true;
+			else
+				work->enforce_security = false;
+
 			queue_work(ib_wq, &work->work);
 		}
 	}
@@ -1204,7 +1219,7 @@ int ib_cache_setup_one(struct ib_device *device)
 		return err;
 
 	for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p)
-		ib_cache_update(device, p + rdma_start_port(device));
+		ib_cache_update(device, p + rdma_start_port(device), true);
 
 	INIT_IB_EVENT_HANDLER(&device->cache.event_handler,
 			      device, ib_cache_event);
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 2759a18..216c288 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -38,6 +38,14 @@
 
 #include <rdma/ib_verbs.h>
 
+struct pkey_index_qp_list {
+	struct list_head    pkey_index_list;
+	u16                 pkey_index;
+	/* Lock to hold while iterating the qp_list. */
+	spinlock_t          qp_list_lock;
+	struct list_head    qp_list;
+};
+
 #if IS_ENABLED(CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS)
 int cma_configfs_init(void);
 void cma_configfs_exit(void);
@@ -147,14 +155,22 @@ int ib_security_enforce_mad_agent_pkey_access(struct ib_device *dev,
 					      u16 pkey_index,
 					      struct ib_mad_agent *mad_agent);
 
+void ib_security_destroy_port_pkey_list(struct ib_device *device);
+
+void ib_security_cache_change(struct ib_device *device,
+			      u8 port_num,
+			      u64 subnet_prefix);
+
 int ib_security_modify_qp(struct ib_qp *qp,
 			  struct ib_qp_attr *qp_attr,
 			  int qp_attr_mask,
 			  struct ib_udata *udata);
 
-int ib_security_create_qp_security(struct ib_qp *qp);
-void ib_security_destroy_qp(struct ib_qp_security *sec);
-int ib_security_open_shared_qp(struct ib_qp *qp);
+int ib_security_create_qp_security(struct ib_qp *qp, struct ib_device *dev);
+void ib_security_destroy_qp_begin(struct ib_qp_security *sec);
+void ib_security_destroy_qp_abort(struct ib_qp_security *sec);
+void ib_security_destroy_qp_end(struct ib_qp_security *sec);
+int ib_security_open_shared_qp(struct ib_qp *qp, struct ib_device *dev);
 void ib_security_close_shared_qp(struct ib_qp_security *sec);
 #else
 static inline int ib_security_enforce_mad_agent_pkey_access(
@@ -166,6 +182,16 @@ static inline int ib_security_enforce_mad_agent_pkey_access(
 	return 0;
 }
 
+static inline void ib_security_destroy_port_pkey_list(struct ib_device *device)
+{
+}
+
+static inline void ib_security_cache_change(struct ib_device *device,
+					    u8 port_num,
+					    u64 subnet_prefix)
+{
+}
+
 static inline int ib_security_modify_qp(struct ib_qp *qp,
 					struct ib_qp_attr *qp_attr,
 					int qp_attr_mask,
@@ -177,16 +203,26 @@ static inline int ib_security_modify_qp(struct ib_qp *qp,
 				     udata);
 }
 
-static inline int ib_security_create_qp_security(struct ib_qp *qp)
+static inline int ib_security_create_qp_security(struct ib_qp *qp,
+						 struct ib_device *dev)
 {
 	return 0;
 }
 
-static inline void ib_security_destroy_qp(struct ib_qp_security *sec)
+static inline void ib_security_destroy_qp_begin(struct ib_qp_security *sec)
+{
+}
+
+static inline void ib_security_destroy_qp_abort(struct ib_qp_security *sec)
+{
+}
+
+static inline void ib_security_destroy_qp_end(struct ib_qp_security *sec)
 {
 }
 
-static inline int ib_security_open_shared_qp(struct ib_qp *qp)
+static inline int ib_security_open_shared_qp(struct ib_qp *qp,
+					     struct ib_device *dev)
 {
 	return 0;
 }
diff --git a/drivers/infiniband/core/core_security.c b/drivers/infiniband/core/core_security.c
index dda680b..ebc66c1 100644
--- a/drivers/infiniband/core/core_security.c
+++ b/drivers/infiniband/core/core_security.c
@@ -1,4 +1,5 @@
-/*
+/* NEW COMMIT TO INSERT INTO REBASE
+ *
  * Copyright (c) 2016 Mellanox Technologies Ltd.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -33,11 +34,27 @@
 #ifdef CONFIG_SECURITY_INFINIBAND
 
 #include <linux/security.h>
+#include <linux/list.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
 #include "core_priv.h"
 
+static struct pkey_index_qp_list *get_pkey_index_qp_list(struct ib_device *dev,
+							 u8 port_num,
+							 u16 index)
+{
+	struct pkey_index_qp_list *tmp_pkey;
+
+	list_for_each_entry(tmp_pkey,
+			    &dev->port_pkey_list[port_num].pkey_list,
+			    pkey_index_list) {
+		if (tmp_pkey->pkey_index == index)
+			return tmp_pkey;
+	}
+	return NULL;
+}
+
 static int get_pkey_info(struct ib_device *dev,
 			 u8 port_num,
 			 u16 pkey_index,
@@ -90,6 +107,175 @@ static int enforce_qp_pkey_security(struct ib_device *dev,
 	return err;
 }
 
+static int check_qp_port_pkey_settings(struct ib_qp_security *sec)
+{
+	struct ib_qp *real_qp = sec->qp->real_qp;
+	int err = 0;
+
+	if (real_qp->qp_sec->ports_pkeys.main.state != IB_PORT_PKEY_NOT_VALID)
+		err = enforce_qp_pkey_security(real_qp->device,
+					       real_qp->qp_sec->ports_pkeys.main.port_num,
+					       real_qp->qp_sec->ports_pkeys.main.pkey_index,
+					       sec);
+	if (err)
+		goto out;
+
+	if (real_qp->qp_sec->ports_pkeys.alt.state != IB_PORT_PKEY_NOT_VALID)
+		err = enforce_qp_pkey_security(real_qp->device,
+					       real_qp->qp_sec->ports_pkeys.alt.port_num,
+					       real_qp->qp_sec->ports_pkeys.alt.pkey_index,
+					       sec);
+
+	if (err)
+		goto out;
+
+out:
+	return err;
+}
+
+static void reset_qp(struct ib_qp_security *sec)
+{
+	struct ib_qp_security *shared_qp_sec;
+	struct ib_qp_attr attr = {
+		.qp_state = IB_QPS_ERR
+	};
+	struct ib_event event = {
+		.event = IB_EVENT_QP_FATAL
+	};
+
+	mutex_lock(&sec->mutex);
+	if (sec->destroying)
+		goto unlock;
+
+	ib_modify_qp(sec->qp,
+		     &attr,
+		     IB_QP_STATE);
+
+	if (sec->qp->event_handler && sec->qp->qp_context) {
+		event.element.qp = sec->qp;
+		sec->qp->event_handler(&event,
+				       sec->qp->qp_context);
+	}
+
+	list_for_each_entry(shared_qp_sec,
+			    &sec->shared_qp_list,
+			    shared_qp_list) {
+		struct ib_qp *qp = shared_qp_sec->qp;
+
+		if (qp->event_handler && qp->qp_context) {
+			event.element.qp = qp;
+			event.device = qp->device;
+			qp->event_handler(&event,
+					  qp->qp_context);
+		}
+	}
+unlock:
+	mutex_unlock(&sec->mutex);
+}
+
+static inline void check_pkey_qps(struct pkey_index_qp_list *pkey,
+				  struct ib_device *device,
+				  u8 port_num,
+				  u64 subnet_prefix)
+{
+	struct ib_qp_security *shared_qp_sec;
+	struct ib_port_pkey *pp, *tmp_pp;
+	LIST_HEAD(reset_list);
+	u16 pkey_val;
+
+	if (!ib_get_cached_pkey(device,
+				port_num,
+				pkey->pkey_index,
+				&pkey_val)) {
+		spin_lock(&pkey->qp_list_lock);
+		list_for_each_entry(pp, &pkey->qp_list, qp_list) {
+			if (pp->sec->destroying)
+				continue;
+
+			if (security_qp_pkey_access(subnet_prefix,
+						    pkey_val,
+						    pp->sec)) {
+				list_add(&pp->reset_list,
+					 &reset_list);
+			} else {
+				list_for_each_entry(shared_qp_sec,
+						    &pp->sec->shared_qp_list,
+						    shared_qp_list) {
+					if (security_qp_pkey_access(subnet_prefix,
+								    pkey_val,
+								    shared_qp_sec)) {
+						list_add(&pp->reset_list,
+							 &reset_list);
+						break;
+					}
+				}
+			}
+		}
+		spin_unlock(&pkey->qp_list_lock);
+	}
+
+	list_for_each_entry_safe(pp,
+				 tmp_pp,
+				 &reset_list,
+				 reset_list) {
+		reset_qp(pp->sec);
+		list_del(&pp->reset_list);
+	}
+}
+
+static int port_pkey_list_insert(struct ib_port_pkey *pp,
+				 u8  port_num,
+				 u16 index)
+{
+	struct pkey_index_qp_list *pkey;
+	struct ib_device *device = pp->sec->dev;
+	int err = 0;
+
+	spin_lock(&device->port_pkey_list[port_num].list_lock);
+	pkey = get_pkey_index_qp_list(pp->sec->dev, port_num, index);
+	if (pkey)
+		goto list_qp;
+
+	pkey = kzalloc(sizeof(*pkey), GFP_ATOMIC);
+	if (!pkey) {
+		spin_unlock(&device->port_pkey_list[port_num].list_lock);
+		return -ENOMEM;
+	}
+
+	pkey->pkey_index = index;
+	spin_lock_init(&pkey->qp_list_lock);
+	INIT_LIST_HEAD(&pkey->qp_list);
+	list_add(&pkey->pkey_index_list,
+		 &device->port_pkey_list[port_num].pkey_list);
+
+list_qp:
+	spin_unlock(&device->port_pkey_list[port_num].list_lock);
+
+	spin_lock(&pkey->qp_list_lock);
+	list_add(&pp->qp_list, &pkey->qp_list);
+	spin_unlock(&pkey->qp_list_lock);
+
+	return err;
+}
+
+static int port_pkey_list_remove(struct ib_port_pkey *pp)
+{
+	struct pkey_index_qp_list *pkey;
+	int err = 0;
+
+	pkey = get_pkey_index_qp_list(pp->sec->dev,
+				      pp->port_num,
+				      pp->pkey_index);
+	if (!pkey)
+		return -ENOENT;
+
+	spin_lock(&pkey->qp_list_lock);
+	list_del(&pp->qp_list);
+	pp->state = IB_PORT_PKEY_NOT_VALID;
+	spin_unlock(&pkey->qp_list_lock);
+	return err;
+}
+
 static int check_pkey(const struct ib_qp *qp,
 		      const struct ib_qp_attr *qp_attr,
 		      int qp_attr_mask)
@@ -118,15 +304,23 @@ static int affects_security_settings(const struct ib_qp *qp,
 	       check_alt_pkey(qp, qp_attr, qp_attr_mask);
 }
 
-static void begin_port_pkey_change(struct ib_qp *qp,
-				   struct ib_port_pkey *pp,
-				   struct ib_port_pkey *old_pp,
-				   u8 port_num,
-				   u16 pkey_index)
+static int begin_port_pkey_change(struct ib_port_pkey *pp,
+				  struct ib_port_pkey *old_pp,
+				  u8 port_num,
+				  u16 pkey_index)
 {
+	int err;
+
 	if (pp->state == IB_PORT_PKEY_NOT_VALID ||
 	    (pkey_index != pp->pkey_index ||
 	     port_num != pp->port_num)) {
+		err = port_pkey_list_insert(pp,
+					    port_num,
+					    pkey_index);
+
+		if (err)
+			return err;
+
 		old_pp->pkey_index = pp->pkey_index;
 		old_pp->port_num = pp->port_num;
 		old_pp->state = pp->state;
@@ -135,6 +329,7 @@ static void begin_port_pkey_change(struct ib_qp *qp,
 		pp->pkey_index = pkey_index;
 		pp->state = IB_PORT_PKEY_CHANGING;
 	}
+	return 0;
 }
 
 static int qp_modify_enforce_security(struct ib_qp *qp,
@@ -161,11 +356,12 @@ static int qp_modify_enforce_security(struct ib_qp *qp,
 		if (err)
 			return err;
 
-		begin_port_pkey_change(qp,
-				       &sec->ports_pkeys.main,
-				       &sec->old_ports_pkeys.main,
-				       port_num,
-				       pkey_index);
+		err = begin_port_pkey_change(&sec->ports_pkeys.main,
+					     &sec->old_ports_pkeys.main,
+					     port_num,
+					     pkey_index);
+		if (err)
+			return err;
 	}
 
 	if (check_alt_pkey(qp, qp_attr, qp_attr_mask)) {
@@ -177,76 +373,123 @@ static int qp_modify_enforce_security(struct ib_qp *qp,
 		if (err)
 			return err;
 
-		begin_port_pkey_change(qp,
-				       &sec->ports_pkeys.alt,
-				       &sec->old_ports_pkeys.alt,
-				       qp_attr->alt_port_num,
-				       qp_attr->alt_pkey_index);
+		err = begin_port_pkey_change(&sec->ports_pkeys.alt,
+					     &sec->old_ports_pkeys.alt,
+					     qp_attr->alt_port_num,
+					     qp_attr->alt_pkey_index);
 	}
 	return err;
 }
 
-static void abort_port_pkey_change(struct ib_qp *qp,
-				   struct ib_port_pkey *pp,
+static void abort_port_pkey_change(struct ib_port_pkey *pp,
 				   struct ib_port_pkey *old_pp)
 {
 	if (pp->state == IB_PORT_PKEY_CHANGING) {
+		port_pkey_list_remove(pp);
+
 		pp->pkey_index = old_pp->pkey_index;
 		pp->port_num = old_pp->port_num;
 		pp->state = old_pp->state;
 	}
 }
 
+static void end_port_pkey_change(struct ib_port_pkey *pp,
+				 struct ib_port_pkey *old_pp)
+{
+	if (pp->state == IB_PORT_PKEY_CHANGING)
+		pp->state = IB_PORT_PKEY_VALID;
+
+	if (old_pp->state == IB_PORT_PKEY_VALID)
+		port_pkey_list_remove(old_pp);
+}
+
 static int cleanup_qp_pkey_associations(struct ib_qp *qp,
 					bool revert_to_old)
 {
-	struct ib_qp_security *sec = qp->qp_sec;
-
 	if (revert_to_old) {
-		abort_port_pkey_change(qp,
-				       &qp->qp_sec->ports_pkeys.main,
+		abort_port_pkey_change(&qp->qp_sec->ports_pkeys.main,
 				       &qp->qp_sec->old_ports_pkeys.main);
 
-		abort_port_pkey_change(qp,
-				       &qp->qp_sec->ports_pkeys.alt,
+		abort_port_pkey_change(&qp->qp_sec->ports_pkeys.alt,
 				       &qp->qp_sec->old_ports_pkeys.alt);
 	} else {
-		if (sec->ports_pkeys.main.state == IB_PORT_PKEY_CHANGING)
-			sec->ports_pkeys.main.state = IB_PORT_PKEY_VALID;
+		end_port_pkey_change(&qp->qp_sec->ports_pkeys.main,
+				     &qp->qp_sec->old_ports_pkeys.main);
 
-		if (sec->ports_pkeys.alt.state == IB_PORT_PKEY_CHANGING)
-			sec->ports_pkeys.alt.state = IB_PORT_PKEY_VALID;
+		end_port_pkey_change(&qp->qp_sec->ports_pkeys.alt,
+				     &qp->qp_sec->old_ports_pkeys.alt);
 	}
 
-	memset(&sec->old_ports_pkeys, 0, sizeof(sec->old_ports_pkeys));
-
 	return 0;
 }
 
-int ib_security_open_shared_qp(struct ib_qp *qp)
+static void destroy_qp_security(struct ib_qp_security *sec)
+{
+	security_ib_qp_free_security(sec);
+	kfree(sec);
+}
+
+static void qp_lists_lock_unlock(struct ib_qp_security *sec,
+				 bool lock)
+{
+	struct ib_port_pkey *prim = NULL;
+	struct ib_port_pkey *alt = NULL;
+	struct ib_port_pkey *first = NULL;
+	struct ib_port_pkey *second = NULL;
+	struct pkey_index_qp_list *pkey;
+
+	if (sec->ports_pkeys.main.state != IB_PORT_PKEY_NOT_VALID)
+		prim = &sec->ports_pkeys.main;
+
+	if (sec->ports_pkeys.alt.state != IB_PORT_PKEY_NOT_VALID)
+		alt = &sec->ports_pkeys.alt;
+
+	if (prim && alt) {
+		if (prim->port_num != alt->port_num) {
+			first = prim->port_num < alt->port_num ? prim : alt;
+			second = prim->port_num >= alt->port_num ? prim : alt;
+		} else {
+			first = prim->pkey_index < alt->pkey_index ?
+				prim : alt;
+			second = prim->pkey_index >= alt->pkey_index ?
+				alt : prim;
+		}
+	} else {
+		first = !prim ? alt : prim;
+	}
+
+	if (first) {
+		pkey = get_pkey_index_qp_list(sec->dev,
+					      first->port_num,
+					      first->pkey_index);
+		if (lock)
+			spin_lock(&pkey->qp_list_lock);
+		else
+			spin_unlock(&pkey->qp_list_lock);
+	}
+
+	if (second) {
+		pkey = get_pkey_index_qp_list(sec->dev,
+					      second->port_num,
+					      second->pkey_index);
+		if (lock)
+			spin_lock(&pkey->qp_list_lock);
+		else
+			spin_unlock(&pkey->qp_list_lock);
+	}
+}
+
+int ib_security_open_shared_qp(struct ib_qp *qp, struct ib_device *dev)
 {
 	struct ib_qp *real_qp = qp->real_qp;
 	int err;
 
-	err = ib_security_create_qp_security(qp);
+	err = ib_security_create_qp_security(qp, dev);
 	if (err)
 		goto out;
 
 	mutex_lock(&real_qp->qp_sec->mutex);
-
-	if (real_qp->qp_sec->ports_pkeys.main.state != IB_PORT_PKEY_NOT_VALID)
-		err = enforce_qp_pkey_security(real_qp->device,
-					       real_qp->qp_sec->ports_pkeys.main.port_num,
-					       real_qp->qp_sec->ports_pkeys.main.pkey_index,
-					       qp->qp_sec);
-	if (err)
-		goto err;
-
-	if (real_qp->qp_sec->ports_pkeys.alt.state != IB_PORT_PKEY_NOT_VALID)
-		err = enforce_qp_pkey_security(real_qp->device,
-					       real_qp->qp_sec->ports_pkeys.alt.port_num,
-					       real_qp->qp_sec->ports_pkeys.alt.pkey_index,
-					       qp->qp_sec);
+	err = check_qp_port_pkey_settings(qp->qp_sec);
 
 	if (err)
 		goto err;
@@ -257,7 +500,7 @@ int ib_security_open_shared_qp(struct ib_qp *qp)
 err:
 	mutex_unlock(&real_qp->qp_sec->mutex);
 	if (err)
-		ib_security_destroy_qp(qp->qp_sec);
+		destroy_qp_security(qp->qp_sec);
 
 out:
 	return err;
@@ -271,10 +514,10 @@ void ib_security_close_shared_qp(struct ib_qp_security *sec)
 	list_del(&sec->shared_qp_list);
 	mutex_unlock(&real_qp->qp_sec->mutex);
 
-	ib_security_destroy_qp(sec);
+	destroy_qp_security(sec);
 }
 
-int ib_security_create_qp_security(struct ib_qp *qp)
+int ib_security_create_qp_security(struct ib_qp *qp, struct ib_device *dev)
 {
 	int err;
 
@@ -283,6 +526,9 @@ int ib_security_create_qp_security(struct ib_qp *qp)
 		return -ENOMEM;
 
 	qp->qp_sec->qp = qp;
+	qp->qp_sec->dev = dev;
+	qp->qp_sec->ports_pkeys.main.sec = qp->qp_sec;
+	qp->qp_sec->ports_pkeys.alt.sec = qp->qp_sec;
 	mutex_init(&qp->qp_sec->mutex);
 	INIT_LIST_HEAD(&qp->qp_sec->shared_qp_list);
 	err = security_ib_qp_alloc_security(qp->qp_sec);
@@ -293,10 +539,86 @@ int ib_security_create_qp_security(struct ib_qp *qp)
 }
 EXPORT_SYMBOL(ib_security_create_qp_security);
 
-void ib_security_destroy_qp(struct ib_qp_security *sec)
+void ib_security_destroy_qp_end(struct ib_qp_security *sec)
 {
-	security_ib_qp_free_security(sec);
-	kfree(sec);
+	mutex_lock(&sec->mutex);
+	if (sec->ports_pkeys.main.state != IB_PORT_PKEY_NOT_VALID)
+		port_pkey_list_remove(&sec->ports_pkeys.main);
+
+	if (sec->ports_pkeys.alt.state != IB_PORT_PKEY_NOT_VALID)
+		port_pkey_list_remove(&sec->ports_pkeys.alt);
+
+	memset(&sec->ports_pkeys, 0, sizeof(sec->ports_pkeys));
+	mutex_unlock(&sec->mutex);
+	destroy_qp_security(sec);
+}
+
+void ib_security_destroy_qp_abort(struct ib_qp_security *sec)
+{
+	int err;
+
+	mutex_lock(&sec->mutex);
+	qp_lists_lock_unlock(sec, true);
+	err = check_qp_port_pkey_settings(sec);
+	if (err)
+		reset_qp(sec);
+	sec->destroying = false;
+	qp_lists_lock_unlock(sec, false);
+	mutex_unlock(&sec->mutex);
+}
+
+void ib_security_destroy_qp_begin(struct ib_qp_security *sec)
+{
+	mutex_lock(&sec->mutex);
+	qp_lists_lock_unlock(sec, true);
+	sec->destroying = true;
+	qp_lists_lock_unlock(sec, false);
+	mutex_unlock(&sec->mutex);
+}
+
+void ib_security_cache_change(struct ib_device *device,
+			      u8 port_num,
+			      u64 subnet_prefix)
+{
+	struct pkey_index_qp_list *pkey;
+
+	list_for_each_entry(pkey,
+			    &device->port_pkey_list[port_num].pkey_list,
+			    pkey_index_list) {
+		check_pkey_qps(pkey,
+			       device,
+			       port_num,
+			       subnet_prefix);
+	}
+}
+
+void ib_security_destroy_port_pkey_list(struct ib_device *device)
+{
+	struct pkey_index_qp_list *pkey, *tmp_pkey;
+	struct ib_port_pkey *pp, *tmp_pp;
+	int i;
+
+	for (i = rdma_start_port(device); i <= rdma_end_port(device); i++) {
+		spin_lock(&device->port_pkey_list[i].list_lock);
+		list_for_each_entry_safe(pkey,
+					 tmp_pkey,
+					 &device->port_pkey_list[i].pkey_list,
+					 pkey_index_list) {
+			spin_lock(&pkey->qp_list_lock);
+			list_for_each_entry_safe(pp,
+						 tmp_pp,
+						 &pkey->qp_list,
+						 qp_list) {
+				if (pp->state != IB_PORT_PKEY_NOT_VALID)
+					list_del(&pp->qp_list);
+			}
+			spin_unlock(&pkey->qp_list_lock);
+
+			list_del(&pkey->pkey_index_list);
+			kfree(pkey);
+		}
+		spin_unlock(&device->port_pkey_list[i].list_lock);
+	}
 }
 
 int ib_security_modify_qp(struct ib_qp *qp,
@@ -311,7 +633,6 @@ int ib_security_modify_qp(struct ib_qp *qp,
 
 	if (enforce_security) {
 		mutex_lock(&qp->qp_sec->mutex);
-
 		err = qp_modify_enforce_security(qp, qp_attr, qp_attr_mask);
 	}
 
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 1097984..f39a2a1 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -311,6 +311,30 @@ static int read_port_immutable(struct ib_device *device)
 	return 0;
 }
 
+static int setup_port_pkey_list(struct ib_device *device)
+{
+	int i;
+
+	/**
+	 * device->port_pkey_list is indexed directly by the port number,
+	 * Therefore it is declared as a 1 based array with potential empty
+	 * slots at the beginning.
+	 */
+	device->port_pkey_list = kzalloc(sizeof(*device->port_pkey_list)
+					 * (rdma_end_port(device) + 1),
+					 GFP_KERNEL);
+
+	if (!device->port_pkey_list)
+		return -ENOMEM;
+
+	for (i = 0; i < (rdma_end_port(device) + 1); i++) {
+		spin_lock_init(&device->port_pkey_list[i].list_lock);
+		INIT_LIST_HEAD(&device->port_pkey_list[i].pkey_list);
+	}
+
+	return 0;
+}
+
 /**
  * ib_register_device - Register an IB device with IB core
  * @device:Device to register
@@ -348,6 +372,12 @@ int ib_register_device(struct ib_device *device,
 		goto out;
 	}
 
+	ret = setup_port_pkey_list(device);
+	if (ret) {
+		dev_warn(device->dma_device, "Couldn't create per port_pkey_list\n");
+		goto out;
+	}
+
 	ret = ib_cache_setup_one(device);
 	if (ret) {
 		pr_warn("Couldn't set up InfiniBand P_Key/GID cache\n");
@@ -418,6 +448,9 @@ void ib_unregister_device(struct ib_device *device)
 	ib_device_unregister_sysfs(device);
 	ib_cache_cleanup_one(device);
 
+	ib_security_destroy_port_pkey_list(device);
+	kfree(device->port_pkey_list);
+
 	down_write(&lists_rwsem);
 	spin_lock_irqsave(&device->client_data_lock, flags);
 	list_for_each_entry_safe(context, tmp, &device->client_data_list, list)
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 6df15ea..a887129 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1857,7 +1857,7 @@ static int create_qp(struct ib_uverbs_file *file,
 	}
 
 	if (cmd->qp_type != IB_QPT_XRC_TGT) {
-		ret = ib_security_create_qp_security(qp);
+		ret = ib_security_create_qp_security(qp, device);
 		if (ret)
 			goto err_destroy;
 
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 47000ee..dddb2b7 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -688,13 +688,13 @@ static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
 	if (!qp)
 		return ERR_PTR(-ENOMEM);
 
-	qp->real_qp = real_qp;
-	err = ib_security_open_shared_qp(qp);
+	err = ib_security_open_shared_qp(qp, real_qp->device);
 	if (err) {
 		kfree(qp);
 		return ERR_PTR(err);
 	}
 
+	qp->real_qp = real_qp;
 	atomic_inc(&real_qp->usecnt);
 	qp->device = real_qp->device;
 	qp->event_handler = event_handler;
@@ -742,7 +742,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
 	qp = device->create_qp(pd, qp_init_attr, NULL);
 
 	if (!IS_ERR(qp)) {
-		err = ib_security_create_qp_security(qp);
+		err = ib_security_create_qp_security(qp, device);
 		if (err)
 			goto destroy_qp;
 
@@ -1280,6 +1280,8 @@ int ib_destroy_qp(struct ib_qp *qp)
 	rcq  = qp->recv_cq;
 	srq  = qp->srq;
 	sec  = qp->qp_sec;
+	if (sec)
+		ib_security_destroy_qp_begin(sec);
 
 	ret = qp->device->destroy_qp(qp);
 	if (!ret) {
@@ -1292,7 +1294,10 @@ int ib_destroy_qp(struct ib_qp *qp)
 		if (srq)
 			atomic_dec(&srq->usecnt);
 		if (sec)
-			ib_security_destroy_qp(sec);
+			ib_security_destroy_qp_end(sec);
+	} else {
+		if (sec)
+			ib_security_destroy_qp_abort(sec);
 	}
 
 	return ret;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index f71cb47..77d6158 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1422,10 +1422,15 @@ enum port_pkey_state {
 	IB_PORT_PKEY_CHANGING = 2,
 };
 
+struct ib_qp_security;
+
 struct ib_port_pkey {
 	enum port_pkey_state	state;
 	u16			pkey_index;
 	u8			port_num;
+	struct list_head	qp_list;
+	struct list_head	reset_list;
+	struct ib_qp_security  *sec;
 };
 
 struct ib_ports_pkeys {
@@ -1435,6 +1440,7 @@ struct ib_ports_pkeys {
 
 struct ib_qp_security {
 	struct ib_qp	       *qp;
+	struct ib_device       *dev;
 	/* Hold this mutex when changing port and pkey settings. */
 	struct mutex		mutex;
 	struct ib_ports_pkeys	ports_pkeys;
@@ -1444,6 +1450,7 @@ struct ib_qp_security {
 	 */
 	struct list_head        shared_qp_list;
 	void                   *q_security;
+	bool			destroying;
 };
 
 struct ib_qp {
@@ -1693,6 +1700,12 @@ struct ib_port_immutable {
 	u32                           max_mad_size;
 };
 
+struct ib_port_pkey_list {
+	/* Lock to hold while modifying the list. */
+	spinlock_t		      list_lock;
+	struct list_head	      pkey_list;
+};
+
 struct ib_device {
 	struct device                *dma_device;
 
@@ -1715,6 +1728,8 @@ struct ib_device {
 
 	int			      num_comp_vectors;
 
+	struct ib_port_pkey_list     *port_pkey_list;
+
 	struct iw_cm_verbs	     *iwcm;
 
 	int		           (*get_protocol_stats)(struct ib_device *device,
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH v2 13/13] ib/core: Implement the Infiniband flush callback.
       [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (8 preceding siblings ...)
  2016-04-06 23:33   ` [RFC PATCH v2 12/13] ib/core: Track which QPs are using which port and PKey index Dan Jurgens
@ 2016-04-06 23:33   ` Dan Jurgens
  2016-04-11 20:11     ` Jason Gunthorpe
  10 siblings, 0 replies; 90+ messages in thread
From: Dan Jurgens @ 2016-04-06 23:33 UTC (permalink / raw)
  To: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Daniel Jurgens

From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Register the callback at init and unregister it at cleanup.

When called walk the device list and call ib_security_cache_change for
each port on each device.

Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 drivers/infiniband/core/core_priv.h     |    3 ++-
 drivers/infiniband/core/core_security.c |    4 +---
 drivers/infiniband/core/device.c        |   26 ++++++++++++++++++++++++++
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 216c288..271d1e0 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -230,5 +230,6 @@ static inline int ib_security_open_shared_qp(struct ib_qp *qp,
 static inline void ib_security_close_shared_qp(struct ib_qp_security *sec)
 {
 }
-#endif
+
+#endif /* CONFIG_SECURITY_INFINIBAND */
 #endif /* _CORE_PRIV_H */
diff --git a/drivers/infiniband/core/core_security.c b/drivers/infiniband/core/core_security.c
index ebc66c1..1426731 100644
--- a/drivers/infiniband/core/core_security.c
+++ b/drivers/infiniband/core/core_security.c
@@ -581,7 +581,6 @@ void ib_security_cache_change(struct ib_device *device,
 			      u64 subnet_prefix)
 {
 	struct pkey_index_qp_list *pkey;
-
 	list_for_each_entry(pkey,
 			    &device->port_pkey_list[port_num].pkey_list,
 			    pkey_index_list) {
@@ -665,5 +664,4 @@ int ib_security_enforce_mad_agent_pkey_access(struct ib_device *dev,
 	return security_mad_agent_pkey_access(subnet_prefix, pkey, mad_agent);
 }
 EXPORT_SYMBOL(ib_security_enforce_mad_agent_pkey_access);
-
-#endif /* CONFIG_SECURITY_INFINIBAND */
+#endif
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index f39a2a1..3647098 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -335,6 +335,29 @@ static int setup_port_pkey_list(struct ib_device *device)
 	return 0;
 }
 
+static void ib_security_flush(void)
+{
+	struct ib_device *dev;
+
+	down_read(&lists_rwsem);
+	list_for_each_entry(dev, &device_list, core_list) {
+		int i;
+
+		for (i = rdma_start_port(dev); i <= rdma_end_port(dev); i++) {
+			u64 sp;
+			int ret = ib_get_cached_subnet_prefix(dev,
+							      i,
+							      &sp);
+
+			WARN_ONCE(ret,
+				  "ib_get_cached_subnet_prefix err: %d, this should never happen here\n",
+				  ret);
+			ib_security_cache_change(dev, i, sp);
+		}
+	}
+	up_read(&lists_rwsem);
+}
+
 /**
  * ib_register_device - Register an IB device with IB core
  * @device:Device to register
@@ -1016,6 +1039,8 @@ static int __init ib_core_init(void)
 		goto err_sysfs;
 	}
 
+	security_register_ib_flush_callback(&ib_security_flush);
+
 	ib_cache_setup();
 
 	return 0;
@@ -1031,6 +1056,7 @@ err:
 
 static void __exit ib_core_cleanup(void)
 {
+	security_unregister_ib_flush_callback();
 	ib_cache_cleanup();
 	ibnl_cleanup();
 	class_unregister(&ib_class);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security
  2016-04-06 23:33 ` [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security Dan Jurgens
@ 2016-04-07  2:53       ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07  2:53 UTC (permalink / raw)
  To: Dan Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	yevgenyp-VPRAkNaXOzVWk0Htik3J/w

[-- Attachment #1: Type: text/plain, Size: 1621 bytes --]

On Thu, Apr 07, 2016 at 02:33:53AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> Cache the subnet prefix and add a function to access it. Enforcing
> security requires frequent queries of the subnet prefix and the pkeys in
> the pkey table.
> 
> Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/infiniband/core/cache.c     |   36 ++++++++++++++++++++++++++++++++++-
>  drivers/infiniband/core/core_priv.h |    3 ++
>  include/rdma/ib_verbs.h             |    1 +
>  3 files changed, 39 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
> index cb00d59..83cf528 100644
> --- a/drivers/infiniband/core/cache.c
> +++ b/drivers/infiniband/core/cache.c
> @@ -925,6 +925,26 @@ int ib_get_cached_pkey(struct ib_device *device,
>  }
>  EXPORT_SYMBOL(ib_get_cached_pkey);
>  
> +int ib_get_cached_subnet_prefix(struct ib_device *device,
> +				u8                port_num,
> +				u64              *sn_pfx)
> +{
> +	unsigned long flags;
> +	int ret = 0;

It is not needed, just return 0 directly.

> +	int p = port_num - rdma_start_port(device);
> +
> +	if (port_num < rdma_start_port(device) ||
> +	    port_num > rdma_end_port(device))
> +		return -EINVAL;
> +
> +	read_lock_irqsave(&device->cache.lock, flags);
> +	*sn_pfx = device->cache.subnet_prefix_cache[p];
> +	read_unlock_irqrestore(&device->cache.lock, flags);
> +
> +	return ret;
> +}

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security
@ 2016-04-07  2:53       ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07  2:53 UTC (permalink / raw)
  To: Dan Jurgens; +Cc: selinux, linux-security-module, linux-rdma, yevgenyp

[-- Attachment #1: Type: text/plain, Size: 1540 bytes --]

On Thu, Apr 07, 2016 at 02:33:53AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Cache the subnet prefix and add a function to access it. Enforcing
> security requires frequent queries of the subnet prefix and the pkeys in
> the pkey table.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> Reviewed-by: Eli Cohen <eli@mellanox.com>
> ---
>  drivers/infiniband/core/cache.c     |   36 ++++++++++++++++++++++++++++++++++-
>  drivers/infiniband/core/core_priv.h |    3 ++
>  include/rdma/ib_verbs.h             |    1 +
>  3 files changed, 39 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
> index cb00d59..83cf528 100644
> --- a/drivers/infiniband/core/cache.c
> +++ b/drivers/infiniband/core/cache.c
> @@ -925,6 +925,26 @@ int ib_get_cached_pkey(struct ib_device *device,
>  }
>  EXPORT_SYMBOL(ib_get_cached_pkey);
>  
> +int ib_get_cached_subnet_prefix(struct ib_device *device,
> +				u8                port_num,
> +				u64              *sn_pfx)
> +{
> +	unsigned long flags;
> +	int ret = 0;

It is not needed, just return 0 directly.

> +	int p = port_num - rdma_start_port(device);
> +
> +	if (port_num < rdma_start_port(device) ||
> +	    port_num > rdma_end_port(device))
> +		return -EINVAL;
> +
> +	read_lock_irqsave(&device->cache.lock, flags);
> +	*sn_pfx = device->cache.subnet_prefix_cache[p];
> +	read_unlock_irqrestore(&device->cache.lock, flags);
> +
> +	return ret;
> +}

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security
  2016-04-06 23:33 ` [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security Dan Jurgens
@ 2016-04-07 15:09       ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 15:09 UTC (permalink / raw)
  To: Dan Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	yevgenyp-VPRAkNaXOzVWk0Htik3J/w

[-- Attachment #1: Type: text/plain, Size: 3054 bytes --]

On Thu, Apr 07, 2016 at 02:33:53AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> Cache the subnet prefix and add a function to access it. Enforcing
> security requires frequent queries of the subnet prefix and the pkeys in
> the pkey table.
> 
> Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/infiniband/core/cache.c     |   36 ++++++++++++++++++++++++++++++++++-
>  drivers/infiniband/core/core_priv.h |    3 ++
>  include/rdma/ib_verbs.h             |    1 +
>  3 files changed, 39 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
> index cb00d59..83cf528 100644
> --- a/drivers/infiniband/core/cache.c
> +++ b/drivers/infiniband/core/cache.c
> @@ -925,6 +925,26 @@ int ib_get_cached_pkey(struct ib_device *device,
>  }
>  EXPORT_SYMBOL(ib_get_cached_pkey);
>  
> +int ib_get_cached_subnet_prefix(struct ib_device *device,
> +				u8                port_num,
> +				u64              *sn_pfx)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +	int p = port_num - rdma_start_port(device);
> +
> +	if (port_num < rdma_start_port(device) ||
> +	    port_num > rdma_end_port(device))
> +		return -EINVAL;
> +
> +	read_lock_irqsave(&device->cache.lock, flags);
> +	*sn_pfx = device->cache.subnet_prefix_cache[p];
> +	read_unlock_irqrestore(&device->cache.lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(ib_get_cached_subnet_prefix);
> +
>  int ib_find_cached_pkey(struct ib_device *device,
>  			u8                port_num,
>  			u16               pkey,
> @@ -1101,6 +1121,8 @@ static void ib_cache_update(struct ib_device *device,
>  
>  	device->cache.lmc_cache[port - rdma_start_port(device)] = tprops->lmc;
>  
> +	device->cache.subnet_prefix_cache[port - rdma_start_port(device)] =
> +							tprops->subnet_prefix;
>  	write_unlock_irq(&device->cache.lock);
>  
>  	kfree(gid_cache);
> @@ -1159,8 +1181,19 @@ int ib_cache_setup_one(struct ib_device *device)
>  					  (rdma_end_port(device) -
>  					   rdma_start_port(device) + 1),
>  					  GFP_KERNEL);
> +
> +	device->cache.subnet_prefix_cache = kcalloc((rdma_end_port(device) -
> +						     rdma_start_port(device) + 1),
> +						    sizeof(*device->cache.subnet_prefix_cache),
> +						    GFP_KERNEL);
> +
>  	if (!device->cache.pkey_cache ||
> -	    !device->cache.lmc_cache) {
> +	    !device->cache.lmc_cache ||
> +	    !device->cache.subnet_prefix_cache) {
> +		kfree(device->cache.pkey_cache);
> +		kfree(device->cache.lmc_cache);
> +		kfree(device->cache.subnet_prefix_cache);
> +
>  		pr_warn("Couldn't allocate cache for %s\n", device->name);

Please remove this print. You won't miss failure in memory allocation.

>  		return -ENOMEM;
>  	}
> @@ -1204,6 +1237,7 @@ void ib_cache_release_one(struct ib_device *device)
>  	gid_table_release_one(device);

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security
@ 2016-04-07 15:09       ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 15:09 UTC (permalink / raw)
  To: Dan Jurgens; +Cc: selinux, linux-security-module, linux-rdma, yevgenyp

[-- Attachment #1: Type: text/plain, Size: 2973 bytes --]

On Thu, Apr 07, 2016 at 02:33:53AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Cache the subnet prefix and add a function to access it. Enforcing
> security requires frequent queries of the subnet prefix and the pkeys in
> the pkey table.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> Reviewed-by: Eli Cohen <eli@mellanox.com>
> ---
>  drivers/infiniband/core/cache.c     |   36 ++++++++++++++++++++++++++++++++++-
>  drivers/infiniband/core/core_priv.h |    3 ++
>  include/rdma/ib_verbs.h             |    1 +
>  3 files changed, 39 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
> index cb00d59..83cf528 100644
> --- a/drivers/infiniband/core/cache.c
> +++ b/drivers/infiniband/core/cache.c
> @@ -925,6 +925,26 @@ int ib_get_cached_pkey(struct ib_device *device,
>  }
>  EXPORT_SYMBOL(ib_get_cached_pkey);
>  
> +int ib_get_cached_subnet_prefix(struct ib_device *device,
> +				u8                port_num,
> +				u64              *sn_pfx)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +	int p = port_num - rdma_start_port(device);
> +
> +	if (port_num < rdma_start_port(device) ||
> +	    port_num > rdma_end_port(device))
> +		return -EINVAL;
> +
> +	read_lock_irqsave(&device->cache.lock, flags);
> +	*sn_pfx = device->cache.subnet_prefix_cache[p];
> +	read_unlock_irqrestore(&device->cache.lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(ib_get_cached_subnet_prefix);
> +
>  int ib_find_cached_pkey(struct ib_device *device,
>  			u8                port_num,
>  			u16               pkey,
> @@ -1101,6 +1121,8 @@ static void ib_cache_update(struct ib_device *device,
>  
>  	device->cache.lmc_cache[port - rdma_start_port(device)] = tprops->lmc;
>  
> +	device->cache.subnet_prefix_cache[port - rdma_start_port(device)] =
> +							tprops->subnet_prefix;
>  	write_unlock_irq(&device->cache.lock);
>  
>  	kfree(gid_cache);
> @@ -1159,8 +1181,19 @@ int ib_cache_setup_one(struct ib_device *device)
>  					  (rdma_end_port(device) -
>  					   rdma_start_port(device) + 1),
>  					  GFP_KERNEL);
> +
> +	device->cache.subnet_prefix_cache = kcalloc((rdma_end_port(device) -
> +						     rdma_start_port(device) + 1),
> +						    sizeof(*device->cache.subnet_prefix_cache),
> +						    GFP_KERNEL);
> +
>  	if (!device->cache.pkey_cache ||
> -	    !device->cache.lmc_cache) {
> +	    !device->cache.lmc_cache ||
> +	    !device->cache.subnet_prefix_cache) {
> +		kfree(device->cache.pkey_cache);
> +		kfree(device->cache.lmc_cache);
> +		kfree(device->cache.subnet_prefix_cache);
> +
>  		pr_warn("Couldn't allocate cache for %s\n", device->name);

Please remove this print. You won't miss failure in memory allocation.

>  		return -ENOMEM;
>  	}
> @@ -1204,6 +1237,7 @@ void ib_cache_release_one(struct ib_device *device)
>  	gid_table_release_one(device);

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security
  2016-04-07  2:53       ` Leon Romanovsky
@ 2016-04-07 15:43         ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 15:43 UTC (permalink / raw)
  To: leon-2ukJVAZIZ/Y
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA

On 4/6/2016 9:53 PM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:53AM +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>>
>> +	int ret = 0;
> 
> It is not needed, just return 0 directly.

Okay

On 4/7/2016 10:24 AM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:53AM +0300, Dan Jurgens wrote:
>> pr_warn("Couldn't allocate cache for %s\n", device->name);
>
> Please remove this print. You won't miss failure in memory allocation.

Sure, I can do that.










_______________________________________________
Selinux mailing list
Selinux-+05T5uksL2qpZYMLLGbcSA@public.gmane.org
To unsubscribe, send email to Selinux-leave-+05T5uksL2pAGbPMOrvdOA@public.gmane.org
To get help, send an email containing "help" to Selinux-request-+05T5uksL2pAGbPMOrvdOA@public.gmane.org

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

* Re: [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security
@ 2016-04-07 15:43         ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 15:43 UTC (permalink / raw)
  To: leon; +Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/6/2016 9:53 PM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:53AM +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>> +	int ret = 0;
> 
> It is not needed, just return 0 directly.

Okay

On 4/7/2016 10:24 AM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:53AM +0300, Dan Jurgens wrote:
>> pr_warn("Couldn't allocate cache for %s\n", device->name);
>
> Please remove this print. You won't miss failure in memory allocation.

Sure, I can do that.

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
  2016-04-06 23:33   ` [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs Dan Jurgens
@ 2016-04-07 16:31         ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 16:31 UTC (permalink / raw)
  To: Dan Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	yevgenyp-VPRAkNaXOzVWk0Htik3J/w

[-- Attachment #1: Type: text/plain, Size: 20097 bytes --]

On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> Allocate and free a security context when creating and destroying a QP.
> This context is used for controlling access to PKeys.
> 
> When a request is made to modify a QP that changes the port, PKey index,
> alternate path port, or alternate path PKey index, check that the QP has
> permission for the PKey in the index on the subnet prefix of the port.
> If the QP is shared make sure all handles to the QP also have access.
> 
> Store which port and pkey a QP is using.  After the reset to init
> transition the user can modify the port and pkey independently.  This
> adds a transactional aspect to modify QP when the port, pkey, or
> alternate path change.  Permission must be checked for the new settings,
> then the modify can be attempted.  If the modify fails the old setting
> should be restored.
> 
> To keep the security changes isolated a new file is used to hold security
> related functionality.
> 
> Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/infiniband/core/Makefile        |    2 +-
>  drivers/infiniband/core/core_priv.h     |   41 ++++
>  drivers/infiniband/core/core_security.c |  331 +++++++++++++++++++++++++++++++

We are already in core, there is no need to call files core_XXX.

>  drivers/infiniband/core/uverbs_cmd.c    |   20 ++-
>  drivers/infiniband/core/verbs.c         |   24 +++-
>  include/rdma/ib_verbs.h                 |   28 +++-
>  6 files changed, 439 insertions(+), 7 deletions(-)
>  create mode 100644 drivers/infiniband/core/core_security.c
> 
> diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
> index f818538..48a4013 100644
> --- a/drivers/infiniband/core/Makefile
> +++ b/drivers/infiniband/core/Makefile
> @@ -10,7 +10,7 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=	ib_uverbs.o ib_ucm.o \
>  
>  ib_core-y :=			packer.o ud_header.o verbs.o cq.o sysfs.o \
>  				device.o fmr_pool.o cache.o netlink.o \
> -				roce_gid_mgmt.o
> +				roce_gid_mgmt.o core_security.o
>  ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
>  ib_core-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o umem_rbtree.o
>  
> diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
> index 722b866..27f2fa8 100644
> --- a/drivers/infiniband/core/core_priv.h
> +++ b/drivers/infiniband/core/core_priv.h
> @@ -140,4 +140,45 @@ static inline bool rdma_is_upper_dev_rcu(struct net_device *dev,
>  int ib_get_cached_subnet_prefix(struct ib_device *device,
>  				u8                port_num,
>  				u64              *sn_pfx);
> +
> +#ifdef CONFIG_SECURITY_INFINIBAND
> +int ib_security_modify_qp(struct ib_qp *qp,
> +			  struct ib_qp_attr *qp_attr,
> +			  int qp_attr_mask,
> +			  struct ib_udata *udata);
> +
> +int ib_security_create_qp_security(struct ib_qp *qp);

Why do we need xx_SECURITY_xxxxx_SECURITY in name?

> +void ib_security_destroy_qp(struct ib_qp_security *sec);
> +int ib_security_open_shared_qp(struct ib_qp *qp);
> +void ib_security_close_shared_qp(struct ib_qp_security *sec);
> +#else
> +static inline int ib_security_modify_qp(struct ib_qp *qp,
> +					struct ib_qp_attr *qp_attr,
> +					int qp_attr_mask,
> +					struct ib_udata *udata)
> +{
> +	return qp->device->modify_qp(qp->real_qp,
> +				     qp_attr,
> +				     qp_attr_mask,
> +				     udata);
> +}
> +
> +static inline int ib_security_create_qp_security(struct ib_qp *qp)
> +{
> +	return 0;
> +}
> +
> +static inline void ib_security_destroy_qp(struct ib_qp_security *sec)
> +{
> +}
> +
> +static inline int ib_security_open_shared_qp(struct ib_qp *qp)
> +{
> +	return 0;
> +}
> +
> +static inline void ib_security_close_shared_qp(struct ib_qp_security *sec)
> +{
> +}
> +#endif
>  #endif /* _CORE_PRIV_H */
> diff --git a/drivers/infiniband/core/core_security.c b/drivers/infiniband/core/core_security.c
> new file mode 100644
> index 0000000..768edea
> --- /dev/null
> +++ b/drivers/infiniband/core/core_security.c
> @@ -0,0 +1,331 @@
> +/*
> + * Copyright (c) 2016 Mellanox Technologies Ltd.  All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifdef CONFIG_SECURITY_INFINIBAND
> +
> +#include <linux/security.h>
> +
> +#include <rdma/ib_verbs.h>
> +#include <rdma/ib_cache.h>
> +#include "core_priv.h"
> +
> +static int get_pkey_info(struct ib_device *dev,
> +			 u8 port_num,
> +			 u16 pkey_index,
> +			 u64 *subnet_prefix,
> +			 u16 *pkey)
> +{
> +	int err;
> +
> +	err = ib_get_cached_pkey(dev, port_num, pkey_index, pkey);
> +	if (err)
> +		return err;
> +
> +	err = ib_get_cached_subnet_prefix(dev, port_num, subnet_prefix);
> +
> +	return err;
> +}
> +
> +static int enforce_qp_pkey_security(struct ib_device *dev,
> +				    u8 port_num,
> +				    u16 pkey_index,
> +				    struct ib_qp_security *sec)
> +{
> +	struct ib_qp_security *shared_qp_sec;
> +	u64 subnet_prefix;
> +	int err = 0;
> +	u16 pkey;
> +
> +	err = get_pkey_info(dev, port_num, pkey_index, &subnet_prefix, &pkey);
> +	if (err)
> +		return err;
> +
> +	err = security_qp_pkey_access(subnet_prefix, pkey, sec);
> +	if (err)
> +		return err;
> +
> +	if (sec->qp == sec->qp->real_qp) {
> +		/* The caller of this function holds the QP security
> +		 * mutex so this list traversal is safe
> +		*/

Did the comment below pass checkpatch.pl?

> +		list_for_each_entry(shared_qp_sec,
> +				    &sec->shared_qp_list,
> +				    shared_qp_list) {

Is this list always needed to be protected by lock?
In general, I prefer to see lock/unlock operations near protected code.
Otherwise, it is hard to follow all lock/unlock paths.

> +			err = security_qp_pkey_access(subnet_prefix,
> +						      pkey,
> +						      shared_qp_sec);
> +			if (err)
> +				break;
> +		}
> +	}
> +	return err;
> +}
> +
> +static int check_pkey(const struct ib_qp *qp,
> +		      const struct ib_qp_attr *qp_attr,
> +		      int qp_attr_mask)
> +{
> +	bool check_pkey = !!(qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT));
> +
> +	return check_pkey && (qp->qp_num != IB_QPT_SMI &&
> +			      qp->qp_num != IB_QPT_GSI);

IB_QPT_SMI and IB_QPT_GSI are declared as struct ib_qp_type and setted
in qp->qp_type and not in qp->qp_num.

> +}
> +
> +static int check_alt_pkey(const struct ib_qp *qp,
> +			  const struct ib_qp_attr *qp_attr,
> +			  int qp_attr_mask)
> +{
> +	bool check_alt_pkey = !!(qp_attr_mask & IB_QP_ALT_PATH);
> +
> +	return check_alt_pkey && (qp->qp_num != IB_QPT_SMI &&
> +				  qp->qp_num != IB_QPT_GSI);
> +}

The same as above.

> +
> +static int affects_security_settings(const struct ib_qp *qp,
> +				     const struct ib_qp_attr *qp_attr,
> +				     int qp_attr_mask)
> +{
> +	return check_pkey(qp, qp_attr, qp_attr_mask) ||
> +	       check_alt_pkey(qp, qp_attr, qp_attr_mask);
> +}
> +
> +static void begin_port_pkey_change(struct ib_qp *qp,
> +				   struct ib_port_pkey *pp,
> +				   struct ib_port_pkey *old_pp,
> +				   u8 port_num,
> +				   u16 pkey_index)
> +{
> +	if (pp->state == IB_PORT_PKEY_NOT_VALID ||
> +	    (pkey_index != pp->pkey_index ||
> +	     port_num != pp->port_num)) {
> +		old_pp->pkey_index = pp->pkey_index;
> +		old_pp->port_num = pp->port_num;
> +		old_pp->state = pp->state;
> +
> +		pp->port_num = port_num;
> +		pp->pkey_index = pkey_index;
> +		pp->state = IB_PORT_PKEY_CHANGING;
> +	}
> +}
> +
> +static int qp_modify_enforce_security(struct ib_qp *qp,
> +				      const struct ib_qp_attr *qp_attr,
> +				      int qp_attr_mask)
> +{
> +	struct ib_qp_security *sec = qp->qp_sec;
> +	int err = 0;
> +
> +	if (check_pkey(qp, qp_attr, qp_attr_mask)) {
> +		u8 port_num = (qp_attr_mask & IB_QP_PORT) ?
> +			       qp_attr->port_num :
> +			       sec->ports_pkeys.main.port_num;
> +
> +		u16 pkey_index = (qp_attr_mask & IB_QP_PKEY_INDEX) ?
> +				  qp_attr->pkey_index :
> +				  sec->ports_pkeys.main.pkey_index;
> +
> +		err = enforce_qp_pkey_security(qp->device,
> +					       port_num,
> +					       pkey_index,
> +					       sec);
> +
> +		if (err)
> +			return err;
> +
> +		begin_port_pkey_change(qp,
> +				       &sec->ports_pkeys.main,
> +				       &sec->old_ports_pkeys.main,
> +				       port_num,
> +				       pkey_index);
> +	}
> +
> +	if (check_alt_pkey(qp, qp_attr, qp_attr_mask)) {
> +		err = enforce_qp_pkey_security(qp->device,
> +					       qp_attr->alt_port_num,
> +					       qp_attr->alt_pkey_index,
> +					       sec);
> +
> +		if (err)
> +			return err;
> +
> +		begin_port_pkey_change(qp,
> +				       &sec->ports_pkeys.alt,
> +				       &sec->old_ports_pkeys.alt,
> +				       qp_attr->alt_port_num,
> +				       qp_attr->alt_pkey_index);
> +	}
> +	return err;
> +}
> +
> +static void abort_port_pkey_change(struct ib_qp *qp,
> +				   struct ib_port_pkey *pp,
> +				   struct ib_port_pkey *old_pp)
> +{
> +	if (pp->state == IB_PORT_PKEY_CHANGING) {
> +		pp->pkey_index = old_pp->pkey_index;
> +		pp->port_num = old_pp->port_num;
> +		pp->state = old_pp->state;
> +	}
> +}
> +
> +static int cleanup_qp_pkey_associations(struct ib_qp *qp,
> +					bool revert_to_old)
> +{
> +	struct ib_qp_security *sec = qp->qp_sec;
> +
> +	if (revert_to_old) {
> +		abort_port_pkey_change(qp,
> +				       &qp->qp_sec->ports_pkeys.main,
> +				       &qp->qp_sec->old_ports_pkeys.main);
> +
> +		abort_port_pkey_change(qp,
> +				       &qp->qp_sec->ports_pkeys.alt,
> +				       &qp->qp_sec->old_ports_pkeys.alt);
> +	} else {
> +		if (sec->ports_pkeys.main.state == IB_PORT_PKEY_CHANGING)
> +			sec->ports_pkeys.main.state = IB_PORT_PKEY_VALID;
> +
> +		if (sec->ports_pkeys.alt.state == IB_PORT_PKEY_CHANGING)
> +			sec->ports_pkeys.alt.state = IB_PORT_PKEY_VALID;
> +	}
> +
> +	memset(&sec->old_ports_pkeys, 0, sizeof(sec->old_ports_pkeys));
> +
> +	return 0;
> +}
> +
> +int ib_security_open_shared_qp(struct ib_qp *qp)
> +{
> +	struct ib_qp *real_qp = qp->real_qp;
> +	int err;
> +
> +	err = ib_security_create_qp_security(qp);
> +	if (err)
> +		goto out;
> +
> +	mutex_lock(&real_qp->qp_sec->mutex);
> +
> +	if (real_qp->qp_sec->ports_pkeys.main.state != IB_PORT_PKEY_NOT_VALID)
> +		err = enforce_qp_pkey_security(real_qp->device,
> +					       real_qp->qp_sec->ports_pkeys.main.port_num,
> +					       real_qp->qp_sec->ports_pkeys.main.pkey_index,
> +					       qp->qp_sec);
> +	if (err)
> +		goto err;
> +
> +	if (real_qp->qp_sec->ports_pkeys.alt.state != IB_PORT_PKEY_NOT_VALID)
> +		err = enforce_qp_pkey_security(real_qp->device,
> +					       real_qp->qp_sec->ports_pkeys.alt.port_num,
> +					       real_qp->qp_sec->ports_pkeys.alt.pkey_index,
> +					       qp->qp_sec);
> +
> +	if (err)
> +		goto err;
> +
> +	if (qp != real_qp)
> +		list_add(&qp->qp_sec->shared_qp_list,
> +			 &real_qp->qp_sec->shared_qp_list);
> +err:
> +	mutex_unlock(&real_qp->qp_sec->mutex);
> +	if (err)
> +		ib_security_destroy_qp(qp->qp_sec);
> +
> +out:
> +	return err;
> +}
> +
> +void ib_security_close_shared_qp(struct ib_qp_security *sec)
> +{
> +	struct ib_qp *real_qp = sec->qp->real_qp;
> +
> +	mutex_lock(&real_qp->qp_sec->mutex);
> +	list_del(&sec->shared_qp_list);
> +	mutex_unlock(&real_qp->qp_sec->mutex);
> +
> +	ib_security_destroy_qp(sec);
> +}
> +
> +int ib_security_create_qp_security(struct ib_qp *qp)
> +{
> +	int err;
> +
> +	qp->qp_sec = kzalloc(sizeof(*qp->qp_sec), GFP_KERNEL);
> +	if (!qp->qp_sec)
> +		return -ENOMEM;
> +
> +	qp->qp_sec->qp = qp;
> +	mutex_init(&qp->qp_sec->mutex);
> +	INIT_LIST_HEAD(&qp->qp_sec->shared_qp_list);
> +	err = security_ib_qp_alloc_security(qp->qp_sec);
> +	if (err)
> +		kfree(qp->qp_sec);
> +
> +	return err;
> +}
> +EXPORT_SYMBOL(ib_security_create_qp_security);
> +
> +void ib_security_destroy_qp(struct ib_qp_security *sec)
> +{
> +	security_ib_qp_free_security(sec);
> +	kfree(sec);
> +}

Did you want to EXPORT_SYMBOL here too?

> +
> +int ib_security_modify_qp(struct ib_qp *qp,
> +			  struct ib_qp_attr *qp_attr,
> +			  int qp_attr_mask,
> +			  struct ib_udata *udata)
> +{
> +	int err = 0;
> +	bool enforce_security = affects_security_settings(qp,
> +							  qp_attr,
> +							  qp_attr_mask);
> +
> +	if (enforce_security) {
> +		mutex_lock(&qp->qp_sec->mutex);
> +
> +		err = qp_modify_enforce_security(qp, qp_attr, qp_attr_mask);
> +	}
> +
> +	if (!err)
> +		err = qp->device->modify_qp(qp->real_qp,
> +					    qp_attr,
> +					    qp_attr_mask,
> +					    udata);
> +	if (enforce_security) {
> +		cleanup_qp_pkey_associations(qp, !!err);
> +		mutex_unlock(&qp->qp_sec->mutex);
> +	}
> +	return err;
> +}
> +EXPORT_SYMBOL(ib_security_modify_qp);
> +
> +#endif /* CONFIG_SECURITY_INFINIBAND */
> diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
> index 6fdc7ec..6df15ea 100644
> --- a/drivers/infiniband/core/uverbs_cmd.c
> +++ b/drivers/infiniband/core/uverbs_cmd.c
> @@ -37,7 +37,7 @@
>  #include <linux/fs.h>
>  #include <linux/slab.h>
>  #include <linux/sched.h>
> -
> +#include <linux/security.h>
>  #include <asm/uaccess.h>
>  
>  #include "uverbs.h"
> @@ -1857,6 +1857,10 @@ static int create_qp(struct ib_uverbs_file *file,
>  	}
>  
>  	if (cmd->qp_type != IB_QPT_XRC_TGT) {
> +		ret = ib_security_create_qp_security(qp);
> +		if (ret)
> +			goto err_destroy;
> +
>  		qp->real_qp	  = qp;
>  		qp->device	  = device;
>  		qp->pd		  = pd;
> @@ -2339,10 +2343,18 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
>  		ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
>  		if (ret)
>  			goto release_qp;
> -		ret = qp->device->modify_qp(qp, attr,
> -			modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
> +
> +		ret = ib_security_modify_qp(qp,
> +					    attr,
> +					    modify_qp_mask(qp->qp_type,
> +							   cmd.attr_mask),
> +					    &udata);
>  	} else {
> -		ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
> +		ret = ib_security_modify_qp(qp,
> +					    attr,
> +					    modify_qp_mask(qp->qp_type,
> +							   cmd.attr_mask),
> +					    NULL);
>  	}
>  
>  	if (ret)
> diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
> index 15b8adb..47000ee 100644
> --- a/drivers/infiniband/core/verbs.c
> +++ b/drivers/infiniband/core/verbs.c
> @@ -44,6 +44,7 @@
>  #include <linux/in.h>
>  #include <linux/in6.h>
>  #include <net/addrconf.h>
> +#include <linux/security.h>
>  
>  #include <rdma/ib_verbs.h>
>  #include <rdma/ib_cache.h>
> @@ -681,12 +682,19 @@ static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
>  {
>  	struct ib_qp *qp;
>  	unsigned long flags;
> +	int err;
>  
>  	qp = kzalloc(sizeof *qp, GFP_KERNEL);
>  	if (!qp)
>  		return ERR_PTR(-ENOMEM);
>  
>  	qp->real_qp = real_qp;
> +	err = ib_security_open_shared_qp(qp);
> +	if (err) {
> +		kfree(qp);
> +		return ERR_PTR(err);
> +	}
> +
>  	atomic_inc(&real_qp->usecnt);
>  	qp->device = real_qp->device;
>  	qp->event_handler = event_handler;
> @@ -728,11 +736,16 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
>  {
>  	struct ib_qp *qp, *real_qp;
>  	struct ib_device *device;
> +	int err;
>  
>  	device = pd ? pd->device : qp_init_attr->xrcd->device;
>  	qp = device->create_qp(pd, qp_init_attr, NULL);
>  
>  	if (!IS_ERR(qp)) {
> +		err = ib_security_create_qp_security(qp);
> +		if (err)
> +			goto destroy_qp;
> +
>  		qp->device     = device;
>  		qp->real_qp    = qp;
>  		qp->uobject    = NULL;
> @@ -780,6 +793,10 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
>  	}
>  
>  	return qp;
> +
> +destroy_qp:
> +	ib_destroy_qp(qp);
> +	return ERR_PTR(err);
>  }
>  EXPORT_SYMBOL(ib_create_qp);
>  
> @@ -1180,7 +1197,7 @@ int ib_modify_qp(struct ib_qp *qp,
>  	if (ret)
>  		return ret;
>  
> -	return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
> +	return ib_security_modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
>  }
>  EXPORT_SYMBOL(ib_modify_qp);
>  
> @@ -1209,6 +1226,7 @@ int ib_close_qp(struct ib_qp *qp)
>  	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
>  
>  	atomic_dec(&real_qp->usecnt);
> +	ib_security_close_shared_qp(qp->qp_sec);
>  	kfree(qp);
>  
>  	return 0;
> @@ -1248,6 +1266,7 @@ int ib_destroy_qp(struct ib_qp *qp)
>  	struct ib_pd *pd;
>  	struct ib_cq *scq, *rcq;
>  	struct ib_srq *srq;
> +	struct ib_qp_security *sec;
>  	int ret;
>  
>  	if (atomic_read(&qp->usecnt))
> @@ -1260,6 +1279,7 @@ int ib_destroy_qp(struct ib_qp *qp)
>  	scq  = qp->send_cq;
>  	rcq  = qp->recv_cq;
>  	srq  = qp->srq;
> +	sec  = qp->qp_sec;
>  
>  	ret = qp->device->destroy_qp(qp);
>  	if (!ret) {
> @@ -1271,6 +1291,8 @@ int ib_destroy_qp(struct ib_qp *qp)
>  			atomic_dec(&rcq->usecnt);
>  		if (srq)
>  			atomic_dec(&srq->usecnt);
> +		if (sec)
> +			ib_security_destroy_qp(sec);
>  	}
>  
>  	return ret;
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index 870c5ac..f71cb47 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -1416,8 +1416,34 @@ struct ib_srq {
>  	} ext;
>  };
>  
> +enum port_pkey_state {
> +	IB_PORT_PKEY_NOT_VALID = 0,
> +	IB_PORT_PKEY_VALID = 1,
> +	IB_PORT_PKEY_CHANGING = 2,
> +};
> +
> +struct ib_port_pkey {
> +	enum port_pkey_state	state;
> +	u16			pkey_index;
> +	u8			port_num;
> +};
> +
> +struct ib_ports_pkeys {
> +	struct ib_port_pkey	main;
> +	struct ib_port_pkey	alt;
> +};
> +
>  struct ib_qp_security {
> -	void *q_security;
> +	struct ib_qp	       *qp;
> +	/* Hold this mutex when changing port and pkey settings. */
> +	struct mutex		mutex;
> +	struct ib_ports_pkeys	ports_pkeys;
> +	struct ib_ports_pkeys	old_ports_pkeys;
> +	/* A list of all open shared QP handles.  Required to enforce security
> +	 * properly for all users of a shared QP.
> +	 */
> +	struct list_head        shared_qp_list;
> +	void                   *q_security;
>  };
>  
>  struct ib_qp {
> -- 
> 1.7.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
@ 2016-04-07 16:31         ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 16:31 UTC (permalink / raw)
  To: Dan Jurgens; +Cc: selinux, linux-security-module, linux-rdma, yevgenyp

[-- Attachment #1: Type: text/plain, Size: 19992 bytes --]

On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Allocate and free a security context when creating and destroying a QP.
> This context is used for controlling access to PKeys.
> 
> When a request is made to modify a QP that changes the port, PKey index,
> alternate path port, or alternate path PKey index, check that the QP has
> permission for the PKey in the index on the subnet prefix of the port.
> If the QP is shared make sure all handles to the QP also have access.
> 
> Store which port and pkey a QP is using.  After the reset to init
> transition the user can modify the port and pkey independently.  This
> adds a transactional aspect to modify QP when the port, pkey, or
> alternate path change.  Permission must be checked for the new settings,
> then the modify can be attempted.  If the modify fails the old setting
> should be restored.
> 
> To keep the security changes isolated a new file is used to hold security
> related functionality.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> Reviewed-by: Eli Cohen <eli@mellanox.com>
> ---
>  drivers/infiniband/core/Makefile        |    2 +-
>  drivers/infiniband/core/core_priv.h     |   41 ++++
>  drivers/infiniband/core/core_security.c |  331 +++++++++++++++++++++++++++++++

We are already in core, there is no need to call files core_XXX.

>  drivers/infiniband/core/uverbs_cmd.c    |   20 ++-
>  drivers/infiniband/core/verbs.c         |   24 +++-
>  include/rdma/ib_verbs.h                 |   28 +++-
>  6 files changed, 439 insertions(+), 7 deletions(-)
>  create mode 100644 drivers/infiniband/core/core_security.c
> 
> diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
> index f818538..48a4013 100644
> --- a/drivers/infiniband/core/Makefile
> +++ b/drivers/infiniband/core/Makefile
> @@ -10,7 +10,7 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=	ib_uverbs.o ib_ucm.o \
>  
>  ib_core-y :=			packer.o ud_header.o verbs.o cq.o sysfs.o \
>  				device.o fmr_pool.o cache.o netlink.o \
> -				roce_gid_mgmt.o
> +				roce_gid_mgmt.o core_security.o
>  ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
>  ib_core-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o umem_rbtree.o
>  
> diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
> index 722b866..27f2fa8 100644
> --- a/drivers/infiniband/core/core_priv.h
> +++ b/drivers/infiniband/core/core_priv.h
> @@ -140,4 +140,45 @@ static inline bool rdma_is_upper_dev_rcu(struct net_device *dev,
>  int ib_get_cached_subnet_prefix(struct ib_device *device,
>  				u8                port_num,
>  				u64              *sn_pfx);
> +
> +#ifdef CONFIG_SECURITY_INFINIBAND
> +int ib_security_modify_qp(struct ib_qp *qp,
> +			  struct ib_qp_attr *qp_attr,
> +			  int qp_attr_mask,
> +			  struct ib_udata *udata);
> +
> +int ib_security_create_qp_security(struct ib_qp *qp);

Why do we need xx_SECURITY_xxxxx_SECURITY in name?

> +void ib_security_destroy_qp(struct ib_qp_security *sec);
> +int ib_security_open_shared_qp(struct ib_qp *qp);
> +void ib_security_close_shared_qp(struct ib_qp_security *sec);
> +#else
> +static inline int ib_security_modify_qp(struct ib_qp *qp,
> +					struct ib_qp_attr *qp_attr,
> +					int qp_attr_mask,
> +					struct ib_udata *udata)
> +{
> +	return qp->device->modify_qp(qp->real_qp,
> +				     qp_attr,
> +				     qp_attr_mask,
> +				     udata);
> +}
> +
> +static inline int ib_security_create_qp_security(struct ib_qp *qp)
> +{
> +	return 0;
> +}
> +
> +static inline void ib_security_destroy_qp(struct ib_qp_security *sec)
> +{
> +}
> +
> +static inline int ib_security_open_shared_qp(struct ib_qp *qp)
> +{
> +	return 0;
> +}
> +
> +static inline void ib_security_close_shared_qp(struct ib_qp_security *sec)
> +{
> +}
> +#endif
>  #endif /* _CORE_PRIV_H */
> diff --git a/drivers/infiniband/core/core_security.c b/drivers/infiniband/core/core_security.c
> new file mode 100644
> index 0000000..768edea
> --- /dev/null
> +++ b/drivers/infiniband/core/core_security.c
> @@ -0,0 +1,331 @@
> +/*
> + * Copyright (c) 2016 Mellanox Technologies Ltd.  All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifdef CONFIG_SECURITY_INFINIBAND
> +
> +#include <linux/security.h>
> +
> +#include <rdma/ib_verbs.h>
> +#include <rdma/ib_cache.h>
> +#include "core_priv.h"
> +
> +static int get_pkey_info(struct ib_device *dev,
> +			 u8 port_num,
> +			 u16 pkey_index,
> +			 u64 *subnet_prefix,
> +			 u16 *pkey)
> +{
> +	int err;
> +
> +	err = ib_get_cached_pkey(dev, port_num, pkey_index, pkey);
> +	if (err)
> +		return err;
> +
> +	err = ib_get_cached_subnet_prefix(dev, port_num, subnet_prefix);
> +
> +	return err;
> +}
> +
> +static int enforce_qp_pkey_security(struct ib_device *dev,
> +				    u8 port_num,
> +				    u16 pkey_index,
> +				    struct ib_qp_security *sec)
> +{
> +	struct ib_qp_security *shared_qp_sec;
> +	u64 subnet_prefix;
> +	int err = 0;
> +	u16 pkey;
> +
> +	err = get_pkey_info(dev, port_num, pkey_index, &subnet_prefix, &pkey);
> +	if (err)
> +		return err;
> +
> +	err = security_qp_pkey_access(subnet_prefix, pkey, sec);
> +	if (err)
> +		return err;
> +
> +	if (sec->qp == sec->qp->real_qp) {
> +		/* The caller of this function holds the QP security
> +		 * mutex so this list traversal is safe
> +		*/

Did the comment below pass checkpatch.pl?

> +		list_for_each_entry(shared_qp_sec,
> +				    &sec->shared_qp_list,
> +				    shared_qp_list) {

Is this list always needed to be protected by lock?
In general, I prefer to see lock/unlock operations near protected code.
Otherwise, it is hard to follow all lock/unlock paths.

> +			err = security_qp_pkey_access(subnet_prefix,
> +						      pkey,
> +						      shared_qp_sec);
> +			if (err)
> +				break;
> +		}
> +	}
> +	return err;
> +}
> +
> +static int check_pkey(const struct ib_qp *qp,
> +		      const struct ib_qp_attr *qp_attr,
> +		      int qp_attr_mask)
> +{
> +	bool check_pkey = !!(qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT));
> +
> +	return check_pkey && (qp->qp_num != IB_QPT_SMI &&
> +			      qp->qp_num != IB_QPT_GSI);

IB_QPT_SMI and IB_QPT_GSI are declared as struct ib_qp_type and setted
in qp->qp_type and not in qp->qp_num.

> +}
> +
> +static int check_alt_pkey(const struct ib_qp *qp,
> +			  const struct ib_qp_attr *qp_attr,
> +			  int qp_attr_mask)
> +{
> +	bool check_alt_pkey = !!(qp_attr_mask & IB_QP_ALT_PATH);
> +
> +	return check_alt_pkey && (qp->qp_num != IB_QPT_SMI &&
> +				  qp->qp_num != IB_QPT_GSI);
> +}

The same as above.

> +
> +static int affects_security_settings(const struct ib_qp *qp,
> +				     const struct ib_qp_attr *qp_attr,
> +				     int qp_attr_mask)
> +{
> +	return check_pkey(qp, qp_attr, qp_attr_mask) ||
> +	       check_alt_pkey(qp, qp_attr, qp_attr_mask);
> +}
> +
> +static void begin_port_pkey_change(struct ib_qp *qp,
> +				   struct ib_port_pkey *pp,
> +				   struct ib_port_pkey *old_pp,
> +				   u8 port_num,
> +				   u16 pkey_index)
> +{
> +	if (pp->state == IB_PORT_PKEY_NOT_VALID ||
> +	    (pkey_index != pp->pkey_index ||
> +	     port_num != pp->port_num)) {
> +		old_pp->pkey_index = pp->pkey_index;
> +		old_pp->port_num = pp->port_num;
> +		old_pp->state = pp->state;
> +
> +		pp->port_num = port_num;
> +		pp->pkey_index = pkey_index;
> +		pp->state = IB_PORT_PKEY_CHANGING;
> +	}
> +}
> +
> +static int qp_modify_enforce_security(struct ib_qp *qp,
> +				      const struct ib_qp_attr *qp_attr,
> +				      int qp_attr_mask)
> +{
> +	struct ib_qp_security *sec = qp->qp_sec;
> +	int err = 0;
> +
> +	if (check_pkey(qp, qp_attr, qp_attr_mask)) {
> +		u8 port_num = (qp_attr_mask & IB_QP_PORT) ?
> +			       qp_attr->port_num :
> +			       sec->ports_pkeys.main.port_num;
> +
> +		u16 pkey_index = (qp_attr_mask & IB_QP_PKEY_INDEX) ?
> +				  qp_attr->pkey_index :
> +				  sec->ports_pkeys.main.pkey_index;
> +
> +		err = enforce_qp_pkey_security(qp->device,
> +					       port_num,
> +					       pkey_index,
> +					       sec);
> +
> +		if (err)
> +			return err;
> +
> +		begin_port_pkey_change(qp,
> +				       &sec->ports_pkeys.main,
> +				       &sec->old_ports_pkeys.main,
> +				       port_num,
> +				       pkey_index);
> +	}
> +
> +	if (check_alt_pkey(qp, qp_attr, qp_attr_mask)) {
> +		err = enforce_qp_pkey_security(qp->device,
> +					       qp_attr->alt_port_num,
> +					       qp_attr->alt_pkey_index,
> +					       sec);
> +
> +		if (err)
> +			return err;
> +
> +		begin_port_pkey_change(qp,
> +				       &sec->ports_pkeys.alt,
> +				       &sec->old_ports_pkeys.alt,
> +				       qp_attr->alt_port_num,
> +				       qp_attr->alt_pkey_index);
> +	}
> +	return err;
> +}
> +
> +static void abort_port_pkey_change(struct ib_qp *qp,
> +				   struct ib_port_pkey *pp,
> +				   struct ib_port_pkey *old_pp)
> +{
> +	if (pp->state == IB_PORT_PKEY_CHANGING) {
> +		pp->pkey_index = old_pp->pkey_index;
> +		pp->port_num = old_pp->port_num;
> +		pp->state = old_pp->state;
> +	}
> +}
> +
> +static int cleanup_qp_pkey_associations(struct ib_qp *qp,
> +					bool revert_to_old)
> +{
> +	struct ib_qp_security *sec = qp->qp_sec;
> +
> +	if (revert_to_old) {
> +		abort_port_pkey_change(qp,
> +				       &qp->qp_sec->ports_pkeys.main,
> +				       &qp->qp_sec->old_ports_pkeys.main);
> +
> +		abort_port_pkey_change(qp,
> +				       &qp->qp_sec->ports_pkeys.alt,
> +				       &qp->qp_sec->old_ports_pkeys.alt);
> +	} else {
> +		if (sec->ports_pkeys.main.state == IB_PORT_PKEY_CHANGING)
> +			sec->ports_pkeys.main.state = IB_PORT_PKEY_VALID;
> +
> +		if (sec->ports_pkeys.alt.state == IB_PORT_PKEY_CHANGING)
> +			sec->ports_pkeys.alt.state = IB_PORT_PKEY_VALID;
> +	}
> +
> +	memset(&sec->old_ports_pkeys, 0, sizeof(sec->old_ports_pkeys));
> +
> +	return 0;
> +}
> +
> +int ib_security_open_shared_qp(struct ib_qp *qp)
> +{
> +	struct ib_qp *real_qp = qp->real_qp;
> +	int err;
> +
> +	err = ib_security_create_qp_security(qp);
> +	if (err)
> +		goto out;
> +
> +	mutex_lock(&real_qp->qp_sec->mutex);
> +
> +	if (real_qp->qp_sec->ports_pkeys.main.state != IB_PORT_PKEY_NOT_VALID)
> +		err = enforce_qp_pkey_security(real_qp->device,
> +					       real_qp->qp_sec->ports_pkeys.main.port_num,
> +					       real_qp->qp_sec->ports_pkeys.main.pkey_index,
> +					       qp->qp_sec);
> +	if (err)
> +		goto err;
> +
> +	if (real_qp->qp_sec->ports_pkeys.alt.state != IB_PORT_PKEY_NOT_VALID)
> +		err = enforce_qp_pkey_security(real_qp->device,
> +					       real_qp->qp_sec->ports_pkeys.alt.port_num,
> +					       real_qp->qp_sec->ports_pkeys.alt.pkey_index,
> +					       qp->qp_sec);
> +
> +	if (err)
> +		goto err;
> +
> +	if (qp != real_qp)
> +		list_add(&qp->qp_sec->shared_qp_list,
> +			 &real_qp->qp_sec->shared_qp_list);
> +err:
> +	mutex_unlock(&real_qp->qp_sec->mutex);
> +	if (err)
> +		ib_security_destroy_qp(qp->qp_sec);
> +
> +out:
> +	return err;
> +}
> +
> +void ib_security_close_shared_qp(struct ib_qp_security *sec)
> +{
> +	struct ib_qp *real_qp = sec->qp->real_qp;
> +
> +	mutex_lock(&real_qp->qp_sec->mutex);
> +	list_del(&sec->shared_qp_list);
> +	mutex_unlock(&real_qp->qp_sec->mutex);
> +
> +	ib_security_destroy_qp(sec);
> +}
> +
> +int ib_security_create_qp_security(struct ib_qp *qp)
> +{
> +	int err;
> +
> +	qp->qp_sec = kzalloc(sizeof(*qp->qp_sec), GFP_KERNEL);
> +	if (!qp->qp_sec)
> +		return -ENOMEM;
> +
> +	qp->qp_sec->qp = qp;
> +	mutex_init(&qp->qp_sec->mutex);
> +	INIT_LIST_HEAD(&qp->qp_sec->shared_qp_list);
> +	err = security_ib_qp_alloc_security(qp->qp_sec);
> +	if (err)
> +		kfree(qp->qp_sec);
> +
> +	return err;
> +}
> +EXPORT_SYMBOL(ib_security_create_qp_security);
> +
> +void ib_security_destroy_qp(struct ib_qp_security *sec)
> +{
> +	security_ib_qp_free_security(sec);
> +	kfree(sec);
> +}

Did you want to EXPORT_SYMBOL here too?

> +
> +int ib_security_modify_qp(struct ib_qp *qp,
> +			  struct ib_qp_attr *qp_attr,
> +			  int qp_attr_mask,
> +			  struct ib_udata *udata)
> +{
> +	int err = 0;
> +	bool enforce_security = affects_security_settings(qp,
> +							  qp_attr,
> +							  qp_attr_mask);
> +
> +	if (enforce_security) {
> +		mutex_lock(&qp->qp_sec->mutex);
> +
> +		err = qp_modify_enforce_security(qp, qp_attr, qp_attr_mask);
> +	}
> +
> +	if (!err)
> +		err = qp->device->modify_qp(qp->real_qp,
> +					    qp_attr,
> +					    qp_attr_mask,
> +					    udata);
> +	if (enforce_security) {
> +		cleanup_qp_pkey_associations(qp, !!err);
> +		mutex_unlock(&qp->qp_sec->mutex);
> +	}
> +	return err;
> +}
> +EXPORT_SYMBOL(ib_security_modify_qp);
> +
> +#endif /* CONFIG_SECURITY_INFINIBAND */
> diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
> index 6fdc7ec..6df15ea 100644
> --- a/drivers/infiniband/core/uverbs_cmd.c
> +++ b/drivers/infiniband/core/uverbs_cmd.c
> @@ -37,7 +37,7 @@
>  #include <linux/fs.h>
>  #include <linux/slab.h>
>  #include <linux/sched.h>
> -
> +#include <linux/security.h>
>  #include <asm/uaccess.h>
>  
>  #include "uverbs.h"
> @@ -1857,6 +1857,10 @@ static int create_qp(struct ib_uverbs_file *file,
>  	}
>  
>  	if (cmd->qp_type != IB_QPT_XRC_TGT) {
> +		ret = ib_security_create_qp_security(qp);
> +		if (ret)
> +			goto err_destroy;
> +
>  		qp->real_qp	  = qp;
>  		qp->device	  = device;
>  		qp->pd		  = pd;
> @@ -2339,10 +2343,18 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
>  		ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
>  		if (ret)
>  			goto release_qp;
> -		ret = qp->device->modify_qp(qp, attr,
> -			modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
> +
> +		ret = ib_security_modify_qp(qp,
> +					    attr,
> +					    modify_qp_mask(qp->qp_type,
> +							   cmd.attr_mask),
> +					    &udata);
>  	} else {
> -		ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
> +		ret = ib_security_modify_qp(qp,
> +					    attr,
> +					    modify_qp_mask(qp->qp_type,
> +							   cmd.attr_mask),
> +					    NULL);
>  	}
>  
>  	if (ret)
> diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
> index 15b8adb..47000ee 100644
> --- a/drivers/infiniband/core/verbs.c
> +++ b/drivers/infiniband/core/verbs.c
> @@ -44,6 +44,7 @@
>  #include <linux/in.h>
>  #include <linux/in6.h>
>  #include <net/addrconf.h>
> +#include <linux/security.h>
>  
>  #include <rdma/ib_verbs.h>
>  #include <rdma/ib_cache.h>
> @@ -681,12 +682,19 @@ static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
>  {
>  	struct ib_qp *qp;
>  	unsigned long flags;
> +	int err;
>  
>  	qp = kzalloc(sizeof *qp, GFP_KERNEL);
>  	if (!qp)
>  		return ERR_PTR(-ENOMEM);
>  
>  	qp->real_qp = real_qp;
> +	err = ib_security_open_shared_qp(qp);
> +	if (err) {
> +		kfree(qp);
> +		return ERR_PTR(err);
> +	}
> +
>  	atomic_inc(&real_qp->usecnt);
>  	qp->device = real_qp->device;
>  	qp->event_handler = event_handler;
> @@ -728,11 +736,16 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
>  {
>  	struct ib_qp *qp, *real_qp;
>  	struct ib_device *device;
> +	int err;
>  
>  	device = pd ? pd->device : qp_init_attr->xrcd->device;
>  	qp = device->create_qp(pd, qp_init_attr, NULL);
>  
>  	if (!IS_ERR(qp)) {
> +		err = ib_security_create_qp_security(qp);
> +		if (err)
> +			goto destroy_qp;
> +
>  		qp->device     = device;
>  		qp->real_qp    = qp;
>  		qp->uobject    = NULL;
> @@ -780,6 +793,10 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
>  	}
>  
>  	return qp;
> +
> +destroy_qp:
> +	ib_destroy_qp(qp);
> +	return ERR_PTR(err);
>  }
>  EXPORT_SYMBOL(ib_create_qp);
>  
> @@ -1180,7 +1197,7 @@ int ib_modify_qp(struct ib_qp *qp,
>  	if (ret)
>  		return ret;
>  
> -	return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
> +	return ib_security_modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
>  }
>  EXPORT_SYMBOL(ib_modify_qp);
>  
> @@ -1209,6 +1226,7 @@ int ib_close_qp(struct ib_qp *qp)
>  	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
>  
>  	atomic_dec(&real_qp->usecnt);
> +	ib_security_close_shared_qp(qp->qp_sec);
>  	kfree(qp);
>  
>  	return 0;
> @@ -1248,6 +1266,7 @@ int ib_destroy_qp(struct ib_qp *qp)
>  	struct ib_pd *pd;
>  	struct ib_cq *scq, *rcq;
>  	struct ib_srq *srq;
> +	struct ib_qp_security *sec;
>  	int ret;
>  
>  	if (atomic_read(&qp->usecnt))
> @@ -1260,6 +1279,7 @@ int ib_destroy_qp(struct ib_qp *qp)
>  	scq  = qp->send_cq;
>  	rcq  = qp->recv_cq;
>  	srq  = qp->srq;
> +	sec  = qp->qp_sec;
>  
>  	ret = qp->device->destroy_qp(qp);
>  	if (!ret) {
> @@ -1271,6 +1291,8 @@ int ib_destroy_qp(struct ib_qp *qp)
>  			atomic_dec(&rcq->usecnt);
>  		if (srq)
>  			atomic_dec(&srq->usecnt);
> +		if (sec)
> +			ib_security_destroy_qp(sec);
>  	}
>  
>  	return ret;
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index 870c5ac..f71cb47 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -1416,8 +1416,34 @@ struct ib_srq {
>  	} ext;
>  };
>  
> +enum port_pkey_state {
> +	IB_PORT_PKEY_NOT_VALID = 0,
> +	IB_PORT_PKEY_VALID = 1,
> +	IB_PORT_PKEY_CHANGING = 2,
> +};
> +
> +struct ib_port_pkey {
> +	enum port_pkey_state	state;
> +	u16			pkey_index;
> +	u8			port_num;
> +};
> +
> +struct ib_ports_pkeys {
> +	struct ib_port_pkey	main;
> +	struct ib_port_pkey	alt;
> +};
> +
>  struct ib_qp_security {
> -	void *q_security;
> +	struct ib_qp	       *qp;
> +	/* Hold this mutex when changing port and pkey settings. */
> +	struct mutex		mutex;
> +	struct ib_ports_pkeys	ports_pkeys;
> +	struct ib_ports_pkeys	old_ports_pkeys;
> +	/* A list of all open shared QP handles.  Required to enforce security
> +	 * properly for all users of a shared QP.
> +	 */
> +	struct list_head        shared_qp_list;
> +	void                   *q_security;
>  };
>  
>  struct ib_qp {
> -- 
> 1.7.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
  2016-04-07 16:31         ` Leon Romanovsky
@ 2016-04-07 17:03           ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 17:03 UTC (permalink / raw)
  To: leon-2ukJVAZIZ/Y
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA

On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>>  drivers/infiniband/core/core_priv.h     |   41 ++++
>>  drivers/infiniband/core/core_security.c |  331 +++++++++++++++++++++++++++++++
> 
> We are already in core, there is no need to call files core_XXX.

I can change core_security.c to security.c.  core_priv.h already existed
so I won't change that in this patch.

>> +int ib_security_create_qp_security(struct ib_qp *qp);
> 
> Why do we need xx_SECURITY_xxxxx_SECURITY in name?

I had called it ib_security_create_qp. Eli thought that implied more
work that it actually does.  All the none static functions are named
ib_security_xxx, which I kind of liked as a convention, but I can
abandon that and go with ib_create_qp_security.

>> +	return check_pkey && (qp->qp_num != IB_QPT_SMI &&
>> +			      qp->qp_num != IB_QPT_GSI);
> 
> IB_QPT_SMI and IB_QPT_GSI are declared as struct ib_qp_type and setted
> in qp->qp_type and not in qp->qp_num.
>> +}
>> +
>> +static int check_alt_pkey(const struct ib_qp *qp,
>> +			  const struct ib_qp_attr *qp_attr,
>> +			  int qp_attr_mask)
>> +{
>> +	bool check_alt_pkey = !!(qp_attr_mask & IB_QP_ALT_PATH);
>> +
>> +	return check_alt_pkey && (qp->qp_num != IB_QPT_SMI &&
>> +				  qp->qp_num != IB_QPT_GSI);
>> +}
> 
> The same as above.

I'll fix this.

>> +		kfree(qp->qp_sec);
>> +
>> +	return err;
>> +}
>> +EXPORT_SYMBOL(ib_security_create_qp_security);
>> +
>> +void ib_security_destroy_qp(struct ib_qp_security *sec)
>> +{
>> +	security_ib_qp_free_security(sec);
>> +	kfree(sec);
>> +}
> 
> Did you want to EXPORT_SYMBOL here too?
> 

It's not called from outside ib_core, I only exported the functions that
are. ib_security_modify_qp and ib_security_create_qp security are called
from ib_core and ib_uverbs.  ib_security_enforce_mad_agent_pkey_access
is called from ib_mad.



_______________________________________________
Selinux mailing list
Selinux-+05T5uksL2qpZYMLLGbcSA@public.gmane.org
To unsubscribe, send email to Selinux-leave-+05T5uksL2pAGbPMOrvdOA@public.gmane.org
To get help, send an email containing "help" to Selinux-request-+05T5uksL2pAGbPMOrvdOA@public.gmane.org

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
@ 2016-04-07 17:03           ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 17:03 UTC (permalink / raw)
  To: leon; +Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>  drivers/infiniband/core/core_priv.h     |   41 ++++
>>  drivers/infiniband/core/core_security.c |  331 +++++++++++++++++++++++++++++++
> 
> We are already in core, there is no need to call files core_XXX.

I can change core_security.c to security.c.  core_priv.h already existed
so I won't change that in this patch.

>> +int ib_security_create_qp_security(struct ib_qp *qp);
> 
> Why do we need xx_SECURITY_xxxxx_SECURITY in name?

I had called it ib_security_create_qp. Eli thought that implied more
work that it actually does.  All the none static functions are named
ib_security_xxx, which I kind of liked as a convention, but I can
abandon that and go with ib_create_qp_security.

>> +	return check_pkey && (qp->qp_num != IB_QPT_SMI &&
>> +			      qp->qp_num != IB_QPT_GSI);
> 
> IB_QPT_SMI and IB_QPT_GSI are declared as struct ib_qp_type and setted
> in qp->qp_type and not in qp->qp_num.
>> +}
>> +
>> +static int check_alt_pkey(const struct ib_qp *qp,
>> +			  const struct ib_qp_attr *qp_attr,
>> +			  int qp_attr_mask)
>> +{
>> +	bool check_alt_pkey = !!(qp_attr_mask & IB_QP_ALT_PATH);
>> +
>> +	return check_alt_pkey && (qp->qp_num != IB_QPT_SMI &&
>> +				  qp->qp_num != IB_QPT_GSI);
>> +}
> 
> The same as above.

I'll fix this.

>> +		kfree(qp->qp_sec);
>> +
>> +	return err;
>> +}
>> +EXPORT_SYMBOL(ib_security_create_qp_security);
>> +
>> +void ib_security_destroy_qp(struct ib_qp_security *sec)
>> +{
>> +	security_ib_qp_free_security(sec);
>> +	kfree(sec);
>> +}
> 
> Did you want to EXPORT_SYMBOL here too?
> 

It's not called from outside ib_core, I only exported the functions that
are. ib_security_modify_qp and ib_security_create_qp security are called
from ib_core and ib_uverbs.  ib_security_enforce_mad_agent_pkey_access
is called from ib_mad.

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
  2016-04-07 17:03           ` Daniel Jurgens
@ 2016-04-07 17:39               ` leon
  -1 siblings, 0 replies; 90+ messages in thread
From: leon-2ukJVAZIZ/Y @ 2016-04-07 17:39 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

[-- Attachment #1: Type: text/plain, Size: 942 bytes --]

On Thu, Apr 07, 2016 at 05:03:50PM +0000, Daniel Jurgens wrote:
> On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
> > On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
> >> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> >> +		kfree(qp->qp_sec);
> >> +
> >> +	return err;
> >> +}
> >> +EXPORT_SYMBOL(ib_security_create_qp_security);
> >> +
> >> +void ib_security_destroy_qp(struct ib_qp_security *sec)
> >> +{
> >> +	security_ib_qp_free_security(sec);
> >> +	kfree(sec);
> >> +}
> > 
> > Did you want to EXPORT_SYMBOL here too?
> > 
> 
> It's not called from outside ib_core, I only exported the functions that
> are. ib_security_modify_qp and ib_security_create_qp security are called
> from ib_core and ib_uverbs.  ib_security_enforce_mad_agent_pkey_access
> is called from ib_mad.

So, how are you releasing the memory which is taken by
ib_security_create_qp_security ?

> 
> 

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
@ 2016-04-07 17:39               ` leon
  0 siblings, 0 replies; 90+ messages in thread
From: leon @ 2016-04-07 17:39 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

[-- Attachment #1: Type: text/plain, Size: 915 bytes --]

On Thu, Apr 07, 2016 at 05:03:50PM +0000, Daniel Jurgens wrote:
> On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
> > On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
> >> From: Daniel Jurgens <danielj@mellanox.com>
> >> +		kfree(qp->qp_sec);
> >> +
> >> +	return err;
> >> +}
> >> +EXPORT_SYMBOL(ib_security_create_qp_security);
> >> +
> >> +void ib_security_destroy_qp(struct ib_qp_security *sec)
> >> +{
> >> +	security_ib_qp_free_security(sec);
> >> +	kfree(sec);
> >> +}
> > 
> > Did you want to EXPORT_SYMBOL here too?
> > 
> 
> It's not called from outside ib_core, I only exported the functions that
> are. ib_security_modify_qp and ib_security_create_qp security are called
> from ib_core and ib_uverbs.  ib_security_enforce_mad_agent_pkey_access
> is called from ib_mad.

So, how are you releasing the memory which is taken by
ib_security_create_qp_security ?

> 
> 

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
  2016-04-07 17:39               ` leon
@ 2016-04-07 17:44                 ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 17:44 UTC (permalink / raw)
  To: leon-2ukJVAZIZ/Y
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/7/2016 12:40 PM, leon-2ukJVAZIZ/Y@public.gmane.org wrote:
> On Thu, Apr 07, 2016 at 05:03:50PM +0000, Daniel Jurgens wrote:
>> On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
>>> On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
>>>> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>>>> +		kfree(qp->qp_sec);
>>>> +
>>>> +	return err;
>>>> +}
>>>> +EXPORT_SYMBOL(ib_security_create_qp_security);
>>>> +
>>>> +void ib_security_destroy_qp(struct ib_qp_security *sec)
>>>> +{
>>>> +	security_ib_qp_free_security(sec);
>>>> +	kfree(sec);
>>>> +}
>>>
>>> Did you want to EXPORT_SYMBOL here too?
>>>
>>
>> It's not called from outside ib_core, I only exported the functions that
>> are. ib_security_modify_qp and ib_security_create_qp security are called
>> from ib_core and ib_uverbs.  ib_security_enforce_mad_agent_pkey_access
>> is called from ib_mad.
> 
> So, how are you releasing the memory which is taken by
> ib_security_create_qp_security ?

It is freed in ib_security_destroy_qp, which is called by ib_destroy_qp
after the QP is destroyed successfully.


--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
@ 2016-04-07 17:44                 ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 17:44 UTC (permalink / raw)
  To: leon; +Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/7/2016 12:40 PM, leon@leon.nu wrote:
> On Thu, Apr 07, 2016 at 05:03:50PM +0000, Daniel Jurgens wrote:
>> On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
>>> On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
>>>> From: Daniel Jurgens <danielj@mellanox.com>
>>>> +		kfree(qp->qp_sec);
>>>> +
>>>> +	return err;
>>>> +}
>>>> +EXPORT_SYMBOL(ib_security_create_qp_security);
>>>> +
>>>> +void ib_security_destroy_qp(struct ib_qp_security *sec)
>>>> +{
>>>> +	security_ib_qp_free_security(sec);
>>>> +	kfree(sec);
>>>> +}
>>>
>>> Did you want to EXPORT_SYMBOL here too?
>>>
>>
>> It's not called from outside ib_core, I only exported the functions that
>> are. ib_security_modify_qp and ib_security_create_qp security are called
>> from ib_core and ib_uverbs.  ib_security_enforce_mad_agent_pkey_access
>> is called from ib_mad.
> 
> So, how are you releasing the memory which is taken by
> ib_security_create_qp_security ?

It is freed in ib_security_destroy_qp, which is called by ib_destroy_qp
after the QP is destroyed successfully.

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

* Re: [RFC PATCH v2 10/13] ib/core: Enforce PKey security on management datagrams
  2016-04-06 23:33   ` [RFC PATCH v2 10/13] ib/core: Enforce PKey security on management datagrams Dan Jurgens
@ 2016-04-07 20:39         ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 20:39 UTC (permalink / raw)
  To: Dan Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	yevgenyp-VPRAkNaXOzVWk0Htik3J/w

[-- Attachment #1: Type: text/plain, Size: 1480 bytes --]

On Thu, Apr 07, 2016 at 02:33:55AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> Allocate and free a security context when creating and destroying a MAD
> agent.  This context is used for controlling access to PKeys.
> 
> When sending or receiving a MAD check that the agent has permission to
> access the PKey for the Subnet Prefix of the port.
> 
> Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/infiniband/core/core_priv.h     |   14 +++++++
>  drivers/infiniband/core/core_security.c |   17 ++++++++
>  drivers/infiniband/core/mad.c           |   65 +++++++++++++++++++++++++++---
>  3 files changed, 89 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
> index 27f2fa8..2759a18 100644
> --- a/drivers/infiniband/core/core_priv.h
> +++ b/drivers/infiniband/core/core_priv.h
> @@ -142,6 +142,11 @@ int ib_get_cached_subnet_prefix(struct ib_device *device,
>  				u64              *sn_pfx);
>  
>  #ifdef CONFIG_SECURITY_INFINIBAND
> +int ib_security_enforce_mad_agent_pkey_access(struct ib_device *dev,

We need to find a way to shorten the name. It is insane to use such long
name.

> +					      u8 port_num,
> +					      u16 pkey_index,
> +					      struct ib_mad_agent *mad_agent);
> +

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 10/13] ib/core: Enforce PKey security on management datagrams
@ 2016-04-07 20:39         ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 20:39 UTC (permalink / raw)
  To: Dan Jurgens; +Cc: selinux, linux-security-module, linux-rdma, yevgenyp

[-- Attachment #1: Type: text/plain, Size: 1399 bytes --]

On Thu, Apr 07, 2016 at 02:33:55AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> Allocate and free a security context when creating and destroying a MAD
> agent.  This context is used for controlling access to PKeys.
> 
> When sending or receiving a MAD check that the agent has permission to
> access the PKey for the Subnet Prefix of the port.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> Reviewed-by: Eli Cohen <eli@mellanox.com>
> ---
>  drivers/infiniband/core/core_priv.h     |   14 +++++++
>  drivers/infiniband/core/core_security.c |   17 ++++++++
>  drivers/infiniband/core/mad.c           |   65 +++++++++++++++++++++++++++---
>  3 files changed, 89 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
> index 27f2fa8..2759a18 100644
> --- a/drivers/infiniband/core/core_priv.h
> +++ b/drivers/infiniband/core/core_priv.h
> @@ -142,6 +142,11 @@ int ib_get_cached_subnet_prefix(struct ib_device *device,
>  				u64              *sn_pfx);
>  
>  #ifdef CONFIG_SECURITY_INFINIBAND
> +int ib_security_enforce_mad_agent_pkey_access(struct ib_device *dev,

We need to find a way to shorten the name. It is insane to use such long
name.

> +					      u8 port_num,
> +					      u16 pkey_index,
> +					      struct ib_mad_agent *mad_agent);
> +

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security
  2016-04-06 23:33 ` [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security Dan Jurgens
@ 2016-04-07 20:44       ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 20:44 UTC (permalink / raw)
  To: Dan Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	yevgenyp-VPRAkNaXOzVWk0Htik3J/w

[-- Attachment #1: Type: text/plain, Size: 4038 bytes --]

On Thu, Apr 07, 2016 at 02:33:56AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> During MAD and snoop agent registration for SMI QPs check that the
> calling process has permission to access the SMI.
> 
> When sending and receiving MADs check that the agent has access to the
> SMI if it's on an SMI QP.  Because security policy can change it's
> possible permission was allowed when creating the agent, but no longer
> is.
> 
> Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/infiniband/core/mad.c |   52 ++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 51 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
> index 907f8ee..b5f42ad 100644
> --- a/drivers/infiniband/core/mad.c
> +++ b/drivers/infiniband/core/mad.c
> @@ -349,6 +349,21 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
>  		goto error3;
>  	}
>  
> +	if (qp_type == IB_QPT_SMI) {
> +		ret2 = security_ibdev_smi(device->name,
> +					  port_num,
> +					  &mad_agent_priv->agent);
> +		if (ret2) {
> +			dev_err(&device->dev,
> +				"%s: Access Denied. Err: %d\n",

Please convert it to lower case.
Can malicious user flood the system with this print?

> +				__func__,
> +				ret2);
> +
> +			ret = ERR_PTR(ret2);
> +			goto error4;
> +		}
> +	}
> +
>  	if (mad_reg_req) {
>  		reg_req = kmemdup(mad_reg_req, sizeof *reg_req, GFP_KERNEL);
>  		if (!reg_req) {
> @@ -535,6 +550,22 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
>  		goto error2;
>  	}
>  
> +	if (qp_type == IB_QPT_SMI) {
> +		err = security_ibdev_smi(device->name,
> +					 port_num,
> +					 &mad_snoop_priv->agent);
> +
> +		if (err) {
> +			dev_err(&device->dev,
> +				"%s: Access Denied. Err: %d\n",

The same as above.

> +				__func__,
> +				err);
> +
> +			ret = ERR_PTR(err);
> +			goto error3;
> +		}
> +	}
> +
>  	/* Now, fill in the various structures */
>  	mad_snoop_priv->qp_info = &port_priv->qp_info[qpn];
>  	mad_snoop_priv->agent.device = device;
> @@ -1248,6 +1279,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
>  
>  	/* Walk list of send WRs and post each on send list */
>  	for (; send_buf; send_buf = next_send_buf) {
> +		int err = 0;
>  
>  		mad_send_wr = container_of(send_buf,
>  					   struct ib_mad_send_wr_private,
> @@ -1255,6 +1287,16 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
>  		mad_agent_priv = mad_send_wr->mad_agent_priv;
>  		pkey_index = mad_send_wr->send_wr.pkey_index;
>  
> +		if (mad_agent_priv->agent.qp->qp_type == IB_QPT_SMI)
> +			err = security_ibdev_smi(mad_agent_priv->agent.device->name,
> +						 mad_agent_priv->agent.port_num,
> +						 &mad_agent_priv->agent);
> +
> +		if (err) {
> +			ret = err;
> +			goto error;
> +		}
> +
>  		ret = ib_security_enforce_mad_agent_pkey_access(
>  					mad_agent_priv->agent.device,
>  					mad_agent_priv->agent.port_num,
> @@ -1997,7 +2039,15 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
>  	struct ib_mad_send_wr_private *mad_send_wr;
>  	struct ib_mad_send_wc mad_send_wc;
>  	unsigned long flags;
> -	int ret;
> +	int ret = 0;
> +
> +	if (mad_agent_priv->agent.qp->qp_type == IB_QPT_SMI)
> +		ret = security_ibdev_smi(mad_agent_priv->agent.device->name,
> +					 mad_agent_priv->agent.port_num,
> +					 &mad_agent_priv->agent);
> +
> +	if (ret)
> +		goto security_error;
>  
>  	ret = ib_security_enforce_mad_agent_pkey_access(
>  					      mad_agent_priv->agent.device,
> -- 
> 1.7.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security
@ 2016-04-07 20:44       ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 20:44 UTC (permalink / raw)
  To: Dan Jurgens; +Cc: selinux, linux-security-module, linux-rdma, yevgenyp

[-- Attachment #1: Type: text/plain, Size: 3933 bytes --]

On Thu, Apr 07, 2016 at 02:33:56AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> During MAD and snoop agent registration for SMI QPs check that the
> calling process has permission to access the SMI.
> 
> When sending and receiving MADs check that the agent has access to the
> SMI if it's on an SMI QP.  Because security policy can change it's
> possible permission was allowed when creating the agent, but no longer
> is.
> 
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> Reviewed-by: Eli Cohen <eli@mellanox.com>
> ---
>  drivers/infiniband/core/mad.c |   52 ++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 51 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
> index 907f8ee..b5f42ad 100644
> --- a/drivers/infiniband/core/mad.c
> +++ b/drivers/infiniband/core/mad.c
> @@ -349,6 +349,21 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
>  		goto error3;
>  	}
>  
> +	if (qp_type == IB_QPT_SMI) {
> +		ret2 = security_ibdev_smi(device->name,
> +					  port_num,
> +					  &mad_agent_priv->agent);
> +		if (ret2) {
> +			dev_err(&device->dev,
> +				"%s: Access Denied. Err: %d\n",

Please convert it to lower case.
Can malicious user flood the system with this print?

> +				__func__,
> +				ret2);
> +
> +			ret = ERR_PTR(ret2);
> +			goto error4;
> +		}
> +	}
> +
>  	if (mad_reg_req) {
>  		reg_req = kmemdup(mad_reg_req, sizeof *reg_req, GFP_KERNEL);
>  		if (!reg_req) {
> @@ -535,6 +550,22 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
>  		goto error2;
>  	}
>  
> +	if (qp_type == IB_QPT_SMI) {
> +		err = security_ibdev_smi(device->name,
> +					 port_num,
> +					 &mad_snoop_priv->agent);
> +
> +		if (err) {
> +			dev_err(&device->dev,
> +				"%s: Access Denied. Err: %d\n",

The same as above.

> +				__func__,
> +				err);
> +
> +			ret = ERR_PTR(err);
> +			goto error3;
> +		}
> +	}
> +
>  	/* Now, fill in the various structures */
>  	mad_snoop_priv->qp_info = &port_priv->qp_info[qpn];
>  	mad_snoop_priv->agent.device = device;
> @@ -1248,6 +1279,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
>  
>  	/* Walk list of send WRs and post each on send list */
>  	for (; send_buf; send_buf = next_send_buf) {
> +		int err = 0;
>  
>  		mad_send_wr = container_of(send_buf,
>  					   struct ib_mad_send_wr_private,
> @@ -1255,6 +1287,16 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
>  		mad_agent_priv = mad_send_wr->mad_agent_priv;
>  		pkey_index = mad_send_wr->send_wr.pkey_index;
>  
> +		if (mad_agent_priv->agent.qp->qp_type == IB_QPT_SMI)
> +			err = security_ibdev_smi(mad_agent_priv->agent.device->name,
> +						 mad_agent_priv->agent.port_num,
> +						 &mad_agent_priv->agent);
> +
> +		if (err) {
> +			ret = err;
> +			goto error;
> +		}
> +
>  		ret = ib_security_enforce_mad_agent_pkey_access(
>  					mad_agent_priv->agent.device,
>  					mad_agent_priv->agent.port_num,
> @@ -1997,7 +2039,15 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
>  	struct ib_mad_send_wr_private *mad_send_wr;
>  	struct ib_mad_send_wc mad_send_wc;
>  	unsigned long flags;
> -	int ret;
> +	int ret = 0;
> +
> +	if (mad_agent_priv->agent.qp->qp_type == IB_QPT_SMI)
> +		ret = security_ibdev_smi(mad_agent_priv->agent.device->name,
> +					 mad_agent_priv->agent.port_num,
> +					 &mad_agent_priv->agent);
> +
> +	if (ret)
> +		goto security_error;
>  
>  	ret = ib_security_enforce_mad_agent_pkey_access(
>  					      mad_agent_priv->agent.device,
> -- 
> 1.7.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 12/13] ib/core: Track which QPs are using which port and PKey index
  2016-04-06 23:33   ` [RFC PATCH v2 12/13] ib/core: Track which QPs are using which port and PKey index Dan Jurgens
@ 2016-04-07 20:53         ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 20:53 UTC (permalink / raw)
  To: Dan Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	yevgenyp-VPRAkNaXOzVWk0Htik3J/w

[-- Attachment #1: Type: text/plain, Size: 586 bytes --]

On Thu, Apr 07, 2016 at 02:33:57AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> --- a/drivers/infiniband/core/core_security.c
> +++ b/drivers/infiniband/core/core_security.c
> @@ -1,4 +1,5 @@
> -/*
> +/* NEW COMMIT TO INSERT INTO REBASE

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Irrelevant

> + *
>   * Copyright (c) 2016 Mellanox Technologies Ltd.  All rights reserved.
>   *
>   * This software is available to you under a choice of one of two
> @@ -33,11 +34,27 @@
>  #ifdef CONFIG_SECURITY_INFINIBAND
>  

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 12/13] ib/core: Track which QPs are using which port and PKey index
@ 2016-04-07 20:53         ` Leon Romanovsky
  0 siblings, 0 replies; 90+ messages in thread
From: Leon Romanovsky @ 2016-04-07 20:53 UTC (permalink / raw)
  To: Dan Jurgens; +Cc: selinux, linux-security-module, linux-rdma, yevgenyp

[-- Attachment #1: Type: text/plain, Size: 559 bytes --]

On Thu, Apr 07, 2016 at 02:33:57AM +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
> 
> --- a/drivers/infiniband/core/core_security.c
> +++ b/drivers/infiniband/core/core_security.c
> @@ -1,4 +1,5 @@
> -/*
> +/* NEW COMMIT TO INSERT INTO REBASE

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Irrelevant

> + *
>   * Copyright (c) 2016 Mellanox Technologies Ltd.  All rights reserved.
>   *
>   * This software is available to you under a choice of one of two
> @@ -33,11 +34,27 @@
>  #ifdef CONFIG_SECURITY_INFINIBAND
>  

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
  2016-04-07 16:31         ` Leon Romanovsky
@ 2016-04-07 21:02           ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 21:02 UTC (permalink / raw)
  To: leon-2ukJVAZIZ/Y
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
> 
>> +	if (sec->qp == sec->qp->real_qp) {
>> +		/* The caller of this function holds the QP security
>> +		 * mutex so this list traversal is safe
>> +		*/
> 
> Did the comment below pass checkpatch.pl?

It did.

>> +		list_for_each_entry(shared_qp_sec,
>> +				    &sec->shared_qp_list,
>> +				    shared_qp_list) {
> 
> Is this list always needed to be protected by lock?
> In general, I prefer to see lock/unlock operations near protected code.
> Otherwise, it is hard to follow all lock/unlock paths.

The mutex is required, and I'm not sure how to push it lower safely.
Consider the situation where a QP is being modified concurrently with an
open_shared_qp. Unless the lock is held the entire time for each
operation open_shared_qp could check permission using a ib_qp_security
struct in a partially modified state, i.e. there could be a mix of new
and old settings for the port/pkey index/alternate path.  Shared QPs use
the port and pkey setting for the underlying real QP with the shared qp
q_security.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
@ 2016-04-07 21:02           ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 21:02 UTC (permalink / raw)
  To: leon; +Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
> 
>> +	if (sec->qp == sec->qp->real_qp) {
>> +		/* The caller of this function holds the QP security
>> +		 * mutex so this list traversal is safe
>> +		*/
> 
> Did the comment below pass checkpatch.pl?

It did.

>> +		list_for_each_entry(shared_qp_sec,
>> +				    &sec->shared_qp_list,
>> +				    shared_qp_list) {
> 
> Is this list always needed to be protected by lock?
> In general, I prefer to see lock/unlock operations near protected code.
> Otherwise, it is hard to follow all lock/unlock paths.

The mutex is required, and I'm not sure how to push it lower safely.
Consider the situation where a QP is being modified concurrently with an
open_shared_qp. Unless the lock is held the entire time for each
operation open_shared_qp could check permission using a ib_qp_security
struct in a partially modified state, i.e. there could be a mix of new
and old settings for the port/pkey index/alternate path.  Shared QPs use
the port and pkey setting for the underlying real QP with the shared qp
q_security.

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
  2016-04-07 21:02           ` Daniel Jurgens
@ 2016-04-07 21:10               ` leon
  -1 siblings, 0 replies; 90+ messages in thread
From: leon-2ukJVAZIZ/Y @ 2016-04-07 21:10 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

[-- Attachment #1: Type: text/plain, Size: 1492 bytes --]

On Thu, Apr 07, 2016 at 09:02:43PM +0000, Daniel Jurgens wrote:
> On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
> > On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
> > 
> >> +	if (sec->qp == sec->qp->real_qp) {
> >> +		/* The caller of this function holds the QP security
> >> +		 * mutex so this list traversal is safe
> >> +		*/
> > 
> > Did the comment below pass checkpatch.pl?
> 
> It did.
> 
> >> +		list_for_each_entry(shared_qp_sec,
> >> +				    &sec->shared_qp_list,
> >> +				    shared_qp_list) {
> > 
> > Is this list always needed to be protected by lock?
> > In general, I prefer to see lock/unlock operations near protected code.
> > Otherwise, it is hard to follow all lock/unlock paths.
> 
> The mutex is required, and I'm not sure how to push it lower safely.
> Consider the situation where a QP is being modified concurrently with an
> open_shared_qp. Unless the lock is held the entire time for each
> operation open_shared_qp could check permission using a ib_qp_security
> struct in a partially modified state, i.e. there could be a mix of new
> and old settings for the port/pkey index/alternate path.  Shared QPs use
> the port and pkey setting for the underlying real QP with the shared qp
> q_security.

Common flow is to do everything in one place:
1. lock
2. check permissions
3. change
4. release lock

Your flow is much broader.
1. lock
2. check permission
3. do work
4. change
5. do work
6. release lock.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
@ 2016-04-07 21:10               ` leon
  0 siblings, 0 replies; 90+ messages in thread
From: leon @ 2016-04-07 21:10 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

[-- Attachment #1: Type: text/plain, Size: 1492 bytes --]

On Thu, Apr 07, 2016 at 09:02:43PM +0000, Daniel Jurgens wrote:
> On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
> > On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
> > 
> >> +	if (sec->qp == sec->qp->real_qp) {
> >> +		/* The caller of this function holds the QP security
> >> +		 * mutex so this list traversal is safe
> >> +		*/
> > 
> > Did the comment below pass checkpatch.pl?
> 
> It did.
> 
> >> +		list_for_each_entry(shared_qp_sec,
> >> +				    &sec->shared_qp_list,
> >> +				    shared_qp_list) {
> > 
> > Is this list always needed to be protected by lock?
> > In general, I prefer to see lock/unlock operations near protected code.
> > Otherwise, it is hard to follow all lock/unlock paths.
> 
> The mutex is required, and I'm not sure how to push it lower safely.
> Consider the situation where a QP is being modified concurrently with an
> open_shared_qp. Unless the lock is held the entire time for each
> operation open_shared_qp could check permission using a ib_qp_security
> struct in a partially modified state, i.e. there could be a mix of new
> and old settings for the port/pkey index/alternate path.  Shared QPs use
> the port and pkey setting for the underlying real QP with the shared qp
> q_security.

Common flow is to do everything in one place:
1. lock
2. check permissions
3. change
4. release lock

Your flow is much broader.
1. lock
2. check permission
3. do work
4. change
5. do work
6. release lock.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
  2016-04-07 21:10               ` leon
@ 2016-04-07 21:23                 ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 21:23 UTC (permalink / raw)
  To: leon-2ukJVAZIZ/Y
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/7/2016 4:11 PM, leon-2ukJVAZIZ/Y@public.gmane.org wrote:
> On Thu, Apr 07, 2016 at 09:02:43PM +0000, Daniel Jurgens wrote:
>> On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
>>> On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
>>>
>>>> +	if (sec->qp == sec->qp->real_qp) {
>>>> +		/* The caller of this function holds the QP security
>>>> +		 * mutex so this list traversal is safe
>>>> +		*/
>>>
>>> Did the comment below pass checkpatch.pl?
>>
>> It did.
>>
>>>> +		list_for_each_entry(shared_qp_sec,
>>>> +				    &sec->shared_qp_list,
>>>> +				    shared_qp_list) {
>>>
>>> Is this list always needed to be protected by lock?
>>> In general, I prefer to see lock/unlock operations near protected code.
>>> Otherwise, it is hard to follow all lock/unlock paths.
>>
>> The mutex is required, and I'm not sure how to push it lower safely.
>> Consider the situation where a QP is being modified concurrently with an
>> open_shared_qp. Unless the lock is held the entire time for each
>> operation open_shared_qp could check permission using a ib_qp_security
>> struct in a partially modified state, i.e. there could be a mix of new
>> and old settings for the port/pkey index/alternate path.  Shared QPs use
>> the port and pkey setting for the underlying real QP with the shared qp
>> q_security.
> 
> Common flow is to do everything in one place:
> 1. lock
> 2. check permissions
> 3. change
> 4. release lock
> 
> Your flow is much broader.
> 1. lock
> 2. check permission
> 3. do work
> 4. change
> 5. do work
> 6. release lock.
> 

I see what your saying. This is an artifact of me breaking this up into
two patches after the fact.  "[RFC PATCH v2 12/13] ib/core: Track which
QPs are using which port and PKey index" introduces the reason that is
needed.  In that patch lists of QP security structures are maintained
and walked when there are changes to pkey table or GIDs.  Those list
operations don't hold the QP security mutexes for all the QPs so it con
run concurrently with a QP modify. This means the QP needs to be added
to the new setting lists, and then clean up the lists after the modify
finishes.

I can change this patch to the common flow above, and then introduce "my
flow" in the patch that requires it.  Another option would be to squash
the two together.  They are both relatively large so I am hesitant to do
that.



--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
@ 2016-04-07 21:23                 ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 21:23 UTC (permalink / raw)
  To: leon; +Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/7/2016 4:11 PM, leon@leon.nu wrote:
> On Thu, Apr 07, 2016 at 09:02:43PM +0000, Daniel Jurgens wrote:
>> On 4/7/2016 11:31 AM, Leon Romanovsky wrote:
>>> On Thu, Apr 07, 2016 at 02:33:54AM +0300, Dan Jurgens wrote:
>>>
>>>> +	if (sec->qp == sec->qp->real_qp) {
>>>> +		/* The caller of this function holds the QP security
>>>> +		 * mutex so this list traversal is safe
>>>> +		*/
>>>
>>> Did the comment below pass checkpatch.pl?
>>
>> It did.
>>
>>>> +		list_for_each_entry(shared_qp_sec,
>>>> +				    &sec->shared_qp_list,
>>>> +				    shared_qp_list) {
>>>
>>> Is this list always needed to be protected by lock?
>>> In general, I prefer to see lock/unlock operations near protected code.
>>> Otherwise, it is hard to follow all lock/unlock paths.
>>
>> The mutex is required, and I'm not sure how to push it lower safely.
>> Consider the situation where a QP is being modified concurrently with an
>> open_shared_qp. Unless the lock is held the entire time for each
>> operation open_shared_qp could check permission using a ib_qp_security
>> struct in a partially modified state, i.e. there could be a mix of new
>> and old settings for the port/pkey index/alternate path.  Shared QPs use
>> the port and pkey setting for the underlying real QP with the shared qp
>> q_security.
> 
> Common flow is to do everything in one place:
> 1. lock
> 2. check permissions
> 3. change
> 4. release lock
> 
> Your flow is much broader.
> 1. lock
> 2. check permission
> 3. do work
> 4. change
> 5. do work
> 6. release lock.
> 

I see what your saying. This is an artifact of me breaking this up into
two patches after the fact.  "[RFC PATCH v2 12/13] ib/core: Track which
QPs are using which port and PKey index" introduces the reason that is
needed.  In that patch lists of QP security structures are maintained
and walked when there are changes to pkey table or GIDs.  Those list
operations don't hold the QP security mutexes for all the QPs so it con
run concurrently with a QP modify. This means the QP needs to be added
to the new setting lists, and then clean up the lists after the modify
finishes.

I can change this patch to the common flow above, and then introduce "my
flow" in the patch that requires it.  Another option would be to squash
the two together.  They are both relatively large so I am hesitant to do
that.

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

* Re: [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security
  2016-04-07 20:44       ` Leon Romanovsky
@ 2016-04-07 21:55         ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 21:55 UTC (permalink / raw)
  To: leon-2ukJVAZIZ/Y
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA

On 4/7/2016 3:54 PM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:56AM +0300, Dan Jurgens wrote:
>> +			dev_err(&device->dev,
>> +				"%s: Access Denied. Err: %d\n",
> 
> Please convert it to lower case.
> Can malicious user flood the system with this print?
>

>> +			dev_err(&device->dev,
>> +				"%s: Access Denied. Err: %d\n",
> 
> The same as above.
> 

I will just remove the prints unless you object.  The denial will be
captured in the audit log.

_______________________________________________
Selinux mailing list
Selinux-+05T5uksL2qpZYMLLGbcSA@public.gmane.org
To unsubscribe, send email to Selinux-leave-+05T5uksL2pAGbPMOrvdOA@public.gmane.org
To get help, send an email containing "help" to Selinux-request-+05T5uksL2pAGbPMOrvdOA@public.gmane.org

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

* Re: [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security
@ 2016-04-07 21:55         ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-07 21:55 UTC (permalink / raw)
  To: leon; +Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/7/2016 3:54 PM, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 02:33:56AM +0300, Dan Jurgens wrote:
>> +			dev_err(&device->dev,
>> +				"%s: Access Denied. Err: %d\n",
> 
> Please convert it to lower case.
> Can malicious user flood the system with this print?
>

>> +			dev_err(&device->dev,
>> +				"%s: Access Denied. Err: %d\n",
> 
> The same as above.
> 

I will just remove the prints unless you object.  The denial will be
captured in the audit log.

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
  2016-04-07 21:23                 ` Daniel Jurgens
@ 2016-04-07 23:24                     ` leon
  -1 siblings, 0 replies; 90+ messages in thread
From: leon-2ukJVAZIZ/Y @ 2016-04-07 23:24 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

[-- Attachment #1: Type: text/plain, Size: 422 bytes --]

On Thu, Apr 07, 2016 at 09:23:04PM +0000, Daniel Jurgens wrote:
> I can change this patch to the common flow above, and then introduce "my
> flow" in the patch that requires it.  Another option would be to squash
> the two together.  They are both relatively large so I am hesitant to do
> that.

It is up to you. There are two things which you can take into account
while doing it: correct code and easy review.

Thanks.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs
@ 2016-04-07 23:24                     ` leon
  0 siblings, 0 replies; 90+ messages in thread
From: leon @ 2016-04-07 23:24 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

[-- Attachment #1: Type: text/plain, Size: 422 bytes --]

On Thu, Apr 07, 2016 at 09:23:04PM +0000, Daniel Jurgens wrote:
> I can change this patch to the common flow above, and then introduce "my
> flow" in the patch that requires it.  Another option would be to squash
> the two together.  They are both relatively large so I am hesitant to do
> that.

It is up to you. There are two things which you can take into account
while doing it: correct code and easy review.

Thanks.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC PATCH v2 04/13] selinux: Allocate and free infiniband security hooks
  2016-04-06 23:33   ` [RFC PATCH v2 04/13] selinux: Allocate and free infiniband security hooks Dan Jurgens
@ 2016-04-11 15:24         ` Casey Schaufler
  0 siblings, 0 replies; 90+ messages in thread
From: Casey Schaufler @ 2016-04-11 15:24 UTC (permalink / raw)
  To: Dan Jurgens, selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: yevgenyp-VPRAkNaXOzVWk0Htik3J/w

On 4/6/2016 4:33 PM, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>
> Implement and attach hooks to allocate and free Infiniband QP and MAD
> agent security structures.
>
> Signed-off-by: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---
>  include/rdma/ib_mad.h             |    1 +
>  include/rdma/ib_verbs.h           |    5 +++

The ib_qp_security structure is defined here, but
referenced in 01/13. You should defined the structure
before you use it.

>  security/selinux/hooks.c          |   53 +++++++++++++++++++++++++++++++++++++
>  security/selinux/include/objsec.h |    5 +++
>  4 files changed, 64 insertions(+), 0 deletions(-)
>
> diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
> index 37dd534..772135c 100644
> --- a/include/rdma/ib_mad.h
> +++ b/include/rdma/ib_mad.h
> @@ -481,6 +481,7 @@ struct ib_mad_agent {
>  	u32			flags;
>  	u8			port_num;
>  	u8			rmpp_version;
> +	void			*m_security;
>  };
>  
>  /**
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index fb2cef4..66d37b8 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -1416,6 +1416,10 @@ struct ib_srq {
>  	} ext;
>  };
>  
> +struct ib_qp_security {
> +	void *q_security;
> +};
> +
>  struct ib_qp {
>  	struct ib_device       *device;
>  	struct ib_pd	       *pd;
> @@ -1433,6 +1437,7 @@ struct ib_qp {
>  	void		       *qp_context;
>  	u32			qp_num;
>  	enum ib_qp_type		qp_type;
> +	struct ib_qp_security  *qp_sec;
>  };
>  
>  struct ib_mr {
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 0fbf3f8..3ac29bd 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -17,6 +17,7 @@
>   *	Paul Moore <paul-r2n+y4ga6xFZroRs9YW3xA@public.gmane.org>
>   *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
>   *		       Yuichi Nakamura <ynakam-FkO1umbPgv4fag7Bw7Dlfw@public.gmane.org>
> + *  Copyright (C) 2016 Mellanox Technologies
>   *
>   *	This program is free software; you can redistribute it and/or modify
>   *	it under the terms of the GNU General Public License version 2,
> @@ -83,6 +84,8 @@
>  #include <linux/export.h>
>  #include <linux/msg.h>
>  #include <linux/shm.h>
> +#include <rdma/ib_verbs.h>
> +#include <rdma/ib_mad.h>
>  
>  #include "avc.h"
>  #include "objsec.h"
> @@ -5999,6 +6002,47 @@ static void selinux_unregister_ib_flush_callback(void)
>  	mutex_unlock(&ib_flush_mutex);
>  }
>  
> +static int selinux_ib_qp_alloc_security(struct ib_qp_security *qp_sec)
> +{
> +	struct ib_security_struct *sec;
> +
> +	sec = kzalloc(sizeof(*sec), GFP_ATOMIC);
> +	if (!sec)
> +		return -ENOMEM;
> +	sec->sid = current_sid();
> +
> +	qp_sec->q_security = sec;
> +	return 0;
> +}
> +
> +static void selinux_ib_qp_free_security(struct ib_qp_security *qp_sec)
> +{
> +	struct ib_security_struct *sec = qp_sec->q_security;
> +
> +	qp_sec->q_security = NULL;
> +	kfree(sec);
> +}
> +
> +static int selinux_ib_mad_agent_alloc_security(struct ib_mad_agent *mad_agent)
> +{
> +	struct ib_security_struct *sec;
> +
> +	sec = kzalloc(sizeof(*sec), GFP_ATOMIC);
> +	if (!sec)
> +		return -ENOMEM;
> +	sec->sid = current_sid();
> +
> +	mad_agent->m_security = sec;
> +	return 0;
> +}
> +
> +static void selinux_ib_mad_agent_free_security(struct ib_mad_agent *mad_agent)
> +{
> +	struct ib_security_struct *sec = mad_agent->m_security;
> +
> +	mad_agent->m_security = NULL;
> +	kfree(sec);
> +}
>  #endif
>  
>  static struct security_hook_list selinux_hooks[] = {
> @@ -6182,11 +6226,20 @@ static struct security_hook_list selinux_hooks[] = {
>  	LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
>  	LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
>  	LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
> +
>  #ifdef CONFIG_SECURITY_INFINIBAND
>  	LSM_HOOK_INIT(register_ib_flush_callback,
>  		      selinux_register_ib_flush_callback),
>  	LSM_HOOK_INIT(unregister_ib_flush_callback,
>  		      selinux_unregister_ib_flush_callback),
> +	LSM_HOOK_INIT(ib_qp_alloc_security,
> +		      selinux_ib_qp_alloc_security),
> +	LSM_HOOK_INIT(ib_qp_free_security,
> +		      selinux_ib_qp_free_security),
> +	LSM_HOOK_INIT(ib_mad_agent_alloc_security,
> +		      selinux_ib_mad_agent_alloc_security),
> +	LSM_HOOK_INIT(ib_mad_agent_free_security,
> +		      selinux_ib_mad_agent_free_security),
>  #endif
>  
>  #ifdef CONFIG_SECURITY_NETWORK_XFRM
> diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
> index c21e135..8e7db43 100644
> --- a/security/selinux/include/objsec.h
> +++ b/security/selinux/include/objsec.h
> @@ -10,6 +10,7 @@
>   *
>   *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
>   *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> + *  Copyright (C) 2016 Mellanox Technologies
>   *
>   *	This program is free software; you can redistribute it and/or modify
>   *	it under the terms of the GNU General Public License version 2,
> @@ -128,6 +129,10 @@ struct key_security_struct {
>  	u32 sid;	/* SID of key */
>  };
>  
> +struct ib_security_struct {
> +	u32 sid;        /* SID of the queue pair or MAD agent */
> +};
> +
>  extern unsigned int selinux_checkreqprot;
>  
>  #endif /* _SELINUX_OBJSEC_H_ */

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 04/13] selinux: Allocate and free infiniband security hooks
@ 2016-04-11 15:24         ` Casey Schaufler
  0 siblings, 0 replies; 90+ messages in thread
From: Casey Schaufler @ 2016-04-11 15:24 UTC (permalink / raw)
  To: Dan Jurgens, selinux, linux-security-module, linux-rdma

On 4/6/2016 4:33 PM, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
>
> Implement and attach hooks to allocate and free Infiniband QP and MAD
> agent security structures.
>
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> Reviewed-by: Eli Cohen <eli@mellanox.com>
> ---
>  include/rdma/ib_mad.h             |    1 +
>  include/rdma/ib_verbs.h           |    5 +++

The ib_qp_security structure is defined here, but
referenced in 01/13. You should defined the structure
before you use it.

>  security/selinux/hooks.c          |   53 +++++++++++++++++++++++++++++++++++++
>  security/selinux/include/objsec.h |    5 +++
>  4 files changed, 64 insertions(+), 0 deletions(-)
>
> diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
> index 37dd534..772135c 100644
> --- a/include/rdma/ib_mad.h
> +++ b/include/rdma/ib_mad.h
> @@ -481,6 +481,7 @@ struct ib_mad_agent {
>  	u32			flags;
>  	u8			port_num;
>  	u8			rmpp_version;
> +	void			*m_security;
>  };
>  
>  /**
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index fb2cef4..66d37b8 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -1416,6 +1416,10 @@ struct ib_srq {
>  	} ext;
>  };
>  
> +struct ib_qp_security {
> +	void *q_security;
> +};
> +
>  struct ib_qp {
>  	struct ib_device       *device;
>  	struct ib_pd	       *pd;
> @@ -1433,6 +1437,7 @@ struct ib_qp {
>  	void		       *qp_context;
>  	u32			qp_num;
>  	enum ib_qp_type		qp_type;
> +	struct ib_qp_security  *qp_sec;
>  };
>  
>  struct ib_mr {
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 0fbf3f8..3ac29bd 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -17,6 +17,7 @@
>   *	Paul Moore <paul@paul-moore.com>
>   *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
>   *		       Yuichi Nakamura <ynakam@hitachisoft.jp>
> + *  Copyright (C) 2016 Mellanox Technologies
>   *
>   *	This program is free software; you can redistribute it and/or modify
>   *	it under the terms of the GNU General Public License version 2,
> @@ -83,6 +84,8 @@
>  #include <linux/export.h>
>  #include <linux/msg.h>
>  #include <linux/shm.h>
> +#include <rdma/ib_verbs.h>
> +#include <rdma/ib_mad.h>
>  
>  #include "avc.h"
>  #include "objsec.h"
> @@ -5999,6 +6002,47 @@ static void selinux_unregister_ib_flush_callback(void)
>  	mutex_unlock(&ib_flush_mutex);
>  }
>  
> +static int selinux_ib_qp_alloc_security(struct ib_qp_security *qp_sec)
> +{
> +	struct ib_security_struct *sec;
> +
> +	sec = kzalloc(sizeof(*sec), GFP_ATOMIC);
> +	if (!sec)
> +		return -ENOMEM;
> +	sec->sid = current_sid();
> +
> +	qp_sec->q_security = sec;
> +	return 0;
> +}
> +
> +static void selinux_ib_qp_free_security(struct ib_qp_security *qp_sec)
> +{
> +	struct ib_security_struct *sec = qp_sec->q_security;
> +
> +	qp_sec->q_security = NULL;
> +	kfree(sec);
> +}
> +
> +static int selinux_ib_mad_agent_alloc_security(struct ib_mad_agent *mad_agent)
> +{
> +	struct ib_security_struct *sec;
> +
> +	sec = kzalloc(sizeof(*sec), GFP_ATOMIC);
> +	if (!sec)
> +		return -ENOMEM;
> +	sec->sid = current_sid();
> +
> +	mad_agent->m_security = sec;
> +	return 0;
> +}
> +
> +static void selinux_ib_mad_agent_free_security(struct ib_mad_agent *mad_agent)
> +{
> +	struct ib_security_struct *sec = mad_agent->m_security;
> +
> +	mad_agent->m_security = NULL;
> +	kfree(sec);
> +}
>  #endif
>  
>  static struct security_hook_list selinux_hooks[] = {
> @@ -6182,11 +6226,20 @@ static struct security_hook_list selinux_hooks[] = {
>  	LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
>  	LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
>  	LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
> +
>  #ifdef CONFIG_SECURITY_INFINIBAND
>  	LSM_HOOK_INIT(register_ib_flush_callback,
>  		      selinux_register_ib_flush_callback),
>  	LSM_HOOK_INIT(unregister_ib_flush_callback,
>  		      selinux_unregister_ib_flush_callback),
> +	LSM_HOOK_INIT(ib_qp_alloc_security,
> +		      selinux_ib_qp_alloc_security),
> +	LSM_HOOK_INIT(ib_qp_free_security,
> +		      selinux_ib_qp_free_security),
> +	LSM_HOOK_INIT(ib_mad_agent_alloc_security,
> +		      selinux_ib_mad_agent_alloc_security),
> +	LSM_HOOK_INIT(ib_mad_agent_free_security,
> +		      selinux_ib_mad_agent_free_security),
>  #endif
>  
>  #ifdef CONFIG_SECURITY_NETWORK_XFRM
> diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
> index c21e135..8e7db43 100644
> --- a/security/selinux/include/objsec.h
> +++ b/security/selinux/include/objsec.h
> @@ -10,6 +10,7 @@
>   *
>   *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
>   *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
> + *  Copyright (C) 2016 Mellanox Technologies
>   *
>   *	This program is free software; you can redistribute it and/or modify
>   *	it under the terms of the GNU General Public License version 2,
> @@ -128,6 +129,10 @@ struct key_security_struct {
>  	u32 sid;	/* SID of key */
>  };
>  
> +struct ib_security_struct {
> +	u32 sid;        /* SID of the queue pair or MAD agent */
> +};
> +
>  extern unsigned int selinux_checkreqprot;
>  
>  #endif /* _SELINUX_OBJSEC_H_ */

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-06 23:33 [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA Dan Jurgens
@ 2016-04-11 20:11     ` Jason Gunthorpe
  2016-04-06 23:33 ` [RFC PATCH v2 07/13] selinux: Add a cache for quicker retreival of PKey SIDs Dan Jurgens
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 90+ messages in thread
From: Jason Gunthorpe @ 2016-04-11 20:11 UTC (permalink / raw)
  To: Dan Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	yevgenyp-VPRAkNaXOzVWk0Htik3J/w

On Thu, Apr 07, 2016 at 02:33:45AM +0300, Dan Jurgens wrote:

> Currently there is no way to provide granular access control to an Infiniband
> fabric.  By providing an ability to restrict user access to specific virtual
> subfabrics administrators can limit access to bandwidth and isolate users on
> the fabric.

Do you actually have a concrete use case for this?

This seems superficially similar to netlabel, which I guess targets a
certain niche, but I'm really wondering with all the other container
patches if this was supposed to be done with namespaces...

> An Infiniband device (ibdev) is labeled by name and port number.  There is a
> single access vector for ibdevs as well, called "smi".

This is called an End Port (SMI is something else in the IB
spec). Please use the standard terminology.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-11 20:11     ` Jason Gunthorpe
  0 siblings, 0 replies; 90+ messages in thread
From: Jason Gunthorpe @ 2016-04-11 20:11 UTC (permalink / raw)
  To: Dan Jurgens; +Cc: selinux, linux-security-module, linux-rdma, yevgenyp

On Thu, Apr 07, 2016 at 02:33:45AM +0300, Dan Jurgens wrote:

> Currently there is no way to provide granular access control to an Infiniband
> fabric.  By providing an ability to restrict user access to specific virtual
> subfabrics administrators can limit access to bandwidth and isolate users on
> the fabric.

Do you actually have a concrete use case for this?

This seems superficially similar to netlabel, which I guess targets a
certain niche, but I'm really wondering with all the other container
patches if this was supposed to be done with namespaces...

> An Infiniband device (ibdev) is labeled by name and port number.  There is a
> single access vector for ibdevs as well, called "smi".

This is called an End Port (SMI is something else in the IB
spec). Please use the standard terminology.

Jason

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-11 20:11     ` Jason Gunthorpe
@ 2016-04-11 20:38       ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-11 20:38 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA

On 4/11/2016 3:12 PM, Jason Gunthorpe wrote:
> On Thu, Apr 07, 2016 at 02:33:45AM +0300, Dan Jurgens wrote:
> 
>> Currently there is no way to provide granular access control to an Infiniband
>> fabric.  By providing an ability to restrict user access to specific virtual
>> subfabrics administrators can limit access to bandwidth and isolate users on
>> the fabric.
> 
> Do you actually have a concrete use case for this?

We know the national labs are interested in this.

> This seems superficially similar to netlabel, which I guess targets a
> certain niche, but I'm really wondering with all the other container
> patches if this was supposed to be done with namespaces...

I can't speak to the goals of the other container patches.

Netlabel can't label kernel bypassed packets.  It can be used for IPoIB
though.

>> An Infiniband device (ibdev) is labeled by name and port number.  There is a
>> single access vector for ibdevs as well, called "smi".
> 
> This is called an End Port (SMI is something else in the IB
> spec). Please use the standard terminology.
I see your point on the end port, I'll address this is the next series
by updating the commit messages and replacing ibdev with ibendport.

I don't understand where you think I've gone wrong on SMI.

>From section 3.4.5.2: "Each node provides a Subnet Management Agent
(SMA) that the SM access through a well known interface called the
Subnet Management Interface (SMI)."

Thanks,
Dan


_______________________________________________
Selinux mailing list
Selinux-+05T5uksL2qpZYMLLGbcSA@public.gmane.org
To unsubscribe, send email to Selinux-leave-+05T5uksL2pAGbPMOrvdOA@public.gmane.org
To get help, send an email containing "help" to Selinux-request-+05T5uksL2pAGbPMOrvdOA@public.gmane.org

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-11 20:38       ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-11 20:38 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/11/2016 3:12 PM, Jason Gunthorpe wrote:
> On Thu, Apr 07, 2016 at 02:33:45AM +0300, Dan Jurgens wrote:
> 
>> Currently there is no way to provide granular access control to an Infiniband
>> fabric.  By providing an ability to restrict user access to specific virtual
>> subfabrics administrators can limit access to bandwidth and isolate users on
>> the fabric.
> 
> Do you actually have a concrete use case for this?

We know the national labs are interested in this.

> This seems superficially similar to netlabel, which I guess targets a
> certain niche, but I'm really wondering with all the other container
> patches if this was supposed to be done with namespaces...

I can't speak to the goals of the other container patches.

Netlabel can't label kernel bypassed packets.  It can be used for IPoIB
though.

>> An Infiniband device (ibdev) is labeled by name and port number.  There is a
>> single access vector for ibdevs as well, called "smi".
> 
> This is called an End Port (SMI is something else in the IB
> spec). Please use the standard terminology.
I see your point on the end port, I'll address this is the next series
by updating the commit messages and replacing ibdev with ibendport.

I don't understand where you think I've gone wrong on SMI.

>From section 3.4.5.2: "Each node provides a Subnet Management Agent
(SMA) that the SM access through a well known interface called the
Subnet Management Interface (SMI)."

Thanks,
Dan

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

* Re: [RFC PATCH v2 04/13] selinux: Allocate and free infiniband security hooks
  2016-04-11 15:24         ` Casey Schaufler
  (?)
@ 2016-04-11 20:41         ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-11 20:41 UTC (permalink / raw)
  To: Casey Schaufler, selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA
  Cc: Yevgeny Petrilin

On 4/11/2016 10:25 AM, Casey Schaufler wrote:
> On 4/6/2016 4:33 PM, Dan Jurgens wrote:
>> From: Daniel Jurgens <danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>>  include/rdma/ib_verbs.h           |    5 +++
> 
> The ib_qp_security structure is defined here, but
> referenced in 01/13. You should defined the structure
> before you use it.
> 

OK, the pointer wasn't accessed by field until this series, but I can
pull this back to 01/13 in the next version of the series.  Most likely
sometime tomorrow.

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-11 20:38       ` Daniel Jurgens
@ 2016-04-11 22:12           ` Jason Gunthorpe
  -1 siblings, 0 replies; 90+ messages in thread
From: Jason Gunthorpe @ 2016-04-11 22:12 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On Mon, Apr 11, 2016 at 08:38:50PM +0000, Daniel Jurgens wrote:

> > This seems superficially similar to netlabel, which I guess targets a
> > certain niche, but I'm really wondering with all the other container
> > patches if this was supposed to be done with namespaces...
> 
> I can't speak to the goals of the other container patches.
> 
> Netlabel can't label kernel bypassed packets.  It can be used for IPoIB
> though.

I guess I'm surprised the first pass at this wasn't to ride on
netlabel at least for all the parts that use IPoIB for addressing (eg
typical rdmacm)

> >> An Infiniband device (ibdev) is labeled by name and port number.  There is a
> >> single access vector for ibdevs as well, called "smi".
> > 
> > This is called an End Port (SMI is something else in the IB
> > spec). Please use the standard terminology.
> I see your point on the end port, I'll address this is the next series
> by updating the commit messages and replacing ibdev with ibendport.
> 
> I don't understand where you think I've gone wrong on SMI.

Well, this makes no sense:
 There is a single access vector for ibdevs as well, called "smi".

SMI is not umad. SMI should only refer to the SMA access channel on a
specific node, and I have no idea why someone would want to restrict
local SMA access independently of generic umad qp0 access. Just call
it QP0 or QP1 or umad.

SMI is an obscure internal term that should not be user facing.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-11 22:12           ` Jason Gunthorpe
  0 siblings, 0 replies; 90+ messages in thread
From: Jason Gunthorpe @ 2016-04-11 22:12 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On Mon, Apr 11, 2016 at 08:38:50PM +0000, Daniel Jurgens wrote:

> > This seems superficially similar to netlabel, which I guess targets a
> > certain niche, but I'm really wondering with all the other container
> > patches if this was supposed to be done with namespaces...
> 
> I can't speak to the goals of the other container patches.
> 
> Netlabel can't label kernel bypassed packets.  It can be used for IPoIB
> though.

I guess I'm surprised the first pass at this wasn't to ride on
netlabel at least for all the parts that use IPoIB for addressing (eg
typical rdmacm)

> >> An Infiniband device (ibdev) is labeled by name and port number.  There is a
> >> single access vector for ibdevs as well, called "smi".
> > 
> > This is called an End Port (SMI is something else in the IB
> > spec). Please use the standard terminology.
> I see your point on the end port, I'll address this is the next series
> by updating the commit messages and replacing ibdev with ibendport.
> 
> I don't understand where you think I've gone wrong on SMI.

Well, this makes no sense:
 There is a single access vector for ibdevs as well, called "smi".

SMI is not umad. SMI should only refer to the SMA access channel on a
specific node, and I have no idea why someone would want to restrict
local SMA access independently of generic umad qp0 access. Just call
it QP0 or QP1 or umad.

SMI is an obscure internal term that should not be user facing.

Jason

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-11 22:12           ` Jason Gunthorpe
@ 2016-04-11 22:30             ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-11 22:30 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/11/2016 5:12 PM, Jason Gunthorpe wrote:
> On Mon, Apr 11, 2016 at 08:38:50PM +0000, Daniel Jurgens wrote:
>>>> An Infiniband device (ibdev) is labeled by name and port number.  There is a
>>>> single access vector for ibdevs as well, called "smi".
>>>
>>> This is called an End Port (SMI is something else in the IB
>>> spec). Please use the standard terminology.
>> I see your point on the end port, I'll address this is the next series
>> by updating the commit messages and replacing ibdev with ibendport.
>>
>> I don't understand where you think I've gone wrong on SMI.
> 
> Well, this makes no sense:
>  There is a single access vector for ibdevs as well, called "smi".

Access vector is an SELinux term.  Object have access vectors.  For
example a file object has has many access vectors like "read", "write",
"unlink", etc.  Policy rules allow access to a type of object on a
subset of its access vectors.

Controlling the "smi" is to prevent someone from starting a subnet manager.

> SMI is not umad. SMI should only refer to the SMA access channel on a
> specific node, and I have no idea why someone would want to restrict
> local SMA access independently of generic umad qp0 access. Just call
> it QP0 or QP1 or umad.
> 
> SMI is an obscure internal term that should not be user facing.
> 

The point of control here is MAD agent registration and MAD transmit and
receive.  When a MAD agent is created it inherits the security ID of
it's parent task.  For MAD agents that have a QP of type IB_QPT_SMI,
when an attempt is made to send a MAD the security ID of the MAD agent
is checked for access to the SMI vector of the IB device (to become End
Port).  This is only for MAD agents that have a qp with of type
IB_QPT_SMI.  So having umad as the access vector is too broad.

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-11 22:30             ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-11 22:30 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/11/2016 5:12 PM, Jason Gunthorpe wrote:
> On Mon, Apr 11, 2016 at 08:38:50PM +0000, Daniel Jurgens wrote:
>>>> An Infiniband device (ibdev) is labeled by name and port number.  There is a
>>>> single access vector for ibdevs as well, called "smi".
>>>
>>> This is called an End Port (SMI is something else in the IB
>>> spec). Please use the standard terminology.
>> I see your point on the end port, I'll address this is the next series
>> by updating the commit messages and replacing ibdev with ibendport.
>>
>> I don't understand where you think I've gone wrong on SMI.
> 
> Well, this makes no sense:
>  There is a single access vector for ibdevs as well, called "smi".

Access vector is an SELinux term.  Object have access vectors.  For
example a file object has has many access vectors like "read", "write",
"unlink", etc.  Policy rules allow access to a type of object on a
subset of its access vectors.

Controlling the "smi" is to prevent someone from starting a subnet manager.

> SMI is not umad. SMI should only refer to the SMA access channel on a
> specific node, and I have no idea why someone would want to restrict
> local SMA access independently of generic umad qp0 access. Just call
> it QP0 or QP1 or umad.
> 
> SMI is an obscure internal term that should not be user facing.
> 

The point of control here is MAD agent registration and MAD transmit and
receive.  When a MAD agent is created it inherits the security ID of
it's parent task.  For MAD agents that have a QP of type IB_QPT_SMI,
when an attempt is made to send a MAD the security ID of the MAD agent
is checked for access to the SMI vector of the IB device (to become End
Port).  This is only for MAD agents that have a qp with of type
IB_QPT_SMI.  So having umad as the access vector is too broad.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-11 22:30             ` Daniel Jurgens
@ 2016-04-11 23:12                 ` Jason Gunthorpe
  -1 siblings, 0 replies; 90+ messages in thread
From: Jason Gunthorpe @ 2016-04-11 23:12 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On Mon, Apr 11, 2016 at 10:30:54PM +0000, Daniel Jurgens wrote:

> > SMI is not umad. SMI should only refer to the SMA access channel on a
> > specific node, and I have no idea why someone would want to restrict
> > local SMA access independently of generic umad qp0 access. Just call
> > it QP0 or QP1 or umad.
> > 
> > SMI is an obscure internal term that should not be user facing.
 
> The point of control here is MAD agent registration and MAD transmit and
> receive.  When a MAD agent is created it inherits the security ID of
> it's parent task.  For MAD agents that have a QP of type IB_QPT_SMI,
> when an attempt is made to send a MAD the security ID of the MAD agent
> is checked for access to the SMI vector of the IB device (to become End
> Port).  This is only for MAD agents that have a qp with of type
> IB_QPT_SMI.  So having umad as the access vector is too broad.

Like I said, the user facing name should be QP0 in that case.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-11 23:12                 ` Jason Gunthorpe
  0 siblings, 0 replies; 90+ messages in thread
From: Jason Gunthorpe @ 2016-04-11 23:12 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On Mon, Apr 11, 2016 at 10:30:54PM +0000, Daniel Jurgens wrote:

> > SMI is not umad. SMI should only refer to the SMA access channel on a
> > specific node, and I have no idea why someone would want to restrict
> > local SMA access independently of generic umad qp0 access. Just call
> > it QP0 or QP1 or umad.
> > 
> > SMI is an obscure internal term that should not be user facing.
 
> The point of control here is MAD agent registration and MAD transmit and
> receive.  When a MAD agent is created it inherits the security ID of
> it's parent task.  For MAD agents that have a QP of type IB_QPT_SMI,
> when an attempt is made to send a MAD the security ID of the MAD agent
> is checked for access to the SMI vector of the IB device (to become End
> Port).  This is only for MAD agents that have a qp with of type
> IB_QPT_SMI.  So having umad as the access vector is too broad.

Like I said, the user facing name should be QP0 in that case.

Jason

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-11 23:12                 ` Jason Gunthorpe
@ 2016-04-11 23:35                   ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-11 23:35 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/11/2016 6:12 PM, Jason Gunthorpe wrote:
> On Mon, Apr 11, 2016 at 10:30:54PM +0000, Daniel Jurgens wrote:
> 
> Like I said, the user facing name should be QP0 in that case.
> 
> Jason
> 

OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
SELinux user space code doesn't allow numbers in access vector identifiers.

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-11 23:35                   ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-11 23:35 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/11/2016 6:12 PM, Jason Gunthorpe wrote:
> On Mon, Apr 11, 2016 at 10:30:54PM +0000, Daniel Jurgens wrote:
> 
> Like I said, the user facing name should be QP0 in that case.
> 
> Jason
> 

OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
SELinux user space code doesn't allow numbers in access vector identifiers.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-11 23:35                   ` Daniel Jurgens
  (?)
@ 2016-04-12  0:06                   ` Jason Gunthorpe
       [not found]                     ` <20160412000621.GD5861-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  2016-04-12 16:45                       ` Daniel Jurgens
  -1 siblings, 2 replies; 90+ messages in thread
From: Jason Gunthorpe @ 2016-04-12  0:06 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On Mon, Apr 11, 2016 at 11:35:57PM +0000, Daniel Jurgens wrote:

> OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
> SELinux user space code doesn't allow numbers in access vector identifiers.

Do you know why you'd want to access control qp0 but leave qp1 open?

Still seems kinda strange.

Jason

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-11 23:35                   ` Daniel Jurgens
  (?)
  (?)
@ 2016-04-12  5:12                   ` Hal Rosenstock
  2016-04-12 16:43                       ` Daniel Jurgens
  -1 siblings, 1 reply; 90+ messages in thread
From: Hal Rosenstock @ 2016-04-12  5:12 UTC (permalink / raw)
  To: Daniel Jurgens, Jason Gunthorpe
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/11/2016 7:35 PM, Daniel Jurgens wrote:
> On 4/11/2016 6:12 PM, Jason Gunthorpe wrote:
>> On Mon, Apr 11, 2016 at 10:30:54PM +0000, Daniel Jurgens wrote:
>>
>> Like I said, the user facing name should be QP0 in that case.
>>
>> Jason
>>
> 
> OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
> SELinux user space code doesn't allow numbers in access vector identifiers.

Another possible name for this is smp.

-- Hal


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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-12  0:06                   ` Jason Gunthorpe
@ 2016-04-12  5:21                         ` Hal Rosenstock
  2016-04-12 16:45                       ` Daniel Jurgens
  1 sibling, 0 replies; 90+ messages in thread
From: Hal Rosenstock @ 2016-04-12  5:21 UTC (permalink / raw)
  To: Jason Gunthorpe, Daniel Jurgens
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/11/2016 8:06 PM, Jason Gunthorpe wrote:
> On Mon, Apr 11, 2016 at 11:35:57PM +0000, Daniel Jurgens wrote:
> 
>> OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
>> SELinux user space code doesn't allow numbers in access vector identifiers.
> 
> Do you know why you'd want to access control qp0 but leave qp1 open?

Wouldn't QP1 require different access control than QP0 due to SA clients
on every end node ?

-- Hal

> Still seems kinda strange.
> 
> Jason
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-12  5:21                         ` Hal Rosenstock
  0 siblings, 0 replies; 90+ messages in thread
From: Hal Rosenstock @ 2016-04-12  5:21 UTC (permalink / raw)
  To: Jason Gunthorpe, Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/11/2016 8:06 PM, Jason Gunthorpe wrote:
> On Mon, Apr 11, 2016 at 11:35:57PM +0000, Daniel Jurgens wrote:
> 
>> OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
>> SELinux user space code doesn't allow numbers in access vector identifiers.
> 
> Do you know why you'd want to access control qp0 but leave qp1 open?

Wouldn't QP1 require different access control than QP0 due to SA clients
on every end node ?

-- Hal

> Still seems kinda strange.
> 
> Jason
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-12  5:12                   ` Hal Rosenstock
@ 2016-04-12 16:43                       ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-12 16:43 UTC (permalink / raw)
  To: Hal Rosenstock, Jason Gunthorpe
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA

On 4/12/2016 12:12 AM, Hal Rosenstock wrote:
> On 4/11/2016 7:35 PM, Daniel Jurgens wrote:
>> On 4/11/2016 6:12 PM, Jason Gunthorpe wrote:
>>> On Mon, Apr 11, 2016 at 10:30:54PM +0000, Daniel Jurgens wrote:
>>>
>>> Like I said, the user facing name should be QP0 in that case.
>>>
>>> Jason
>>>
>>
>> OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
>> SELinux user space code doesn't allow numbers in access vector identifiers.
> 
> Another possible name for this is smp.
> 
> -- Hal
> 
> 

Thanks Hal, I'll go with that as long as Jason doesn't object.

_______________________________________________
Selinux mailing list
Selinux-+05T5uksL2qpZYMLLGbcSA@public.gmane.org
To unsubscribe, send email to Selinux-leave-+05T5uksL2pAGbPMOrvdOA@public.gmane.org
To get help, send an email containing "help" to Selinux-request-+05T5uksL2pAGbPMOrvdOA@public.gmane.org

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-12 16:43                       ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-12 16:43 UTC (permalink / raw)
  To: Hal Rosenstock, Jason Gunthorpe
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/12/2016 12:12 AM, Hal Rosenstock wrote:
> On 4/11/2016 7:35 PM, Daniel Jurgens wrote:
>> On 4/11/2016 6:12 PM, Jason Gunthorpe wrote:
>>> On Mon, Apr 11, 2016 at 10:30:54PM +0000, Daniel Jurgens wrote:
>>>
>>> Like I said, the user facing name should be QP0 in that case.
>>>
>>> Jason
>>>
>>
>> OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
>> SELinux user space code doesn't allow numbers in access vector identifiers.
> 
> Another possible name for this is smp.
> 
> -- Hal
> 
> 

Thanks Hal, I'll go with that as long as Jason doesn't object.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-12  0:06                   ` Jason Gunthorpe
@ 2016-04-12 16:45                       ` Daniel Jurgens
  2016-04-12 16:45                       ` Daniel Jurgens
  1 sibling, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-12 16:45 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/11/2016 7:06 PM, Jason Gunthorpe wrote:
> On Mon, Apr 11, 2016 at 11:35:57PM +0000, Daniel Jurgens wrote:
> 
>> OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
>> SELinux user space code doesn't allow numbers in access vector identifiers.
> 
> Do you know why you'd want to access control qp0 but leave qp1 open?
> 
> Still seems kinda strange.
> 
> Jason
> 

The point is to restrict the ability to run an SM.  MADs go through PKey
enforcement as well.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-12 16:45                       ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-12 16:45 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/11/2016 7:06 PM, Jason Gunthorpe wrote:
> On Mon, Apr 11, 2016 at 11:35:57PM +0000, Daniel Jurgens wrote:
> 
>> OK, I'll change idbev to ibendport and smi to qp0, or qpzero if the
>> SELinux user space code doesn't allow numbers in access vector identifiers.
> 
> Do you know why you'd want to access control qp0 but leave qp1 open?
> 
> Still seems kinda strange.
> 
> Jason
> 

The point is to restrict the ability to run an SM.  MADs go through PKey
enforcement as well.

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

* RE: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-12  5:21                         ` Hal Rosenstock
  (?)
@ 2016-04-12 17:06                         ` Hefty, Sean
  2016-04-12 17:58                           ` Jason Gunthorpe
  2016-04-13  5:07                           ` Hal Rosenstock
  -1 siblings, 2 replies; 90+ messages in thread
From: Hefty, Sean @ 2016-04-12 17:06 UTC (permalink / raw)
  To: Hal Rosenstock, Jason Gunthorpe, Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

> Wouldn't QP1 require different access control than QP0 due to SA clients
> on every end node ?

QP1 still allows modification of the fabric (e.g. multicast join) or an DoS attack against the SA.  Though the latter probably requires restricting how a UD QP may be used.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-12 17:06                         ` Hefty, Sean
@ 2016-04-12 17:58                           ` Jason Gunthorpe
       [not found]                             ` <20160412175837.GA15027-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  2016-04-13  5:07                           ` Hal Rosenstock
  1 sibling, 1 reply; 90+ messages in thread
From: Jason Gunthorpe @ 2016-04-12 17:58 UTC (permalink / raw)
  To: Hefty, Sean
  Cc: Hal Rosenstock, Daniel Jurgens, selinux, linux-security-module,
	linux-rdma, Yevgeny Petrilin

On Tue, Apr 12, 2016 at 05:06:45PM +0000, Hefty, Sean wrote:
> > Wouldn't QP1 require different access control than QP0 due to SA clients
> > on every end node ?
> 
> QP1 still allows modification of the fabric (e.g. multicast join) or
> an DoS attack against the SA.  Though the latter probably requires
> restricting how a UD QP may be used.

Right, I don't disagree we should have smp and gmp 'just in case'
(fine names as well) labels, I just don't really understand why you'd
trust something enough to grant gmp but not enough for smp...

Particularly encouraging people to grant gmp as though that was 'safe'
is really bad advice.

Which in turn makes me wonder why the umad dev node label is not
sufficient.

Jason

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-12 17:06                         ` Hefty, Sean
  2016-04-12 17:58                           ` Jason Gunthorpe
@ 2016-04-13  5:07                           ` Hal Rosenstock
  2016-04-13 16:47                             ` Hefty, Sean
  1 sibling, 1 reply; 90+ messages in thread
From: Hal Rosenstock @ 2016-04-13  5:07 UTC (permalink / raw)
  To: Hefty, Sean, Jason Gunthorpe, Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/12/2016 1:06 PM, Hefty, Sean wrote:
>> Wouldn't QP1 require different access control than QP0 due to SA clients
>> on every end node ?
> 
> QP1 still allows modification of the fabric (e.g. multicast join) or an DoS attack against the SA.  does
> Though the latter probably requires restricting how a UD QP may be used.

Former (multicast modifications of fabric) also requires restricting
arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-12 17:58                           ` Jason Gunthorpe
@ 2016-04-13 12:09                                 ` Hal Rosenstock
  0 siblings, 0 replies; 90+ messages in thread
From: Hal Rosenstock @ 2016-04-13 12:09 UTC (permalink / raw)
  To: Jason Gunthorpe, Hefty, Sean
  Cc: Daniel Jurgens, selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/12/2016 1:58 PM, Jason Gunthorpe wrote:
> On Tue, Apr 12, 2016 at 05:06:45PM +0000, Hefty, Sean wrote:
>>> Wouldn't QP1 require different access control than QP0 due to SA clients
>>> on every end node ?
>>
>> QP1 still allows modification of the fabric (e.g. multicast join) or
>> an DoS attack against the SA.  Though the latter probably requires
>> restricting how a UD QP may be used.
> 
> Right, I don't disagree we should have smp and gmp 'just in case'
> (fine names as well) labels, I just don't really understand why you'd
> trust something enough to grant gmp but not enough for smp...
> 
> Particularly encouraging people to grant gmp as though that was 'safe'
> is really bad advice.

I'm not sure what the motivation is either. The nature of the QP1 threat
is somewhat different from the QP0 threat. Only thing I can think of is
that it's hard to protect GMPs/QP1 since any UD QP can send to QP1.

-- Hal

> Which in turn makes me wonder why the umad dev node label is not
> sufficient.
> 
> Jason
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-13 12:09                                 ` Hal Rosenstock
  0 siblings, 0 replies; 90+ messages in thread
From: Hal Rosenstock @ 2016-04-13 12:09 UTC (permalink / raw)
  To: Jason Gunthorpe, Hefty, Sean
  Cc: Daniel Jurgens, selinux, linux-security-module, linux-rdma,
	Yevgeny Petrilin

On 4/12/2016 1:58 PM, Jason Gunthorpe wrote:
> On Tue, Apr 12, 2016 at 05:06:45PM +0000, Hefty, Sean wrote:
>>> Wouldn't QP1 require different access control than QP0 due to SA clients
>>> on every end node ?
>>
>> QP1 still allows modification of the fabric (e.g. multicast join) or
>> an DoS attack against the SA.  Though the latter probably requires
>> restricting how a UD QP may be used.
> 
> Right, I don't disagree we should have smp and gmp 'just in case'
> (fine names as well) labels, I just don't really understand why you'd
> trust something enough to grant gmp but not enough for smp...
> 
> Particularly encouraging people to grant gmp as though that was 'safe'
> is really bad advice.

I'm not sure what the motivation is either. The nature of the QP1 threat
is somewhat different from the QP0 threat. Only thing I can think of is
that it's hard to protect GMPs/QP1 since any UD QP can send to QP1.

-- Hal

> Which in turn makes me wonder why the umad dev node label is not
> sufficient.
> 
> Jason
> 

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-13 12:09                                 ` Hal Rosenstock
@ 2016-04-13 13:17                                   ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-13 13:17 UTC (permalink / raw)
  To: Hal Rosenstock, Jason Gunthorpe, Hefty, Sean
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA

On 4/13/2016 7:10 AM, Hal Rosenstock wrote:
> On 4/12/2016 1:58 PM, Jason Gunthorpe wrote:
>> On Tue, Apr 12, 2016 at 05:06:45PM +0000, Hefty, Sean wrote:
>>>> Wouldn't QP1 require different access control than QP0 due to SA clients
>>>> on every end node ?
>>>
>>> QP1 still allows modification of the fabric (e.g. multicast join) or
>>> an DoS attack against the SA.  Though the latter probably requires
>>> restricting how a UD QP may be used.
>>
>> Right, I don't disagree we should have smp and gmp 'just in case'
>> (fine names as well) labels, I just don't really understand why you'd
>> trust something enough to grant gmp but not enough for smp...
>>
>> Particularly encouraging people to grant gmp as though that was 'safe'
>> is really bad advice.
> 
> I'm not sure what the motivation is either. The nature of the QP1 threat
> is somewhat different from the QP0 threat. Only thing I can think of is
> that it's hard to protect GMPs/QP1 since any UD QP can send to QP1.
> 
> -- Hal
> 
>> Which in turn makes me wonder why the umad dev node label is not
>> sufficient.
>>
>> Jason
>>
> 

I've asked Liran to look over this thread, I'd like him to weigh in.  He
said he will have time tomorrow.

_______________________________________________
Selinux mailing list
Selinux-+05T5uksL2qpZYMLLGbcSA@public.gmane.org
To unsubscribe, send email to Selinux-leave-+05T5uksL2pAGbPMOrvdOA@public.gmane.org
To get help, send an email containing "help" to Selinux-request-+05T5uksL2pAGbPMOrvdOA@public.gmane.org

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-13 13:17                                   ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-13 13:17 UTC (permalink / raw)
  To: Hal Rosenstock, Jason Gunthorpe, Hefty, Sean
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/13/2016 7:10 AM, Hal Rosenstock wrote:
> On 4/12/2016 1:58 PM, Jason Gunthorpe wrote:
>> On Tue, Apr 12, 2016 at 05:06:45PM +0000, Hefty, Sean wrote:
>>>> Wouldn't QP1 require different access control than QP0 due to SA clients
>>>> on every end node ?
>>>
>>> QP1 still allows modification of the fabric (e.g. multicast join) or
>>> an DoS attack against the SA.  Though the latter probably requires
>>> restricting how a UD QP may be used.
>>
>> Right, I don't disagree we should have smp and gmp 'just in case'
>> (fine names as well) labels, I just don't really understand why you'd
>> trust something enough to grant gmp but not enough for smp...
>>
>> Particularly encouraging people to grant gmp as though that was 'safe'
>> is really bad advice.
> 
> I'm not sure what the motivation is either. The nature of the QP1 threat
> is somewhat different from the QP0 threat. Only thing I can think of is
> that it's hard to protect GMPs/QP1 since any UD QP can send to QP1.
> 
> -- Hal
> 
>> Which in turn makes me wonder why the umad dev node label is not
>> sufficient.
>>
>> Jason
>>
> 

I've asked Liran to look over this thread, I'd like him to weigh in.  He
said he will have time tomorrow.

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

* RE: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-13  5:07                           ` Hal Rosenstock
@ 2016-04-13 16:47                             ` Hefty, Sean
       [not found]                               ` <1828884A29C6694DAF28B7E6B8A82373AB041285-P5GAC/sN6hkd3b2yrw5b5LfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 90+ messages in thread
From: Hefty, Sean @ 2016-04-13 16:47 UTC (permalink / raw)
  To: Hal Rosenstock, Jason Gunthorpe, Daniel Jurgens
  Cc: selinux, linux-security-module, linux-rdma, Yevgeny Petrilin

> Former (multicast modifications of fabric) also requires restricting
> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.

The SA could have an option to ignore all requests that do not originate QP1, then protect access to QP1 on the client nodes.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-13 16:47                             ` Hefty, Sean
@ 2016-04-14  0:27                                   ` Ira Weiny
  0 siblings, 0 replies; 90+ messages in thread
From: Ira Weiny @ 2016-04-14  0:27 UTC (permalink / raw)
  To: Hefty, Sean
  Cc: Hal Rosenstock, Jason Gunthorpe, Daniel Jurgens,
	selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On Wed, Apr 13, 2016 at 04:47:48PM +0000, Sean Hefty wrote:
> > Former (multicast modifications of fabric) also requires restricting
> > arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
> 
> The SA could have an option to ignore all requests that do not originate QP1,
> then protect access to QP1 on the client nodes.

I'm not really sure what we are protecting against here.  Is it simply DoS
against the SA?

Ira

> --
>
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-14  0:27                                   ` Ira Weiny
  0 siblings, 0 replies; 90+ messages in thread
From: Ira Weiny @ 2016-04-14  0:27 UTC (permalink / raw)
  To: Hefty, Sean
  Cc: Hal Rosenstock, Jason Gunthorpe, Daniel Jurgens, selinux,
	linux-security-module, linux-rdma, Yevgeny Petrilin

On Wed, Apr 13, 2016 at 04:47:48PM +0000, Sean Hefty wrote:
> > Former (multicast modifications of fabric) also requires restricting
> > arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
> 
> The SA could have an option to ignore all requests that do not originate QP1,
> then protect access to QP1 on the client nodes.

I'm not really sure what we are protecting against here.  Is it simply DoS
against the SA?

Ira

> --
>
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-14  0:27                                   ` Ira Weiny
  (?)
@ 2016-04-14  0:31                                   ` Ira Weiny
  -1 siblings, 0 replies; 90+ messages in thread
From: Ira Weiny @ 2016-04-14  0:31 UTC (permalink / raw)
  To: Hefty, Sean
  Cc: Hal Rosenstock, Jason Gunthorpe, Daniel Jurgens, selinux,
	linux-security-module, linux-rdma, Yevgeny Petrilin

On Wed, Apr 13, 2016 at 04:47:48PM +0000, Sean Hefty wrote:
> > Former (multicast modifications of fabric) also requires restricting
> > arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
> 
> The SA could have an option to ignore all requests that do not originate QP1,
> then protect access to QP1 on the client nodes.

I'm not really sure what we are protecting against here.  Is it simply DoS
against the SA?

Ira

> --
>
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-14  0:27                                   ` Ira Weiny
@ 2016-04-14  4:22                                     ` Hefty, Sean
  -1 siblings, 0 replies; 90+ messages in thread
From: Hefty, Sean @ 2016-04-14  4:22 UTC (permalink / raw)
  To: Weiny, Ira
  Cc: Hal Rosenstock, Jason Gunthorpe, Daniel Jurgens,
	selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

> > > Former (multicast modifications of fabric) also requires restricting
> > > arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
> >
> > The SA could have an option to ignore all requests that do not originate
> QP1,
> > then protect access to QP1 on the client nodes.
> 
> I'm not really sure what we are protecting against here.  Is it simply DoS
> against the SA?

This would protect against a non-privileged QP trying to change multicast or event subscription, for example.  Though it could help with DoS, by avoiding the processing associated with requests.  Jason's original question was why would you want to leave qp1 open, and I think the answer to that depends on what restrictions could be enforced for qpX: X > 1.  Restricting both seem desirable, IMO.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-14  4:22                                     ` Hefty, Sean
  0 siblings, 0 replies; 90+ messages in thread
From: Hefty, Sean @ 2016-04-14  4:22 UTC (permalink / raw)
  To: Weiny, Ira
  Cc: Hal Rosenstock, Jason Gunthorpe, Daniel Jurgens, selinux,
	linux-security-module, linux-rdma, Yevgeny Petrilin

> > > Former (multicast modifications of fabric) also requires restricting
> > > arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
> >
> > The SA could have an option to ignore all requests that do not originate
> QP1,
> > then protect access to QP1 on the client nodes.
> 
> I'm not really sure what we are protecting against here.  Is it simply DoS
> against the SA?

This would protect against a non-privileged QP trying to change multicast or event subscription, for example.  Though it could help with DoS, by avoiding the processing associated with requests.  Jason's original question was why would you want to leave qp1 open, and I think the answer to that depends on what restrictions could be enforced for qpX: X > 1.  Restricting both seem desirable, IMO.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-14  0:27                                   ` Ira Weiny
@ 2016-04-14 13:06                                     ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-14 13:06 UTC (permalink / raw)
  To: Ira Weiny, Hefty, Sean
  Cc: Hal Rosenstock, Jason Gunthorpe, selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On 4/13/2016 7:27 PM, Ira Weiny wrote:
> On Wed, Apr 13, 2016 at 04:47:48PM +0000, Sean Hefty wrote:
>>> Former (multicast modifications of fabric) also requires restricting
>>> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
>>
>> The SA could have an option to ignore all requests that do not originate QP1,
>> then protect access to QP1 on the client nodes.
> 
> I'm not really sure what we are protecting against here.  Is it simply DoS
> against the SA?
> 
> Ira
> 
>> --
>>
>> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
>> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

A DoS attack against the SA is out of scope for this proposed change.
SELinux provides access control.  Preventing a user from maliciously
doing something you've given them permission to do is a different problem.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-14 13:06                                     ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-14 13:06 UTC (permalink / raw)
  To: Ira Weiny, Hefty, Sean
  Cc: Hal Rosenstock, Jason Gunthorpe, selinux, linux-security-module,
	linux-rdma, Yevgeny Petrilin

On 4/13/2016 7:27 PM, Ira Weiny wrote:
> On Wed, Apr 13, 2016 at 04:47:48PM +0000, Sean Hefty wrote:
>>> Former (multicast modifications of fabric) also requires restricting
>>> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
>>
>> The SA could have an option to ignore all requests that do not originate QP1,
>> then protect access to QP1 on the client nodes.
> 
> I'm not really sure what we are protecting against here.  Is it simply DoS
> against the SA?
> 
> Ira
> 
>> --
>>
>> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

A DoS attack against the SA is out of scope for this proposed change.
SELinux provides access control.  Preventing a user from maliciously
doing something you've given them permission to do is a different problem.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-14  4:22                                     ` Hefty, Sean
@ 2016-04-14 13:11                                       ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-14 13:11 UTC (permalink / raw)
  To: Hefty, Sean, Weiny, Ira
  Cc: Hal Rosenstock, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	Jason Gunthorpe, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA

On 4/13/2016 11:23 PM, Hefty, Sean wrote:
>>>> Former (multicast modifications of fabric) also requires restricting
>>>> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
>>>
>>> The SA could have an option to ignore all requests that do not originate
>> QP1,
>>> then protect access to QP1 on the client nodes.
>>
>> I'm not really sure what we are protecting against here.  Is it simply DoS
>> against the SA?
> 
> This would protect against a non-privileged QP trying to change multicast or event subscription, for example.  Though it could help with DoS, by avoiding the processing associated with requests.  Jason's original question was why would you want to leave qp1 open, and I think the answer to that depends on what restrictions could be enforced for qpX: X > 1.  Restricting both seem desirable, IMO.
> 

There are no qpX to qpX restrictions.  As long as the users that created
both QPs have permission to use the PKey in the PKey index they
specified then they are free to communicate in any way.

_______________________________________________
Selinux mailing list
Selinux-+05T5uksL2qpZYMLLGbcSA@public.gmane.org
To unsubscribe, send email to Selinux-leave-+05T5uksL2pAGbPMOrvdOA@public.gmane.org
To get help, send an email containing "help" to Selinux-request-+05T5uksL2pAGbPMOrvdOA@public.gmane.org

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-14 13:11                                       ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-14 13:11 UTC (permalink / raw)
  To: Hefty, Sean, Weiny, Ira
  Cc: Hal Rosenstock, Jason Gunthorpe, selinux, linux-security-module,
	linux-rdma, Yevgeny Petrilin

On 4/13/2016 11:23 PM, Hefty, Sean wrote:
>>>> Former (multicast modifications of fabric) also requires restricting
>>>> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
>>>
>>> The SA could have an option to ignore all requests that do not originate
>> QP1,
>>> then protect access to QP1 on the client nodes.
>>
>> I'm not really sure what we are protecting against here.  Is it simply DoS
>> against the SA?
> 
> This would protect against a non-privileged QP trying to change multicast or event subscription, for example.  Though it could help with DoS, by avoiding the processing associated with requests.  Jason's original question was why would you want to leave qp1 open, and I think the answer to that depends on what restrictions could be enforced for qpX: X > 1.  Restricting both seem desirable, IMO.
> 

There are no qpX to qpX restrictions.  As long as the users that created
both QPs have permission to use the PKey in the PKey index they
specified then they are free to communicate in any way.

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-14 13:11                                       ` Daniel Jurgens
@ 2016-04-14 16:26                                           ` Ira Weiny
  -1 siblings, 0 replies; 90+ messages in thread
From: Ira Weiny @ 2016-04-14 16:26 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: Hefty, Sean, Hal Rosenstock, Jason Gunthorpe,
	selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

On Thu, Apr 14, 2016 at 01:11:15PM +0000, Daniel Jurgens wrote:
> On 4/13/2016 11:23 PM, Hefty, Sean wrote:
> >>>> Former (multicast modifications of fabric) also requires restricting
> >>>> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
> >>>
> >>> The SA could have an option to ignore all requests that do not originate
> >> QP1,
> >>> then protect access to QP1 on the client nodes.
> >>
> >> I'm not really sure what we are protecting against here.  Is it simply DoS
> >> against the SA?
> > 
> > This would protect against a non-privileged QP trying to change multicast or event subscription, for example.  Though it could help with DoS, by avoiding the processing associated with requests.  Jason's original question was why would you want to leave qp1 open, and I think the answer to that depends on what restrictions could be enforced for qpX: X > 1.  Restricting both seem desirable, IMO.
> > 
> 
> There are no qpX to qpX restrictions.  As long as the users that created
> both QPs have permission to use the PKey in the PKey index they
> specified then they are free to communicate in any way.

For GSI (from 'random' QPs) this seams reasonable.

In InfiniBand, the pkey is ignored in SMPs (those packets on QP0/VL15).  So it
does not really make sense to me to control SMPs via pkey.  (OPA does check
pkeys in SMPs.)

Therefore, I agree with Jason that need to control access to QP0.  Furthermore,
I think you can/should do that when the agent is registered.  This will be more
performant for SMs as well.

For SA/GSI access using umad I think the best control is to limit access to the
umad char device itself?  ibacm has been changed to be an SA cache (with
plugins available for both IB and OPA) and therefore it can run with sufficient
privileges to access the umad char device.  Then regular user applications
don't need umad access at all.

For SA/GSI interactions from 'random' UD QPs, those can be controlled via the
Pkey mechanism you mention above.

If you do add a check on every packet in the mad stack I would like time to
evaluate how that will affect the mad interface for performance.

Ira

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-14 16:26                                           ` Ira Weiny
  0 siblings, 0 replies; 90+ messages in thread
From: Ira Weiny @ 2016-04-14 16:26 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: Hefty, Sean, Hal Rosenstock, Jason Gunthorpe, selinux,
	linux-security-module, linux-rdma, Yevgeny Petrilin

On Thu, Apr 14, 2016 at 01:11:15PM +0000, Daniel Jurgens wrote:
> On 4/13/2016 11:23 PM, Hefty, Sean wrote:
> >>>> Former (multicast modifications of fabric) also requires restricting
> >>>> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
> >>>
> >>> The SA could have an option to ignore all requests that do not originate
> >> QP1,
> >>> then protect access to QP1 on the client nodes.
> >>
> >> I'm not really sure what we are protecting against here.  Is it simply DoS
> >> against the SA?
> > 
> > This would protect against a non-privileged QP trying to change multicast or event subscription, for example.  Though it could help with DoS, by avoiding the processing associated with requests.  Jason's original question was why would you want to leave qp1 open, and I think the answer to that depends on what restrictions could be enforced for qpX: X > 1.  Restricting both seem desirable, IMO.
> > 
> 
> There are no qpX to qpX restrictions.  As long as the users that created
> both QPs have permission to use the PKey in the PKey index they
> specified then they are free to communicate in any way.

For GSI (from 'random' QPs) this seams reasonable.

In InfiniBand, the pkey is ignored in SMPs (those packets on QP0/VL15).  So it
does not really make sense to me to control SMPs via pkey.  (OPA does check
pkeys in SMPs.)

Therefore, I agree with Jason that need to control access to QP0.  Furthermore,
I think you can/should do that when the agent is registered.  This will be more
performant for SMs as well.

For SA/GSI access using umad I think the best control is to limit access to the
umad char device itself?  ibacm has been changed to be an SA cache (with
plugins available for both IB and OPA) and therefore it can run with sufficient
privileges to access the umad char device.  Then regular user applications
don't need umad access at all.

For SA/GSI interactions from 'random' UD QPs, those can be controlled via the
Pkey mechanism you mention above.

If you do add a check on every packet in the mad stack I would like time to
evaluate how that will affect the mad interface for performance.

Ira

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-14 16:26                                           ` Ira Weiny
@ 2016-04-14 16:49                                             ` Daniel Jurgens
  -1 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-14 16:49 UTC (permalink / raw)
  To: Ira Weiny
  Cc: Hal Rosenstock, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	Jason Gunthorpe, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, Hefty, Sean

On 4/14/2016 11:26 AM, Ira Weiny wrote:
> On Thu, Apr 14, 2016 at 01:11:15PM +0000, Daniel Jurgens wrote:
>> On 4/13/2016 11:23 PM, Hefty, Sean wrote:
>>>>>> Former (multicast modifications of fabric) also requires restricting
>>>>>> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
>>>>>
>>>>> The SA could have an option to ignore all requests that do not originate
>>>> QP1,
>>>>> then protect access to QP1 on the client nodes.
>>>>
>>>> I'm not really sure what we are protecting against here.  Is it simply DoS
>>>> against the SA?
>>>
>>> This would protect against a non-privileged QP trying to change multicast or event subscription, for example.  Though it could help with DoS, by avoiding the processing associated with requests.  Jason's original question was why would you want to leave qp1 open, and I think the answer to that depends on what restrictions could be enforced for qpX: X > 1.  Restricting both seem desirable, IMO.
>>>
>>
>> There are no qpX to qpX restrictions.  As long as the users that created
>> both QPs have permission to use the PKey in the PKey index they
>> specified then they are free to communicate in any way.
> 
> For GSI (from 'random' QPs) this seams reasonable.
> 
> In InfiniBand, the pkey is ignored in SMPs (those packets on QP0/VL15).  So it
> does not really make sense to me to control SMPs via pkey.  (OPA does check
> pkeys in SMPs.)
> 
> Therefore, I agree with Jason that need to control access to QP0.  Furthermore,
> I think you can/should do that when the agent is registered.  This will be more
> performant for SMs as well.

QP0 is already controlled, just some naming cleanup there.  Agent
registration is the ideal time to do this, unfortunately security policy
can change at run time, and there's no existing way to destroy a mad
agent from the "bottom up".  I added per MAD checks for that reason.

> For SA/GSI access using umad I think the best control is to limit access to the
> umad char device itself?  ibacm has been changed to be an SA cache (with
> plugins available for both IB and OPA) and therefore it can run with sufficient
> privileges to access the umad char device.  Then regular user applications
> don't need umad access at all.

Denying access for all MADs could be managed via existing filesystem
mechanism.

> For SA/GSI interactions from 'random' UD QPs, those can be controlled via the
> Pkey mechanism you mention above.
> 
> If you do add a check on every packet in the mad stack I would like time to
> evaluate how that will affect the mad interface for performance.

I don't anticipate a large performance impact, due to caching of
security ID's.  I can try to quantify it though.  I don't know of any
MAD performance tests off hand, do have a recommendation?

Thanks,
Dan



_______________________________________________
Selinux mailing list
Selinux-+05T5uksL2qpZYMLLGbcSA@public.gmane.org
To unsubscribe, send email to Selinux-leave-+05T5uksL2pAGbPMOrvdOA@public.gmane.org
To get help, send an email containing "help" to Selinux-request-+05T5uksL2pAGbPMOrvdOA@public.gmane.org

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-14 16:49                                             ` Daniel Jurgens
  0 siblings, 0 replies; 90+ messages in thread
From: Daniel Jurgens @ 2016-04-14 16:49 UTC (permalink / raw)
  To: Ira Weiny
  Cc: Hefty, Sean, Hal Rosenstock, Jason Gunthorpe, selinux,
	linux-security-module, linux-rdma, Yevgeny Petrilin

On 4/14/2016 11:26 AM, Ira Weiny wrote:
> On Thu, Apr 14, 2016 at 01:11:15PM +0000, Daniel Jurgens wrote:
>> On 4/13/2016 11:23 PM, Hefty, Sean wrote:
>>>>>> Former (multicast modifications of fabric) also requires restricting
>>>>>> arbitrary UD QPs as well as QP1 as SA access is QPn (n > 0) <-> QP1.
>>>>>
>>>>> The SA could have an option to ignore all requests that do not originate
>>>> QP1,
>>>>> then protect access to QP1 on the client nodes.
>>>>
>>>> I'm not really sure what we are protecting against here.  Is it simply DoS
>>>> against the SA?
>>>
>>> This would protect against a non-privileged QP trying to change multicast or event subscription, for example.  Though it could help with DoS, by avoiding the processing associated with requests.  Jason's original question was why would you want to leave qp1 open, and I think the answer to that depends on what restrictions could be enforced for qpX: X > 1.  Restricting both seem desirable, IMO.
>>>
>>
>> There are no qpX to qpX restrictions.  As long as the users that created
>> both QPs have permission to use the PKey in the PKey index they
>> specified then they are free to communicate in any way.
> 
> For GSI (from 'random' QPs) this seams reasonable.
> 
> In InfiniBand, the pkey is ignored in SMPs (those packets on QP0/VL15).  So it
> does not really make sense to me to control SMPs via pkey.  (OPA does check
> pkeys in SMPs.)
> 
> Therefore, I agree with Jason that need to control access to QP0.  Furthermore,
> I think you can/should do that when the agent is registered.  This will be more
> performant for SMs as well.

QP0 is already controlled, just some naming cleanup there.  Agent
registration is the ideal time to do this, unfortunately security policy
can change at run time, and there's no existing way to destroy a mad
agent from the "bottom up".  I added per MAD checks for that reason.

> For SA/GSI access using umad I think the best control is to limit access to the
> umad char device itself?  ibacm has been changed to be an SA cache (with
> plugins available for both IB and OPA) and therefore it can run with sufficient
> privileges to access the umad char device.  Then regular user applications
> don't need umad access at all.

Denying access for all MADs could be managed via existing filesystem
mechanism.

> For SA/GSI interactions from 'random' UD QPs, those can be controlled via the
> Pkey mechanism you mention above.
> 
> If you do add a check on every packet in the mad stack I would like time to
> evaluate how that will affect the mad interface for performance.

I don't anticipate a large performance impact, due to caching of
security ID's.  I can try to quantify it though.  I don't know of any
MAD performance tests off hand, do have a recommendation?

Thanks,
Dan

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
  2016-04-14 16:49                                             ` Daniel Jurgens
@ 2016-04-14 21:58                                                 ` Ira Weiny
  -1 siblings, 0 replies; 90+ messages in thread
From: Ira Weiny @ 2016-04-14 21:58 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: Hefty, Sean, Hal Rosenstock, Jason Gunthorpe,
	selinux-+05T5uksL2qpZYMLLGbcSA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, Yevgeny Petrilin

> > 
> > If you do add a check on every packet in the mad stack I would like time to
> > evaluate how that will affect the mad interface for performance.
> 
> I don't anticipate a large performance impact, due to caching of
> security ID's.  I can try to quantify it though.  I don't know of any
> MAD performance tests off hand, do have a recommendation?

Unfortunately I don't have any that are public.

Ira

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA
@ 2016-04-14 21:58                                                 ` Ira Weiny
  0 siblings, 0 replies; 90+ messages in thread
From: Ira Weiny @ 2016-04-14 21:58 UTC (permalink / raw)
  To: Daniel Jurgens
  Cc: Hefty, Sean, Hal Rosenstock, Jason Gunthorpe, selinux,
	linux-security-module, linux-rdma, Yevgeny Petrilin

> > 
> > If you do add a check on every packet in the mad stack I would like time to
> > evaluate how that will affect the mad interface for performance.
> 
> I don't anticipate a large performance impact, due to caching of
> security ID's.  I can try to quantify it though.  I don't know of any
> MAD performance tests off hand, do have a recommendation?

Unfortunately I don't have any that are public.

Ira

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

end of thread, other threads:[~2016-04-14 21:58 UTC | newest]

Thread overview: 90+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-06 23:33 [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA Dan Jurgens
     [not found] ` <1459985638-37233-1-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-04-06 23:33   ` [RFC PATCH v2 01/13] security: Add LSM hooks for Infiniband security Dan Jurgens
2016-04-06 23:33   ` [RFC PATCH v2 02/13] selinux: Create policydb version for Infiniband support Dan Jurgens
2016-04-06 23:33   ` [RFC PATCH v2 03/13] selinux: Implement Infiniband flush callback Dan Jurgens
2016-04-06 23:33   ` [RFC PATCH v2 04/13] selinux: Allocate and free infiniband security hooks Dan Jurgens
     [not found]     ` <1459985638-37233-5-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-04-11 15:24       ` Casey Schaufler
2016-04-11 15:24         ` Casey Schaufler
2016-04-11 20:41         ` Daniel Jurgens
2016-04-06 23:33   ` [RFC PATCH v2 05/13] selinux: Implement Infiniband PKey "Access" access vector Dan Jurgens
2016-04-06 23:33   ` [RFC PATCH v2 06/13] selinux: Add IB Device SMI " Dan Jurgens
2016-04-06 23:33   ` [RFC PATCH v2 09/13] ib/core: Enforce PKey security when modifying QPs Dan Jurgens
     [not found]     ` <1459985638-37233-10-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-04-07 16:31       ` Leon Romanovsky
2016-04-07 16:31         ` Leon Romanovsky
2016-04-07 17:03         ` Daniel Jurgens
2016-04-07 17:03           ` Daniel Jurgens
     [not found]           ` <DB5PR05MB111169883324ADC42E52C4D6C4900-8IvNv+8VlcBJTpKhoUy7I9qRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-04-07 17:39             ` leon-2ukJVAZIZ/Y
2016-04-07 17:39               ` leon
2016-04-07 17:44               ` Daniel Jurgens
2016-04-07 17:44                 ` Daniel Jurgens
2016-04-07 21:02         ` Daniel Jurgens
2016-04-07 21:02           ` Daniel Jurgens
     [not found]           ` <DB5PR05MB11113874870EBBE896E0D601C4900-8IvNv+8VlcBJTpKhoUy7I9qRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-04-07 21:10             ` leon-2ukJVAZIZ/Y
2016-04-07 21:10               ` leon
2016-04-07 21:23               ` Daniel Jurgens
2016-04-07 21:23                 ` Daniel Jurgens
     [not found]                 ` <DB5PR05MB11115DF816F6CEAD7738201EC4900-8IvNv+8VlcBJTpKhoUy7I9qRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-04-07 23:24                   ` leon-2ukJVAZIZ/Y
2016-04-07 23:24                     ` leon
2016-04-06 23:33   ` [RFC PATCH v2 10/13] ib/core: Enforce PKey security on management datagrams Dan Jurgens
     [not found]     ` <1459985638-37233-11-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-04-07 20:39       ` Leon Romanovsky
2016-04-07 20:39         ` Leon Romanovsky
2016-04-06 23:33   ` [RFC PATCH v2 12/13] ib/core: Track which QPs are using which port and PKey index Dan Jurgens
     [not found]     ` <1459985638-37233-13-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-04-07 20:53       ` Leon Romanovsky
2016-04-07 20:53         ` Leon Romanovsky
2016-04-06 23:33   ` [RFC PATCH v2 13/13] ib/core: Implement the Infiniband flush callback Dan Jurgens
2016-04-11 20:11   ` [RFC PATCH v2 00/13] SELinux support for Infiniband RDMA Jason Gunthorpe
2016-04-11 20:11     ` Jason Gunthorpe
2016-04-11 20:38     ` Daniel Jurgens
2016-04-11 20:38       ` Daniel Jurgens
     [not found]       ` <DB5PR05MB111168B6670B36F12979705BC4940-8IvNv+8VlcBJTpKhoUy7I9qRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-04-11 22:12         ` Jason Gunthorpe
2016-04-11 22:12           ` Jason Gunthorpe
2016-04-11 22:30           ` Daniel Jurgens
2016-04-11 22:30             ` Daniel Jurgens
     [not found]             ` <DB5PR05MB1111E6A72480FF78AAB12747C4940-8IvNv+8VlcBJTpKhoUy7I9qRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-04-11 23:12               ` Jason Gunthorpe
2016-04-11 23:12                 ` Jason Gunthorpe
2016-04-11 23:35                 ` Daniel Jurgens
2016-04-11 23:35                   ` Daniel Jurgens
2016-04-12  0:06                   ` Jason Gunthorpe
     [not found]                     ` <20160412000621.GD5861-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-04-12  5:21                       ` Hal Rosenstock
2016-04-12  5:21                         ` Hal Rosenstock
2016-04-12 17:06                         ` Hefty, Sean
2016-04-12 17:58                           ` Jason Gunthorpe
     [not found]                             ` <20160412175837.GA15027-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-04-13 12:09                               ` Hal Rosenstock
2016-04-13 12:09                                 ` Hal Rosenstock
2016-04-13 13:17                                 ` Daniel Jurgens
2016-04-13 13:17                                   ` Daniel Jurgens
2016-04-13  5:07                           ` Hal Rosenstock
2016-04-13 16:47                             ` Hefty, Sean
     [not found]                               ` <1828884A29C6694DAF28B7E6B8A82373AB041285-P5GAC/sN6hkd3b2yrw5b5LfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2016-04-14  0:27                                 ` Ira Weiny
2016-04-14  0:27                                   ` Ira Weiny
2016-04-14  0:31                                   ` Ira Weiny
2016-04-14  4:22                                   ` Hefty, Sean
2016-04-14  4:22                                     ` Hefty, Sean
2016-04-14 13:11                                     ` Daniel Jurgens
2016-04-14 13:11                                       ` Daniel Jurgens
     [not found]                                       ` <AM2PR05MB1105E03BDEE8ED9552C8EDE7C4970-Wc3DjHnhGidZ7IXwgIC3xtqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-04-14 16:26                                         ` Ira Weiny
2016-04-14 16:26                                           ` Ira Weiny
2016-04-14 16:49                                           ` Daniel Jurgens
2016-04-14 16:49                                             ` Daniel Jurgens
     [not found]                                             ` <AM2PR05MB11059E1985CE6544FAE4BA00C4970-Wc3DjHnhGidZ7IXwgIC3xtqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-04-14 21:58                                               ` Ira Weiny
2016-04-14 21:58                                                 ` Ira Weiny
2016-04-14 13:06                                   ` Daniel Jurgens
2016-04-14 13:06                                     ` Daniel Jurgens
2016-04-12 16:45                     ` Daniel Jurgens
2016-04-12 16:45                       ` Daniel Jurgens
2016-04-12  5:12                   ` Hal Rosenstock
2016-04-12 16:43                     ` Daniel Jurgens
2016-04-12 16:43                       ` Daniel Jurgens
2016-04-06 23:33 ` [RFC PATCH v2 07/13] selinux: Add a cache for quicker retreival of PKey SIDs Dan Jurgens
2016-04-06 23:33 ` [RFC PATCH v2 08/13] ib/core: IB cache enhancements to support Infiniband security Dan Jurgens
     [not found]   ` <1459985638-37233-9-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-04-07  2:53     ` Leon Romanovsky
2016-04-07  2:53       ` Leon Romanovsky
2016-04-07 15:43       ` Daniel Jurgens
2016-04-07 15:43         ` Daniel Jurgens
2016-04-07 15:09     ` Leon Romanovsky
2016-04-07 15:09       ` Leon Romanovsky
2016-04-06 23:33 ` [RFC PATCH v2 11/13] ib/core: Enforce Infiniband device SMI security Dan Jurgens
     [not found]   ` <1459985638-37233-12-git-send-email-danielj-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-04-07 20:44     ` Leon Romanovsky
2016-04-07 20:44       ` Leon Romanovsky
2016-04-07 21:55       ` Daniel Jurgens
2016-04-07 21:55         ` Daniel 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.